-
Notifications
You must be signed in to change notification settings - Fork 159
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
base: main
Are you sure you want to change the base?
SDK-6103 Added support for My Account API. #847
Conversation
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
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`. |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are optional parameters
There was a problem hiding this comment.
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
…nd modifying Email, Phone, and TOTP Verification verifyOtp(...)
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 |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.* |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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
There was a problem hiding this 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") |
There was a problem hiding this comment.
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.
) : 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") |
There was a problem hiding this comment.
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.
) : 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") |
There was a problem hiding this comment.
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.
) : 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") |
There was a problem hiding this comment.
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.
) : 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") |
There was a problem hiding this comment.
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.
) : 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 | ||
|
There was a problem hiding this comment.
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.
/** | |
* 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 |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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, ) |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 ?
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