Skip to content

SDK-6103 Added support for My Account API. #847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

utkrishtsahu
Copy link
Contributor

This PR introduces new sets of API for the MyAccount feature .

Checklist
I have read the Auth0 general contribution guidelines

I have read the Auth0 Code of Conduct

All existing and new tests complete without errors

@utkrishtsahu utkrishtsahu requested a review from a team as a code owner July 21, 2025 03:47
Comment on lines +17 to +32
internal class Deserializer : JsonDeserializer<EnrollmentChallenge> {
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): EnrollmentChallenge? {
val jsonObject = json.asJsonObject
val targetClass = when {
jsonObject.has("barcode_uri") -> TotpEnrollmentChallenge::class.java
jsonObject.has("recovery_code") -> RecoveryCodeEnrollmentChallenge::class.java
jsonObject.has("authn_params_public_key") -> PasskeyEnrollmentChallenge::class.java
else -> MfaEnrollmentChallenge::class.java
}
return context.deserialize(jsonObject, targetClass)
}
}

Check notice

Code scanning / CodeQL

Unused classes and interfaces Note

Unused class: Deserializer is not referenced within this codebase. If not used as an external API it should be removed.

Copilot Autofix

AI 3 days ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

* You can use the refresh token to get an access token for the My Account API. Refer to [com.auth0.android.authentication.storage.CredentialsManager.getApiCredentials]
* , or alternatively [com.auth0.android.authentication.AuthenticationAPIClient.renewAuth] if you are not using CredentialsManager.
* You can use a refresh token to get an access token for the My Account API.
* Refer to `CredentialsManager#getApiCredentials` or `AuthenticationAPIClient#renewAuth`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the comment changed ? Ensure the comments convey as much detail as possible including samples wherever applicable

