From 8a6a95f3556b5bf059438a50ea8813f9801b3b18 Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Wed, 4 Jun 2025 15:54:40 +0530 Subject: [PATCH 1/3] Added passkey enrollment to examples.md file --- EXAMPLES.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/EXAMPLES.md b/EXAMPLES.md index 6597019d8..e92bfef1d 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -21,6 +21,8 @@ - [Get user information](#get-user-information) - [Custom Token Exchange](#custom-token-exchange) - [Native to Web SSO login [EA]](#native-to-web-sso-login-ea) + - [My Account API](#my-account-api) + - [Enroll a new passkey](#enroll-a-new-passkey) - [Credentials Manager](#credentials-manager) - [Secure Credentials Manager](#secure-credentials-manager) - [Usage](#usage) @@ -649,6 +651,115 @@ authentication +## My Account API + +> [!NOTE] +> The My Account API 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. + +Use the Auth0 My Account API to manage the current user's account. + +To call the My Account API, you need an access token issued specifically for this API, including any required scopes for the operations you want to perform. + +### Enroll a new passkey + +**Scopes required:** `create:me:authentication_methods` + +Enrolling a new passkey is a three-step process. First, you request an enrollment challenge from Auth0. Then you need to pass that challenge to Google's [Credential Manager](https://developer.android.com/identity/sign-in/credential-manager) +APIs to create a new passkey credential. Finally, you use the created passkey credential and the original challenge to enroll the passkey with Auth0. + +#### Prerequisites + +- A custom domain configured for your Auth0 tenant. +- The **Passkeys** grant to be enabled for your Auth0 application. +- The Android **Device Settings** configured for your Auth0 application. +- Passkeys are supported only on devices that run Android 9 (API level 28) or higher. + +Check [our documentation](https://auth0.com/docs/native-passkeys-for-mobile-applications#before-you-begin) for more information. + +#### 1. Request an enrollment challenge + +You can specify an optional user identity identifier and/or a database connection name to help Auth0 find the user. The user identity identifier will be needed if the user logged in with a [linked account](https://auth0.com/docs/manage-users/user-accounts/user-account-linking). + +```kotlin + +val client = MyAccountAPIClient(account, accessToken) + +client.passkeyEnrollmentChallenge() + .start(object :Callback{ + override fun onSuccess(result: PasskeyEnrollmentChallenge) { + print("Challenge: ${result.challenge}") + } + override fun onFailure(error: MyAccountException) { + print("Error: ${error.message}") + } + }) +``` +
+ Using coroutines + +```kotlin + + val client = MyAccountAPIClient(account, "accessToken") + + try{ + val challenge = client.passkeyEnrollmentChallenge() + .await() + println("Challenge: $challenge") + } catch (exception:MyAccountException){ + print("Error: ${exception.message}") + } +``` +
+ +#### 2. Create a new passkey credential + +Use the enrollment challenge with the Google's [CredentialManager](https://developer.android.com/identity/sign-in/credential-manager) APIs to create a new passkey credential. + +```kotlin +// Using coroutines +val request = CreatePublicKeyCredentialRequest( + Gson().toJson(enrollmentChallenge.authParamsPublicKey) +) + +val result = credentialManager.createCredential(requireContext(), request) + +val passkeyCredentials = Gson().fromJson( + (result as CreatePublicKeyCredentialResponse).registrationResponseJson, + PublicKeyCredentials::class.java +) +``` +#### 3. Enroll the passkey + +Use the created passkey credential and the enrollment challenge to enroll the passkey with Auth0. + +```Kotlin + +client.enroll(passkeyCredential,challenge) + .start(object :Callback{ + override fun onSuccess(result: PasskeyAuthenticationMethod) { + println("Passkey enrolled successfully: ${result.id}") + } + + override fun onFailure(error: MyAccountException) { + println("Error enrolling passkey: ${error.message}") + } + }) +``` +
+ Using coroutines + +```kotlin + +try{ + val result = client.enroll(passkeyCredential,challenge) + .await() + println("Passkey enrolled successfully: ${result.id}") +}catch(error:MyAccountException){ + println("Error enrolling passkey: ${error.message}") +} +``` +
+ ## Credentials Manager ### Secure Credentials Manager From b8fe479bd7babaaaa08af7e4efa14e81e5f0bfcd Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Mon, 9 Jun 2025 15:25:36 +0530 Subject: [PATCH 2/3] Minor indent refactors --- EXAMPLES.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index e92bfef1d..8d8f226ce 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -685,7 +685,7 @@ You can specify an optional user identity identifier and/or a database connectio val client = MyAccountAPIClient(account, accessToken) client.passkeyEnrollmentChallenge() - .start(object :Callback{ + .start(object: Callback { override fun onSuccess(result: PasskeyEnrollmentChallenge) { print("Challenge: ${result.challenge}") } @@ -699,13 +699,13 @@ client.passkeyEnrollmentChallenge() ```kotlin - val client = MyAccountAPIClient(account, "accessToken") + val client = MyAccountAPIClient(account, "accessToken") - try{ - val challenge = client.passkeyEnrollmentChallenge() + try { + val challenge = client.passkeyEnrollmentChallenge() .await() println("Challenge: $challenge") - } catch (exception:MyAccountException){ + } catch (exception: MyAccountException) { print("Error: ${exception.message}") } ``` @@ -735,7 +735,7 @@ Use the created passkey credential and the enrollment challenge to enroll the pa ```Kotlin client.enroll(passkeyCredential,challenge) - .start(object :Callback{ + .start(object: Callback { override fun onSuccess(result: PasskeyAuthenticationMethod) { println("Passkey enrolled successfully: ${result.id}") } @@ -750,11 +750,11 @@ client.enroll(passkeyCredential,challenge) ```kotlin -try{ - val result = client.enroll(passkeyCredential,challenge) +try { + val result = client.enroll(passkeyCredential, challenge) .await() println("Passkey enrolled successfully: ${result.id}") -}catch(error:MyAccountException){ +} catch(error: MyAccountException) { println("Error enrolling passkey: ${error.message}") } ``` From 5cda66b7ea3f1883a531703f83fc3cae96a49c43 Mon Sep 17 00:00:00 2001 From: Prince Mathew Date: Mon, 9 Jun 2025 15:43:43 +0530 Subject: [PATCH 3/3] Added example for APICredentials --- EXAMPLES.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index 8d8f226ce..7521ed719 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -27,6 +27,7 @@ - [Secure Credentials Manager](#secure-credentials-manager) - [Usage](#usage) - [Requiring Authentication](#requiring-authentication) + - [Other Credentials](#other-credentials) - [Handling Credentials Manager exceptions](#handling-credentials-manager-exceptions) - [Passkeys](#passkeys) - [Bot Protection](#bot-protection) @@ -658,7 +659,7 @@ authentication Use the Auth0 My Account API to manage the current user's account. -To call the My Account API, you need an access token issued specifically for this API, including any required scopes for the operations you want to perform. +To call the My Account API, you need an access token issued specifically for this API, including any required scopes for the operations you want to perform. See [API credentials [EA]](#api-credentials-ea) to learn how to obtain one. ### Enroll a new passkey @@ -846,6 +847,56 @@ AuthenticationLevel is an enum that defines the different levels of authenticati - **WEAK**: Any biometric (e.g., fingerprint, iris, or face) on the device that meets or exceeds the requirements for Class 2 (formerly Weak), as defined by the Android CDD. - **DEVICE_CREDENTIAL**: The non-biometric credential used to secure the device (i.e., PIN, pattern, or password). + +### Other Credentials + +#### API credentials [EA] + +> [!NOTE] +> 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. + +When the user logs in, you can request an access token for a specific API by passing its API identifier as the [audience](#specify-audience) value. The access token in the resulting credentials can then be used to make authenticated requests to that API. + +However, if you need an access token for a different API, you can exchange the [refresh token](https://auth0.com/docs/secure/tokens/refresh-tokens) for credentials containing an access token specific to this other API. + +> [!IMPORTANT] +> Currently, only the Auth0 My Account API is supported. Support for other APIs will be added in the future. + +```kotlin + +credentialsManager.getApiCredentials( + audience = "https://example.com/me", scope = " create:me:authentication_methods", + callback = object : Callback { + override fun onSuccess(result: APICredentials) { + print("Obtained API credentials: $result") + } + + override fun onFailure(error: CredentialsManagerException) { + print("Failed with: $error") + } + }) + +``` + +
+ Using Coroutines + +```kotlin + + try { + val result = credentialsManager.awaitApiCredentials( + audience = "https://example.com/me", + scope = "create:me:authentication_methods" + ) + print("Obtained API credentials: $result") + } catch (error: CredentialsManagerException) { + print("Failed with: $error") + } + +``` + +
+ ### Handling Credentials Manager exceptions In the event that something happened while trying to save or retrieve the credentials, a `CredentialsManagerException` will be thrown. These are some of the expected failure scenarios: