|
21 | 21 | - [Get user information](#get-user-information) |
22 | 22 | - [Custom Token Exchange](#custom-token-exchange) |
23 | 23 | - [Native to Web SSO login [EA]](#native-to-web-sso-login-ea) |
| 24 | + - [My Account API](#my-account-api) |
| 25 | + - [Enroll a new passkey](#enroll-a-new-passkey) |
24 | 26 | - [Credentials Manager](#credentials-manager) |
25 | 27 | - [Secure Credentials Manager](#secure-credentials-manager) |
26 | 28 | - [Usage](#usage) |
27 | 29 | - [Requiring Authentication](#requiring-authentication) |
| 30 | + - [Other Credentials](#other-credentials) |
28 | 31 | - [Handling Credentials Manager exceptions](#handling-credentials-manager-exceptions) |
29 | 32 | - [Passkeys](#passkeys) |
30 | 33 | - [Bot Protection](#bot-protection) |
@@ -649,6 +652,115 @@ authentication |
649 | 652 | </details> |
650 | 653 |
|
651 | 654 |
|
| 655 | +## My Account API |
| 656 | + |
| 657 | +> [!NOTE] |
| 658 | +> 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. |
| 659 | +
|
| 660 | +Use the Auth0 My Account API to manage the current user's account. |
| 661 | + |
| 662 | +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. |
| 663 | + |
| 664 | +### Enroll a new passkey |
| 665 | + |
| 666 | +**Scopes required:** `create:me:authentication_methods` |
| 667 | + |
| 668 | +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) |
| 669 | +APIs to create a new passkey credential. Finally, you use the created passkey credential and the original challenge to enroll the passkey with Auth0. |
| 670 | + |
| 671 | +#### Prerequisites |
| 672 | + |
| 673 | +- A custom domain configured for your Auth0 tenant. |
| 674 | +- The **Passkeys** grant to be enabled for your Auth0 application. |
| 675 | +- The Android **Device Settings** configured for your Auth0 application. |
| 676 | +- Passkeys are supported only on devices that run Android 9 (API level 28) or higher. |
| 677 | + |
| 678 | +Check [our documentation](https://auth0.com/docs/native-passkeys-for-mobile-applications#before-you-begin) for more information. |
| 679 | + |
| 680 | +#### 1. Request an enrollment challenge |
| 681 | + |
| 682 | +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). |
| 683 | + |
| 684 | +```kotlin |
| 685 | + |
| 686 | +val client = MyAccountAPIClient(account, accessToken) |
| 687 | + |
| 688 | +client.passkeyEnrollmentChallenge() |
| 689 | + .start(object: Callback<PasskeyEnrollmentChallenge, MyAccountException> { |
| 690 | + override fun onSuccess(result: PasskeyEnrollmentChallenge) { |
| 691 | + print("Challenge: ${result.challenge}") |
| 692 | + } |
| 693 | + override fun onFailure(error: MyAccountException) { |
| 694 | + print("Error: ${error.message}") |
| 695 | + } |
| 696 | + }) |
| 697 | +``` |
| 698 | +<details> |
| 699 | + <summary>Using coroutines</summary> |
| 700 | + |
| 701 | +```kotlin |
| 702 | + |
| 703 | + val client = MyAccountAPIClient(account, "accessToken") |
| 704 | + |
| 705 | + try { |
| 706 | + val challenge = client.passkeyEnrollmentChallenge() |
| 707 | + .await() |
| 708 | + println("Challenge: $challenge") |
| 709 | + } catch (exception: MyAccountException) { |
| 710 | + print("Error: ${exception.message}") |
| 711 | + } |
| 712 | +``` |
| 713 | +</details> |
| 714 | + |
| 715 | +#### 2. Create a new passkey credential |
| 716 | + |
| 717 | +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. |
| 718 | + |
| 719 | +```kotlin |
| 720 | +// Using coroutines |
| 721 | +val request = CreatePublicKeyCredentialRequest( |
| 722 | + Gson().toJson(enrollmentChallenge.authParamsPublicKey) |
| 723 | +) |
| 724 | + |
| 725 | +val result = credentialManager.createCredential(requireContext(), request) |
| 726 | + |
| 727 | +val passkeyCredentials = Gson().fromJson( |
| 728 | + (result as CreatePublicKeyCredentialResponse).registrationResponseJson, |
| 729 | + PublicKeyCredentials::class.java |
| 730 | +) |
| 731 | +``` |
| 732 | +#### 3. Enroll the passkey |
| 733 | + |
| 734 | +Use the created passkey credential and the enrollment challenge to enroll the passkey with Auth0. |
| 735 | + |
| 736 | +```Kotlin |
| 737 | + |
| 738 | +client.enroll(passkeyCredential,challenge) |
| 739 | + .start(object: Callback<PasskeyAuthenticationMethod, MyAccountException> { |
| 740 | + override fun onSuccess(result: PasskeyAuthenticationMethod) { |
| 741 | + println("Passkey enrolled successfully: ${result.id}") |
| 742 | + } |
| 743 | + |
| 744 | + override fun onFailure(error: MyAccountException) { |
| 745 | + println("Error enrolling passkey: ${error.message}") |
| 746 | + } |
| 747 | + }) |
| 748 | +``` |
| 749 | +<details> |
| 750 | + <summary>Using coroutines</summary> |
| 751 | + |
| 752 | +```kotlin |
| 753 | + |
| 754 | +try { |
| 755 | + val result = client.enroll(passkeyCredential, challenge) |
| 756 | + .await() |
| 757 | + println("Passkey enrolled successfully: ${result.id}") |
| 758 | +} catch(error: MyAccountException) { |
| 759 | + println("Error enrolling passkey: ${error.message}") |
| 760 | +} |
| 761 | +``` |
| 762 | +</details> |
| 763 | + |
652 | 764 | ## Credentials Manager |
653 | 765 |
|
654 | 766 | ### Secure Credentials Manager |
@@ -735,6 +847,56 @@ AuthenticationLevel is an enum that defines the different levels of authenticati |
735 | 847 | - **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. |
736 | 848 | - **DEVICE_CREDENTIAL**: The non-biometric credential used to secure the device (i.e., PIN, pattern, or password). |
737 | 849 |
|
| 850 | + |
| 851 | +### Other Credentials |
| 852 | + |
| 853 | +#### API credentials [EA] |
| 854 | + |
| 855 | +> [!NOTE] |
| 856 | +> 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. |
| 857 | +
|
| 858 | +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. |
| 859 | + |
| 860 | +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. |
| 861 | + |
| 862 | +> [!IMPORTANT] |
| 863 | +> Currently, only the Auth0 My Account API is supported. Support for other APIs will be added in the future. |
| 864 | +
|
| 865 | +```kotlin |
| 866 | + |
| 867 | +credentialsManager.getApiCredentials( |
| 868 | + audience = "https://example.com/me", scope = " create:me:authentication_methods", |
| 869 | + callback = object : Callback<APICredentials, CredentialsManagerException> { |
| 870 | + override fun onSuccess(result: APICredentials) { |
| 871 | + print("Obtained API credentials: $result") |
| 872 | + } |
| 873 | + |
| 874 | + override fun onFailure(error: CredentialsManagerException) { |
| 875 | + print("Failed with: $error") |
| 876 | + } |
| 877 | + }) |
| 878 | + |
| 879 | +``` |
| 880 | + |
| 881 | +<details> |
| 882 | + <summary>Using Coroutines</summary> |
| 883 | + |
| 884 | +```kotlin |
| 885 | + |
| 886 | + try { |
| 887 | + val result = credentialsManager.awaitApiCredentials( |
| 888 | + audience = "https://example.com/me", |
| 889 | + scope = "create:me:authentication_methods" |
| 890 | + ) |
| 891 | + print("Obtained API credentials: $result") |
| 892 | + } catch (error: CredentialsManagerException) { |
| 893 | + print("Failed with: $error") |
| 894 | + } |
| 895 | + |
| 896 | +``` |
| 897 | + |
| 898 | +</details> |
| 899 | + |
738 | 900 | ### Handling Credentials Manager exceptions |
739 | 901 |
|
740 | 902 | 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: |
|
0 commit comments