*
* ## Usage
* ```kotlin
* val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
* val client = MyAccountAPIClient(auth0,accessToken)
* val auth0 = Auth0("YOUR_CLIENT_ID", "YOUR_DOMAIN")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN") is the correct way to access an Auth0 instance . Please correct in the comment

public fun updateAuthenticationMethodById(
authenticationMethodId: String,
preferredAuthenticationMethod: String,
authenticationMethodName: String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are optional parameters

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make them as optional .Check with @NandanPrabhu

jsonObject.has("barcode_uri") -> TotpEnrollmentChallenge::class.java
jsonObject.has("recovery_code") -> RecoveryCodeEnrollmentChallenge::class.java
jsonObject.has("authn_params_public_key") -> PasskeyEnrollmentChallenge::class.java
else -> MfaEnrollmentChallenge::class.java
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does these 4 options cover all the response scenarios as per the OAS ?

public val recoveryCode: String
) : EnrollmentChallenge(id, authSession)

public data class PublicKeyCredentialCreationOptions(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a duplicate of AuthnParamsPublicKey data class in the PasskeyRegistrationChallenge.kt file

public val identityUserId: String?
) : EnrollmentPayload("passkey")

public data class WebAuthnPlatformEnrollmentPayload(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a normal class ?

public class WebAuthnPlatformEnrollmentPayload() : EnrollmentPayload("webauthn-roaming") 

This way you don't have to add an empty placeholder for the data class


public data class WebAuthnRoamingEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("webauthn-roaming")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above


public data class TotpEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("totp")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

) : EnrollmentPayload("totp")

public data class PushNotificationEnrollmentPayload(
private val placeholder: String? = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

) : EnrollmentPayload("push-notification")

public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

public typealias PasskeyAuthenticationMethod = AuthenticationMethod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AuthenticationMethod data class has some mandatory property like usage which the passkeys response might not send . Please cross check them and test this to avoid run time crashes

)
public val authenticationMethodId: String,
public val authSession: String,
public val authParamsPublicKey: AuthnParamsPublicKey
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are the serialized names removed ?

import com.auth0.android.request.JsonAdapter
import com.auth0.android.request.PublicKeyCredentials
import com.auth0.android.request.Request
import com.auth0.android.request.*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please configure your IDE to have specific imports instead of generic one

*/
public fun updateAuthenticationMethodById(
authenticationMethodId: String,
preferredAuthenticationMethod: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets limit the preferredAuthenticationMethod type to the accepted values of sms and voice . Lets use an enum type here with string default value

* val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN")
* val apiClient = MyAccountAPIClient(auth0, accessToken)
*
* apiClient.getFactors()
Copy link
Contributor

@pmathew92 pmathew92 Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format the code samples as these are client facing

* val apiClient = MyAccountAPIClient(auth0, accessToken)
*
* apiClient.enrollPhone("+11234567890", "sms")
* .start(object : Callback<EnrollmentChallenge, MyAccountException> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format the code samples

* @param preferredMethod The preferred method for this factor ("sms" or "voice").
* @return a request that will yield an enrollment challenge.
*/
public fun enrollPhone(phoneNumber: String, preferredMethod: String): Request<EnrollmentChallenge, MyAccountException> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed above ,lets have the preferred method as an enum type

@pmathew92 pmathew92 requested a review from Copilot August 19, 2025 05:20
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces comprehensive support for the My Account API, adding new functionality for managing authentication methods and factors beyond the existing passkey support.

Key changes include:

  • Addition of new authentication method management APIs (CRUD operations)
  • Support for enrolling various factor types (email, phone, TOTP, recovery codes, push notifications)
  • Introduction of new data models to support different authentication method types
  • Consolidation of existing passkey-specific classes into more general authentication method structures

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
MyAccountAPIClientTest.kt Updated test suite to include comprehensive tests for new API endpoints and removed redundant passkey-specific tests
MyAccountAPIClient.kt Added new API methods for authentication method management and factor enrollment
AuthenticationMethod.kt New unified data model for all authentication method types
EnrollmentChallenge.kt New sealed class hierarchy for different enrollment challenge types
EnrollmentPayload.kt New sealed class for various enrollment request payloads
Factors.kt New data model for factor listings
Factor.kt New data model representing individual factors
ErrorResponse.kt New standardized error response model
VerificationPayload.kt New data model for verification requests
PasskeyAuthenticationMethod.kt Converted to type alias pointing to general AuthenticationMethod
PasskeyEnrollmentChallenge.kt Simplified to remove serialization annotations

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("recovery-code")
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using placeholder parameters in data classes is not a good practice. Consider using object declarations for payload types that don't need additional properties, or remove these placeholder fields entirely.

Suggested change
) : EnrollmentPayload("recovery-code")
public object WebAuthnPlatformEnrollmentPayload : EnrollmentPayload("webauthn-platform")
public object WebAuthnRoamingEnrollmentPayload : EnrollmentPayload("webauthn-roaming")
public object TotpEnrollmentPayload : EnrollmentPayload("totp")
public object PushNotificationEnrollmentPayload : EnrollmentPayload("push-notification")
public object RecoveryCodeEnrollmentPayload : EnrollmentPayload("recovery-code")

Copilot uses AI. Check for mistakes.


public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("recovery-code")
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using placeholder parameters in data classes is not a good practice. Consider using object declarations for payload types that don't need additional properties, or remove these placeholder fields entirely.

Suggested change
) : EnrollmentPayload("recovery-code")
public object WebAuthnPlatformEnrollmentPayload : EnrollmentPayload("webauthn-platform")
public object WebAuthnRoamingEnrollmentPayload : EnrollmentPayload("webauthn-roaming")
public object TotpEnrollmentPayload : EnrollmentPayload("totp")
public object PushNotificationEnrollmentPayload : EnrollmentPayload("push-notification")
public object RecoveryCodeEnrollmentPayload : EnrollmentPayload("recovery-code")

Copilot uses AI. Check for mistakes.


public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("recovery-code")
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using placeholder parameters in data classes is not a good practice. Consider using object declarations for payload types that don't need additional properties, or remove these placeholder fields entirely.

Suggested change
) : EnrollmentPayload("recovery-code")
public object WebAuthnPlatformEnrollmentPayload : EnrollmentPayload("webauthn-platform")
public object WebAuthnRoamingEnrollmentPayload : EnrollmentPayload("webauthn-roaming")
public object TotpEnrollmentPayload : EnrollmentPayload("totp")
public object PushNotificationEnrollmentPayload : EnrollmentPayload("push-notification")
public object RecoveryCodeEnrollmentPayload : EnrollmentPayload("recovery-code")

Copilot uses AI. Check for mistakes.


public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("recovery-code")
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using placeholder parameters in data classes is not a good practice. Consider using object declarations for payload types that don't need additional properties, or remove these placeholder fields entirely.

Suggested change
) : EnrollmentPayload("recovery-code")
public object WebAuthnPlatformEnrollmentPayload : EnrollmentPayload("webauthn-platform")
public object WebAuthnRoamingEnrollmentPayload : EnrollmentPayload("webauthn-roaming")
public object TotpEnrollmentPayload : EnrollmentPayload("totp")
public object PushNotificationEnrollmentPayload : EnrollmentPayload("push-notification")
public object RecoveryCodeEnrollmentPayload : EnrollmentPayload("recovery-code")

Copilot uses AI. Check for mistakes.


public data class RecoveryCodeEnrollmentPayload(
private val placeholder: String? = null
) : EnrollmentPayload("recovery-code")
Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using placeholder parameters in data classes is not a good practice. Consider using object declarations for payload types that don't need additional properties, or remove these placeholder fields entirely.

Suggested change
) : EnrollmentPayload("recovery-code")
public object WebAuthnPlatformEnrollmentPayload : EnrollmentPayload("webauthn-platform")
public object WebAuthnRoamingEnrollmentPayload : EnrollmentPayload("webauthn-roaming")
public object TotpEnrollmentPayload : EnrollmentPayload("totp")
public object PushNotificationEnrollmentPayload : EnrollmentPayload("push-notification")
public object RecoveryCodeEnrollmentPayload : EnrollmentPayload("recovery-code")

Copilot uses AI. Check for mistakes.

package com.auth0.android.result

import com.google.gson.annotations.SerializedName

Copy link
Preview

Copilot AI Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Factor class lacks documentation. Public data classes should have KDoc comments explaining their purpose and properties.

Suggested change
/**
* Represents a multi-factor authentication factor.
*
* @property type The type of factor (e.g., "totp", "sms", etc.).
* @property usage The usages supported by this factor (e.g., "authentication", "recovery"). May be null.
*/

Copilot uses AI. Check for mistakes.

@SerializedName("barcode_uri")
public val barcodeUri: String,
@SerializedName("manual_input_code")
public val manualInputCode: String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manualInputCode must be optional.we dont get it incase of push notification factor

*/
public fun updateAuthenticationMethodById(
authenticationMethodId: String,
authenticationMethodName: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name and preferredAuthenticationMethod can be updated together or one at a time. So we need to make both of them optional

* ```
*
*/
public fun getAuthenticationMethods(): Request<AuthenticationMethods, MyAccountException> {
Copy link
Contributor

@pmathew92 pmathew92 Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NandanPrabhu @utkrishtsahu Would it be more Dx friendly if we return List here ? With this now the user has to result.list[index] to access an AuthenticationMethod . Just returning the list will be easier I think. Returning a list will also be easy when we add support for Pagination and would be easier. Let me know your thoughts

url.toString(),
GsonAdapter(AuthenticationMethods::class.java)
)
.addHeader(AUTHORIZATION_KEY, "Bearer $accessToken")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach will change once DPoP support is added to MyAccountAPIs. Just an heads up on the same

* val apiClient = MyAccountAPIClient(auth0, accessToken)
*
*
* apiClient.deleteAuthenticationMethod(authenticationMethodId, )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: It should be apiClient.deleteAuthenticationMethod(authenticationMethodId )

* ```
* @return A request to get the list of available factors.
*/
public fun getFactors(): Request<Factors, MyAccountException> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type can be List<Factor> instead of Factors as discussed above

@@ -56,262 +52,177 @@ public class MyAccountAPIClientTest {
assertThat(request.path, Matchers.equalTo("/me/v1/authentication-methods"))
}

@Test
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these cases removed ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants