@@ -167,7 +167,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
167167 * ```
168168 * client.signinWithPasskey("{authSession}", "{authResponse}","{realm}")
169169 * .validateClaims() //mandatory
170- * .addParameter(" scope","scope ")
170+ * .setScope("{ scope} ")
171171 * .start(object: Callback<Credentials, AuthenticationException> {
172172 * override fun onFailure(error: AuthenticationException) { }
173173 * override fun onSuccess(result: Credentials) { }
@@ -211,7 +211,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
211211 * ```
212212 * client.signinWithPasskey("{authSession}", "{authResponse}","{realm}")
213213 * .validateClaims() //mandatory
214- * .addParameter(" scope","scope ")
214+ * .setScope("{ scope} ")
215215 * .start(object: Callback<Credentials, AuthenticationException> {
216216 * override fun onFailure(error: AuthenticationException) { }
217217 * override fun onSuccess(result: Credentials) { }
@@ -457,13 +457,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
457457 * @return a request to configure and start that will yield [Credentials]
458458 */
459459 public fun loginWithNativeSocialToken (token : String , tokenType : String ): AuthenticationRequest {
460- val parameters = ParameterBuilder .newAuthenticationBuilder()
461- .setGrantType(ParameterBuilder .GRANT_TYPE_TOKEN_EXCHANGE )
462- .setClientId(clientId)
463- .set(SUBJECT_TOKEN_KEY , token)
464- .set(SUBJECT_TOKEN_TYPE_KEY , tokenType)
465- .asDictionary()
466- return loginWithToken(parameters)
460+ return tokenExchange(tokenType, token)
467461 }
468462
469463 /* *
@@ -707,6 +701,34 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
707701 .addParameters(parameters)
708702 }
709703
704+ /* *
705+ * The Custom Token Exchange feature allows clients to exchange their existing tokens for Auth0 tokens by calling the `/oauth/token` endpoint with specific parameters.
706+ * The default scope used is 'openid profile email'.
707+ *
708+ * Example usage:
709+ *
710+ * ```
711+ * client.customTokenExchange("{subject token type}", "{subject token}")
712+ * .validateClaims() //mandatory
713+ * .setScope("{scope}")
714+ * .setAudience("{audience}")
715+ * .start(object: Callback<Credentials, AuthenticationException> {
716+ * override fun onSuccess(result: Credentials) { }
717+ * override fun onFailure(error: AuthenticationException) { }
718+ * })
719+ * ```
720+ *
721+ * @param subjectTokenType the subject token type that is associated with the existing Identity Provider. e.g. 'http://acme.com/legacy-token'
722+ * @param subjectToken the subject token, typically obtained through the Identity Provider's SDK
723+ * @return a request to configure and start that will yield [Credentials]
724+ */
725+ public fun customTokenExchange (
726+ subjectTokenType : String ,
727+ subjectToken : String ,
728+ ): AuthenticationRequest {
729+ return tokenExchange(subjectTokenType, subjectToken)
730+ }
731+
710732 /* *
711733 * Requests new Credentials using a valid Refresh Token. The received token will have the same audience and scope as first requested.
712734 *
@@ -922,6 +944,21 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
922944 return request
923945 }
924946
947+ /* *
948+ * Helper function to make a request to the /oauth/token endpoint with the token exchange grant type.
949+ */
950+ private fun tokenExchange (
951+ subjectTokenType : String ,
952+ subjectToken : String
953+ ): AuthenticationRequest {
954+ val parameters = ParameterBuilder .newAuthenticationBuilder()
955+ .setGrantType(ParameterBuilder .GRANT_TYPE_TOKEN_EXCHANGE )
956+ .set(SUBJECT_TOKEN_TYPE_KEY , subjectTokenType)
957+ .set(SUBJECT_TOKEN_KEY , subjectToken)
958+ .asDictionary()
959+ return loginWithToken(parameters)
960+ }
961+
925962 private fun profileRequest (): Request <UserProfile , AuthenticationException > {
926963 val url =
927964 auth0.getDomainUrl().toHttpUrl().newBuilder()
0 commit comments