@@ -299,7 +299,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
299299
300300 val request = factory.get(
301301 url.toString(),
302- GsonAdapter (AuthenticationMethods ::class .java)
302+ GsonAdapter (AuthenticationMethods ::class .java, gson )
303303 )
304304 .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
305305
@@ -348,7 +348,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
348348
349349 val request = factory.get(
350350 url.toString(),
351- GsonAdapter (AuthenticationMethod ::class .java)
351+ GsonAdapter (AuthenticationMethod ::class .java, gson )
352352 )
353353 .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
354354
@@ -407,7 +407,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
407407
408408 val request = factory.patch(
409409 url.toString(),
410- GsonAdapter (AuthenticationMethod ::class .java)
410+ GsonAdapter (AuthenticationMethod ::class .java, gson )
411411 )
412412 .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
413413 .addParameters(params)
@@ -452,16 +452,20 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
452452 */
453453 public fun deleteAuthenticationMethod (
454454 authenticationMethodId : String
455- ): Request <Void , MyAccountException > {
455+ ): Request <Void ? , MyAccountException > {
456456 val url =
457457 getDomainUrlBuilder()
458458 .addPathSegment(AUTHENTICATION_METHODS )
459459 .addPathSegment(authenticationMethodId)
460460 .build()
461461
462- val request = factory.delete(url.toString(), GsonAdapter (Void ::class .java))
462+ val voidAdapter = object : JsonAdapter <Void ?> {
463+ override fun fromJson (reader : Reader , metadata : Map <String , Any >): Void ? {
464+ return null
465+ }
466+ }
467+ val request = factory.delete(url.toString(), voidAdapter)
463468 .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
464-
465469 return request
466470 }
467471
@@ -504,6 +508,217 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
504508 .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
505509 }
506510
511+ /* *
512+ * Starts the enrollment of a phone authentication method.
513+ *
514+ * ## Scopes Required
515+ * `create:me:authentication_methods`
516+ *
517+ * ## Usage
518+ *
519+ * ```kotlin
520+ * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
521+ * val apiClient = MyAccountAPIClient(auth0, accessToken)
522+ *
523+ * apiClient.enrollPhone("+11234567890", "sms")
524+ * .start(object : Callback<EnrollmentChallenge, MyAccountException> {
525+ * override fun onSuccess(result: EnrollmentChallenge) {
526+ * // The enrollment has started. 'result.id' contains the ID for verification.
527+ * Log.d("MyApp", "Enrollment started. ID: ${result.id}")
528+ * }
529+ * override fun onFailure(error: MyAccountException) {
530+ * Log.e("MyApp", "Failed with: ${error.message}")
531+ * }
532+ * })
533+ * ```
534+ * @param phoneNumber The phone number to enroll in E.164 format.
535+ * @param preferredMethod The preferred method for this factor ("sms" or "voice").
536+ * @return a request that will yield an enrollment challenge.
537+ */
538+ public fun enrollPhone (phoneNumber : String , preferredMethod : String ): Request <EnrollmentChallenge , MyAccountException > {
539+ val url = getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build()
540+ val params = ParameterBuilder .newBuilder()
541+ .set(TYPE_KEY , " phone" )
542+ .set(PHONE_NUMBER_KEY , phoneNumber)
543+ .set(PREFERRED_AUTHENTICATION_METHOD , preferredMethod)
544+ .asDictionary()
545+ return factory.post(url.toString(), GsonAdapter (EnrollmentChallenge ::class .java, gson))
546+ .addParameters(params)
547+ .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
548+ }
549+
550+ /* *
551+ * Starts the enrollment of an email authentication method.
552+ *
553+ * ## Scopes Required
554+ * `create:me:authentication_methods`
555+ *
556+ * ## Usage
557+ *
558+ * ```kotlin
559+ * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
560+ * val apiClient = MyAccountAPIClient(auth0, accessToken)
561+ *
562+ * apiClient.enrollEmail("[email protected] ") 563+ * .start(object : Callback<EnrollmentChallenge, MyAccountException> {
564+ * override fun onSuccess(result: EnrollmentChallenge) {
565+ * // The enrollment has started. 'result.id' contains the ID for verification.
566+ * Log.d("MyApp", "Enrollment started. ID: ${result.id}")
567+ * }
568+ * override fun onFailure(error: MyAccountException) {
569+ * Log.e("MyApp", "Failed with: ${error.message}")
570+ * }
571+ * })
572+ * ```
573+ * @param email the email address to enroll.
574+ * @return a request that will yield an enrollment challenge.
575+ */
576+ public fun enrollEmail (email : String ): Request <EnrollmentChallenge , MyAccountException > {
577+ val url = getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build()
578+ val params = ParameterBuilder .newBuilder()
579+ .set(TYPE_KEY , " email" )
580+ .set(EMAIL_KEY , email)
581+ .asDictionary()
582+ return factory.post(url.toString(), GsonAdapter (EnrollmentChallenge ::class .java, gson))
583+ .addParameters(params)
584+ .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
585+ }
586+
587+
588+ /* *
589+ * Confirms the enrollment of a phone, email, or TOTP method by providing the one-time password (OTP).
590+ *
591+ * ## Scopes Required
592+ * `create:me:authentication_methods`
593+ *
594+ * ## Usage
595+ *
596+ * ```kotlin
597+ * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
598+ * val apiClient = MyAccountAPIClient(auth0, accessToken)
599+ *
600+ * val authMethodId = "from_enrollment_challenge"
601+ * val otp = "123456"
602+ *
603+ * apiClient.verifyOtp(authMethodId, otp)
604+ * .start(object : Callback<AuthenticationMethod, MyAccountException> {
605+ * override fun onSuccess(result: AuthenticationMethod) {
606+ * Log.d("MyApp", "Successfully verified method: ${result.id}")
607+ * }
608+ * override fun onFailure(error: MyAccountException) { //... }
609+ * })
610+ * ```
611+ * @param authenticationMethodId The ID of the method being verified (from the enrollment challenge).
612+ * @param otpCode The OTP code sent to the user's phone or email, or from their authenticator app.
613+ * @return a request that will yield the newly verified authentication method.
614+ */
615+ public fun verifyOtp (authenticationMethodId : String , otpCode : String ): Request <AuthenticationMethod , MyAccountException > {
616+ val url = getDomainUrlBuilder()
617+ .addPathSegment(AUTHENTICATION_METHODS )
618+ .addPathSegment(authenticationMethodId)
619+ .addPathSegment(VERIFY )
620+ .build()
621+ val params = mapOf (" otp_code" to otpCode)
622+ return factory.post(url.toString(), GsonAdapter (AuthenticationMethod ::class .java, gson))
623+ .addParameters(params)
624+ .addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
625+ }
626+
627+ /* *
628+ * Starts the enrollment of a TOTP (authenticator app) method.
629+ *
630+ * ## Scopes Required
631+ * `create:me:authentication_methods`
632+ *
633+ * ## Usage
634+ *
635+ * ```kotlin
636+ * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
637+ * val apiClient = MyAccountAPIClient(auth0, accessToken)
638+ *
639+ * apiClient.enrollTotp()
640+ * .start(object : Callback<EnrollmentChallenge, MyAccountException> {
641+ * override fun onSuccess(result: EnrollmentChallenge) {
642+ * // The result will be a TotpEnrollmentChallenge with a barcode_uri
643+ * Log.d("MyApp", "Enrollment started for TOTP.")
644+ * }
645+ * override fun onFailure(error: MyAccountException) { //... }
646+ * })
647+ * ```
648+ * @return a request that will yield an enrollment challenge.
649+ */
650+ public fun enrollTotp (): Request <EnrollmentChallenge , MyAccountException > {
651+ val params = ParameterBuilder .newBuilder().set(TYPE_KEY , " totp" ).asDictionary()
652+ return factory.post(
653+ getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build().toString(),
654+ GsonAdapter (EnrollmentChallenge ::class .java, gson)
655+ ).addParameters(params).addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
656+ }
657+
658+ /* *
659+ * Starts the enrollment of a WebAuthn Platform (e.g., biometrics) authenticator.
660+ *
661+ * ## Scopes Required
662+ * `create:me:authentication_methods`
663+ *
664+ * @return a request that will yield an enrollment challenge.
665+ */
666+ public fun enrollWebAuthnPlatform (): Request <EnrollmentChallenge , MyAccountException > {
667+ val params = ParameterBuilder .newBuilder().set(TYPE_KEY , " webauthn-platform" ).asDictionary()
668+ return factory.post(
669+ getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build().toString(),
670+ GsonAdapter (EnrollmentChallenge ::class .java, gson)
671+ ).addParameters(params).addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
672+ }
673+
674+ /* *
675+ * Starts the enrollment of a WebAuthn Roaming (e.g., security key) authenticator.
676+ *
677+ * ## Scopes Required
678+ * `create:me:authentication_methods`
679+ *
680+ * @return a request that will yield an enrollment challenge.
681+ */
682+ public fun enrollWebAuthnRoaming (): Request <EnrollmentChallenge , MyAccountException > {
683+ val params = ParameterBuilder .newBuilder().set(TYPE_KEY , " webauthn-roaming" ).asDictionary()
684+ return factory.post(
685+ getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build().toString(),
686+ GsonAdapter (EnrollmentChallenge ::class .java, gson)
687+ ).addParameters(params).addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
688+ }
689+
690+ /* *
691+ * Starts the enrollment of a Push Notification authenticator.
692+ *
693+ * ## Scopes Required
694+ * `create:me:authentication_methods`
695+ *
696+ * @return a request that will yield an enrollment challenge.
697+ */
698+ public fun enrollPushNotification (): Request <EnrollmentChallenge , MyAccountException > {
699+ val params = ParameterBuilder .newBuilder().set(TYPE_KEY , " push-notification" ).asDictionary()
700+ return factory.post(
701+ getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build().toString(),
702+ GsonAdapter (EnrollmentChallenge ::class .java, gson)
703+ ).addParameters(params).addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
704+ }
705+
706+ /* *
707+ * Starts the enrollment of a Recovery Code authenticator.
708+ *
709+ * ## Scopes Required
710+ * `create:me:authentication_methods`
711+ *
712+ * @return a request that will yield an enrollment challenge containing the recovery code.
713+ */
714+ public fun enrollRecoveryCode (): Request <EnrollmentChallenge , MyAccountException > {
715+ val params = ParameterBuilder .newBuilder().set(TYPE_KEY , " recovery-code" ).asDictionary()
716+ return factory.post(
717+ getDomainUrlBuilder().addPathSegment(AUTHENTICATION_METHODS ).build().toString(),
718+ GsonAdapter (EnrollmentChallenge ::class .java, gson)
719+ ).addParameters(params).addHeader(AUTHORIZATION_KEY , " Bearer $accessToken " )
720+ }
721+
507722 private fun getDomainUrlBuilder (): HttpUrl .Builder {
508723 return auth0.getDomainUrl().toHttpUrl().newBuilder()
509724 .addPathSegment(ME_PATH )
@@ -526,6 +741,9 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting
526741 private const val PREFERRED_AUTHENTICATION_METHOD = " preferred_authentication_method"
527742 private const val AUTHENTICATION_METHOD_NAME = " name"
528743 private const val FACTORS = " factors"
744+ private const val PHONE_NUMBER_KEY = " phone_number"
745+ private const val EMAIL_KEY = " email"
746+
529747 private fun createErrorAdapter (): ErrorAdapter <MyAccountException > {
530748 val mapAdapter = forMap(GsonProvider .gson)
531749 return object : ErrorAdapter <MyAccountException > {
0 commit comments