From 7b519d9d3bdfd51edf89e9b5462e3af88c76ee70 Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Tue, 17 Jun 2025 12:47:45 +0530 Subject: [PATCH 1/3] Added api of the delete method --- .../android/myaccount/MyAccountAPIClient.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt index 401dd0d5d..bb4d7cca6 100644 --- a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt +++ b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt @@ -264,6 +264,57 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting return request } + + /** + * Deletes an existing authentication method. + * + * ## Availability + * + * This feature is currently available in + * [Early Access](https://auth0.com/docs/troubleshoot/product-lifecycle/product-release-stages#early-access). + * Please reach out to Auth0 support to get it enabled for your tenant. + * + * ## Scopes Required + * `delete:me:authentication-methods:passkey` + * + * ## Usage + * + * ```kotlin + * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN") + * val apiClient = MyAccountAPIClient(auth0, accessToken) + * + * + * apiClient.delete(authenticationMethodId, ) + * .start(object : Callback { + * override fun onSuccess(result: Void) { + * Log.d("MyApp", "Authentication method deleted") + * } + * + * override fun onFailure(error: MyAccountException) { + * Log.e("MyApp", "Failed with: ${error.message}") + * } + * }) + * ``` + * + * @param authenticationMethodId Id of the authentication method to be deleted + * + */ + public fun delete( + authenticationMethodId: String + ): Request { + val url = + getDomainUrlBuilder() + .addPathSegment(AUTHENTICATION_METHODS) + .addPathSegment(authenticationMethodId) + .build() + + val request = factory.delete(url.toString(), GsonAdapter(Void::class.java)) + .addHeader(AUTHORIZATION_KEY, "Bearer $accessToken") + + return request + } + + private fun getDomainUrlBuilder(): HttpUrl.Builder { return auth0.getDomainUrl().toHttpUrl().newBuilder() .addPathSegment(ME_PATH) From 28f059c24495ce10c9afc7f410df22d70c76b0e0 Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Wed, 18 Jun 2025 13:45:54 +0530 Subject: [PATCH 2/3] Added the initial set of api for passkey /authentication methods management --- .../android/myaccount/MyAccountAPIClient.kt | 59 +++++++++++++++++-- .../android/result/AuthenticationMethod.kt | 36 +++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt diff --git a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt index bb4d7cca6..dcb397dd7 100644 --- a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt +++ b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt @@ -1,6 +1,7 @@ package com.auth0.android.myaccount import androidx.annotation.VisibleForTesting +import androidx.browser.customtabs.CustomTabsService.Result import com.auth0.android.Auth0 import com.auth0.android.Auth0Exception import com.auth0.android.NetworkErrorException @@ -14,6 +15,7 @@ import com.auth0.android.request.internal.GsonAdapter.Companion.forMap import com.auth0.android.request.internal.GsonProvider import com.auth0.android.request.internal.RequestFactory import com.auth0.android.request.internal.ResponseUtils.isNetworkError +import com.auth0.android.result.AuthenticationMethod import com.auth0.android.result.PasskeyAuthenticationMethod import com.auth0.android.result.PasskeyEnrollmentChallenge import com.auth0.android.result.PasskeyRegistrationChallenge @@ -244,7 +246,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting "type" to "public-key", "response" to mapOf( "clientDataJSON" to credentials.response.clientDataJSON, - "attestationObject" to credentials.response.attestationObject + "attestationObject" to credentials.response.attestationObject, ) ) @@ -266,7 +268,56 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting /** - * Deletes an existing authentication method. + * Retrieves a single authentication method belonging to the user. + * + * ## Availability + * + * This feature is currently available in + * [Early Access](https://auth0.com/docs/troubleshoot/product-lifecycle/product-release-stages#early-access). + * Please reach out to Auth0 support to get it enabled for your tenant. + * + * + * ## Usage + * + * ```kotlin + * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN") + * val apiClient = MyAccountAPIClient(auth0, accessToken) + * + * + * apiClient.getAuthenticationMethod(authenticationMethodId, ) + * .start(object : Callback { + * override fun onSuccess(result: AuthenticationMethod) { + * Log.d("MyApp", "Authentication method $result") + * } + * + * override fun onFailure(error: MyAccountException) { + * Log.e("MyApp", "Failed with: ${error.message}") + * } + * }) + * ``` + * + * @param authenticationMethodId Id of the authentication method to be retrieved + * + */ + public fun getAuthenticationMethod(authenticationMethodId: String): Result { + val url = + getDomainUrlBuilder() + .addPathSegment(AUTHENTICATION_METHODS) + .addPathSegment(authenticationMethodId) + .build() + + val request = factory.get( + url.toString(), + GsonAdapter(AuthenticationMethod::class.java) + ) + .addHeader(AUTHORIZATION_KEY, "Bearer $accessToken") + + return request + } + + + /** + * Deletes an existing authentication method belonging to the user. * * ## Availability * @@ -284,7 +335,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting * val apiClient = MyAccountAPIClient(auth0, accessToken) * * - * apiClient.delete(authenticationMethodId, ) + * apiClient.deleteAuthenticationMethod(authenticationMethodId, ) * .start(object : Callback { * override fun onSuccess(result: Void) { * Log.d("MyApp", "Authentication method deleted") @@ -299,7 +350,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting * @param authenticationMethodId Id of the authentication method to be deleted * */ - public fun delete( + public fun deleteAuthenticationMethod( authenticationMethodId: String ): Request { val url = diff --git a/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt b/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt new file mode 100644 index 000000000..ea86d3508 --- /dev/null +++ b/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt @@ -0,0 +1,36 @@ +package com.auth0.android.result + + +import com.google.gson.annotations.SerializedName + +/** + * An Authentication Method + */ +public data class AuthenticationMethod( + @SerializedName("created_at") + val createdAt: String, + @SerializedName("credential_backed_up") + val credentialBackedUp: Boolean?, + @SerializedName("credential_device_type") + val credentialDeviceType: String?, + @SerializedName("id") + val id: String, + @SerializedName("identity_user_id") + val identityUserId: String, + @SerializedName("key_id") + val keyId: String?, + @SerializedName("last_password_reset") + val lastPasswordReset: String, + @SerializedName("public_key") + val publicKey: String?, + @SerializedName("transports") + val transports: List?, + @SerializedName("type") + val type: String, + @SerializedName("usage") + val usage: String, + @SerializedName("user_agent") + val userAgent: String?, + @SerializedName("user_handle") + val userHandle: String? +) \ No newline at end of file From 2dd8661043e38507adce8b8deb4f033aa9f17d00 Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Tue, 15 Jul 2025 11:54:26 +0530 Subject: [PATCH 3/3] Added the remaining end points --- .../android/myaccount/MyAccountAPIClient.kt | 114 +++++++++++++++++- .../android/result/AuthenticationMethod.kt | 11 +- 2 files changed, 121 insertions(+), 4 deletions(-) diff --git a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt index dcb397dd7..cc030e268 100644 --- a/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt +++ b/auth0/src/main/java/com/auth0/android/myaccount/MyAccountAPIClient.kt @@ -1,7 +1,6 @@ package com.auth0.android.myaccount import androidx.annotation.VisibleForTesting -import androidx.browser.customtabs.CustomTabsService.Result import com.auth0.android.Auth0 import com.auth0.android.Auth0Exception import com.auth0.android.NetworkErrorException @@ -16,6 +15,7 @@ import com.auth0.android.request.internal.GsonProvider import com.auth0.android.request.internal.RequestFactory import com.auth0.android.request.internal.ResponseUtils.isNetworkError import com.auth0.android.result.AuthenticationMethod +import com.auth0.android.result.AuthenticationMethods import com.auth0.android.result.PasskeyAuthenticationMethod import com.auth0.android.result.PasskeyEnrollmentChallenge import com.auth0.android.result.PasskeyRegistrationChallenge @@ -267,6 +267,52 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting } + /** + * Retrieves a detailed list of authentication methods belonging to the user. + * + * ## Availability + * + * This feature is currently available in + * [Early Access](https://auth0.com/docs/troubleshoot/product-lifecycle/product-release-stages#early-access). + * Please reach out to Auth0 support to get it enabled for your tenant. + * + * + * ## Usage + * + * ```kotlin + * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN") + * val apiClient = MyAccountAPIClient(auth0, accessToken) + * + * + * apiClient.getAuthenticationMethods() + * .start(object : Callback { + * override fun onSuccess(result: AuthenticationMethods) { + * Log.d("MyApp", "Authentication method $result") + * } + * + * override fun onFailure(error: MyAccountException) { + * Log.e("MyApp", "Failed with: ${error.message}") + * } + * }) + * ``` + * + */ + public fun getAuthenticationMethods(): Request { + val url = + getDomainUrlBuilder() + .addPathSegment(AUTHENTICATION_METHODS) + .build() + + val request = factory.get( + url.toString(), + GsonAdapter(AuthenticationMethods::class.java) + ) + .addHeader(AUTHORIZATION_KEY, "Bearer $accessToken") + + return request + } + + /** * Retrieves a single authentication method belonging to the user. * @@ -284,7 +330,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting * val apiClient = MyAccountAPIClient(auth0, accessToken) * * - * apiClient.getAuthenticationMethod(authenticationMethodId, ) + * apiClient.getAuthenticationMethodById(authenticationMethodId, ) * .start(object : Callback { * override fun onSuccess(result: AuthenticationMethod) { * Log.d("MyApp", "Authentication method $result") @@ -299,7 +345,7 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting * @param authenticationMethodId Id of the authentication method to be retrieved * */ - public fun getAuthenticationMethod(authenticationMethodId: String): Result { + public fun getAuthenticationMethodById(authenticationMethodId: String): Request { val url = getDomainUrlBuilder() .addPathSegment(AUTHENTICATION_METHODS) @@ -315,6 +361,66 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting return request } + /** + * Updates a single authentication method belonging to the user. + * + * ## Availability + * + * This feature is currently available in + * [Early Access](https://auth0.com/docs/troubleshoot/product-lifecycle/product-release-stages#early-access). + * Please reach out to Auth0 support to get it enabled for your tenant. + * + * + * ## Usage + * + * ```kotlin + * val auth0 = Auth0.getInstance("YOUR_CLIENT_ID", "YOUR_DOMAIN") + * val apiClient = MyAccountAPIClient(auth0, accessToken) + * + * + * apiClient.updateAuthenticationMethodById(authenticationMethodId,preferredAuthenticationMethod, authenticationMethodName) + * .start(object : Callback { + * override fun onSuccess(result: AuthenticationMethod) { + * Log.d("MyApp", "Authentication method $result") + * } + * + * override fun onFailure(error: MyAccountException) { + * Log.e("MyApp", "Failed with: ${error.message}") + * } + * }) + * ``` + * + * @param authenticationMethodId Id of the authentication method to be retrieved + * @param authenticationMethodName The friendly name of the authentication method + * @param preferredAuthenticationMethod The preferred authentication method for the user. (for phone authenticators) + * + */ + public fun updateAuthenticationMethodById( + authenticationMethodId: String, + preferredAuthenticationMethod: String, + authenticationMethodName: String + ): Request { + val url = + getDomainUrlBuilder() + .addPathSegment(AUTHENTICATION_METHODS) + .addPathSegment(authenticationMethodId) + .build() + + val params = ParameterBuilder.newBuilder().apply { + set(PREFERRED_AUTHENTICATION_METHOD, preferredAuthenticationMethod) + set(AUTHENTICATION_METHOD_NAME, authenticationMethodName) + }.asDictionary() + + val request = factory.patch( + url.toString(), + GsonAdapter(AuthenticationMethod::class.java) + ) + .addHeader(AUTHORIZATION_KEY, "Bearer $accessToken") + .addParameters(params) + + return request + } + /** * Deletes an existing authentication method belonging to the user. @@ -385,6 +491,8 @@ public class MyAccountAPIClient @VisibleForTesting(otherwise = VisibleForTesting private const val LOCATION_KEY = "location" private const val AUTH_SESSION_KEY = "auth_session" private const val AUTHN_RESPONSE_KEY = "authn_response" + private const val PREFERRED_AUTHENTICATION_METHOD = "preferred_authentication_method" + private const val AUTHENTICATION_METHOD_NAME = "name" private fun createErrorAdapter(): ErrorAdapter { val mapAdapter = forMap(GsonProvider.gson) return object : ErrorAdapter { diff --git a/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt b/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt index ea86d3508..8699c9495 100644 --- a/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt +++ b/auth0/src/main/java/com/auth0/android/result/AuthenticationMethod.kt @@ -28,9 +28,18 @@ public data class AuthenticationMethod( @SerializedName("type") val type: String, @SerializedName("usage") - val usage: String, + val usage: List, @SerializedName("user_agent") val userAgent: String?, @SerializedName("user_handle") val userHandle: String? +) + + +/** + * List of Authentication Methods + */ +public data class AuthenticationMethods( + @SerializedName("authentication_methods") + val authenticationMethods: List ) \ No newline at end of file