diff --git a/main/docs/manage-users/my-account-api.mdx b/main/docs/manage-users/my-account-api.mdx index 9e7a0832f8..df7cdad411 100644 --- a/main/docs/manage-users/my-account-api.mdx +++ b/main/docs/manage-users/my-account-api.mdx @@ -2,19 +2,13 @@ description: Learn how you can empower your users to manage their own account information with the My Account API. title: My Account API --- -import {AuthCodeBlock} from "/snippets/AuthCodeBlock.jsx"; - import {AuthCodeGroup} from "/snippets/AuthCodeGroup.jsx"; - - -The My Account API is available in Early Access. To request access, contact your Auth0 account manager or contact [Auth0 Support](https://support.auth0.com). To learn more about Auth0's product release cycle, read [Product Release Stages](/docs/troubleshoot/product-lifecycle/product-release-stages). - - +import { ReleaseStageNotice } from "/snippets/ReleaseStageNotice.jsx" The Auth0 My Account API provides a dedicated set of endpoints for users to manage their own account information. Customers can use these APIs to build self-service experiences in their applications or progressively add details to a user account. -The My Account API operates within the context of the currently logged-in user and can be used directly within user-facing applications. +The My Account API operates within the context of the currently logged-in user, and you can use it directly within user-facing applications. @@ -38,9 +32,9 @@ You can activate the My Account API for your tenant in the @@ -59,13 +53,14 @@ You cannot update the application API policy for client access to the My Account To learn more about how to manage application API access policies and their associated client grants, read [Application Access to APIs: Client Grants](/docs/get-started/applications/application-access-to-apis-client-grants). -## Default Policy setting - - - -Authentication Assurance for the **My Account API** is currently in Early Access with a single-option policy. By using this feature, you agree to the applicable Free Trial terms in Okta’s [Master Subscription Agreement](https://www.okta.com/legal). To learn more about Auth0’s product release cycle, read [Product Release Stages](/docs/troubleshoot/product-lifecycle/product-release-stages). To participate in the program, contact [Auth0 Support](https://support.auth0.com). +## Default Policy - + The Default Policy provides built-in authentication assurance for the My Account API by requiring [Step-up Authentication](/docs/secure/multi-factor-authentication/step-up-authentication). When enabled, Auth0 automatically enforces that users have authenticated recently and with a second factor. @@ -84,20 +79,20 @@ The Default Policy is not compatible with Classic Login. Enable this feature if To enable the Default Policy for the My Account API: -1. Navigate to [**Applications > APIs**](https://manage.auth0.com/#/apis), then select the **My Account API**. -2. Select the **Settings** tab. -3. Under **Default Policy**, toggle on **Require 2FA**. -4. Select **Save**. +1. Navigate to [**Applications > APIs**](https://manage.auth0.com/#/apis), then select the **My Account API**. +2. Select the **Settings** tab. +3. Under **Default Policy**, toggle on **Require 2FA**. +4. Select **Save**. -When your tenant has the Default Policy enabled, it is automatically attached whenever a new My Account API is created. +When your tenant has the Default Policy enabled, Auth0 automatically attaches it whenever it creates a new My Account API. ### Authentication requirements hierarchy The Default Policy sits between the tenant-level MFA policy and any MFA logic you define in Actions: -1. **Tenant MFA policy** — the base default applied across all authentication on your tenant -2. **Default Policy** — overrides the tenant level specifically for the My Account API -3. **Actions** — any MFA commands in Actions always take precedence over both +1. **Tenant MFA policy**: The base default applied across all authentication on your tenant +2. **Default Policy**: Overrides the tenant-level specifically for the My Account API +3. **Actions**: Any MFA commands in Actions always take precedence over both ### Default Policy behavior @@ -122,9 +117,9 @@ For users with no verified email and no enrolled factor: -When `unmet_authentication_requirements` is returned on a refresh token exchange, the token cannot be refreshed. Your application must restart the full authentication flow to obtain new tokens. +When Auth0 returns `unmet_authentication_requirements` on a refresh token exchange, you cannot refresh the token. Your application must restart the full authentication flow to obtain new tokens. -The same error is returned for a silent login (`prompt=none`) when the user cannot satisfy the policy after 15 minutes. +A silent login (`prompt=none`) returns the same error when the user cannot satisfy the policy after 15 minutes. @@ -161,7 +156,7 @@ The My Account API supports the following scopes: | `create:me:authentication_methods` | Allows the user to enroll a new authentication method. | | `read:me:authentication_methods` | Allows the user to view existing authentication methods. | | `update:me:authentication_methods` | Allows the user to modify existing authentication methods. | -| `delete:me:authentication_methods` | Allows the user to modify existing authentication methods. | +| `delete:me:authentication_methods` | Allows the user to delete existing authentication methods. | | `read:me:factors` | Allows the user to view the factors they can enroll. | For [Connected Accounts with Token Vault](/docs/secure/call-apis-on-users-behalf/token-vault/connected-accounts-for-token-vault), the My Account API supports the following scopes: @@ -172,11 +167,13 @@ For [Connected Accounts with Token Vault](/docs/secure/call-apis-on-users-behalf | `read:me:connected_accounts` | Allows the user to view the existing connected accounts linked to their user profile. | | `delete:me:connected_accounts` | Allows the user to delete a connected account from their user profile. | -### Examples +### Access token examples + +#### Universal Login with Authorization Code Flow -#### Universal Login with authorization code flow +Retrieving access tokens with [Auth0's Universal Login](/docs/authenticate/login/auth0-universal-login#auth0-universal-login) is a two-step process: request an authorization code and exchange the code for an access token. To learn more about this grant type, read [Authorization Code Flow](/docs/get-started/authentication-and-authorization-flow/authorization-code-flow). -##### Step 1: Request authorization code +First, make an API call to the `/authorize` endpoint to request an authorization code: ```bash cURL @@ -217,7 +214,7 @@ func main() { HttpResponse response = Unirest.get("https://{yourDomain}/authorize?response_type=code&client_id={yourClientId}&redirect_uri=%7ByourRedirectUri%7D&scope=create%3Ame%3Aauthentication_methods&offline_access=&audience=https%3A%2F%2F{yourDomain}%2Fme%2F") .asString(); ``` -```javascript Node.JS +```javascript Node.js var axios = require("axios").default; var options = { @@ -293,20 +290,20 @@ puts response.read_body ``` -##### Step 2: Exchange code for access token +Next, exchange the code for an access token: ```bash cURL curl --request POST \ --url 'https://{yourDomain}/oauth/token' \ --header 'content-type: application/json' \ - --data '{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}' + --data '{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}' ``` ```csharp C# var client = new RestClient("https://{yourDomain}/oauth/token"); var request = new RestRequest(Method.POST); request.AddHeader("content-type", "application/json"); -request.AddParameter("application/json", "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}", ParameterType.RequestBody); +request.AddParameter("application/json", "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```go Go @@ -323,7 +320,7 @@ func main() { url := "https://{yourDomain}/oauth/token" - payload := strings.NewReader("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}") + payload := strings.NewReader("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}") req, _ := http.NewRequest("POST", url, payload) @@ -342,10 +339,10 @@ func main() { ```java Java HttpResponse response = Unirest.post("https://{yourDomain}/oauth/token") .header("content-type", "application/json") - .body("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}") + .body("{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}") .asString(); ``` -```javascript Node.JS +```javascript Node.js var axios = require("axios").default; var options = { @@ -355,10 +352,10 @@ var options = { data: { grant_type: 'authorization_code', client_id: '{yourClientId}', - client_secret: '{yourClientId}', + client_secret: '{yourClientSecret}', code: '{yourAuthorizationCode}', redirect_uri: '{yourRedirectUri}', - audience: '{yourAudience}', + audience: 'https://{yourDomain}/me/', scope: 'create:me:authentication_methods', offline_access: '' } @@ -381,7 +378,7 @@ curl_setopt_array($curl, [ CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}", + CURLOPT_POSTFIELDS => "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}", CURLOPT_HTTPHEADER => [ "content-type: application/json" ], @@ -403,7 +400,7 @@ import http.client conn = http.client.HTTPSConnection("") -payload = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}" +payload = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}" headers = { 'content-type': "application/json" } @@ -427,7 +424,7 @@ http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Post.new(url) request["content-type"] = 'application/json' -request.body = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientId}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "{yourAudience}","scope": "create:me:authentication_methods","offline_access": ""}" +request.body = "{"grant_type": "authorization_code","client_id": "{yourClientId}","client_secret": "{yourClientSecret}","code": "{yourAuthorizationCode}","redirect_uri": "{yourRedirectUri}","audience": "https://{yourDomain}/me/","scope": "create:me:authentication_methods","offline_access": ""}" response = http.request(request) puts response.read_body @@ -436,20 +433,20 @@ puts response.read_body #### Embedded login with native passkeys -##### Step 1: Request login challenge +To include [passkeys](/docs/authenticate/database-connections/passkeys) in your embedded application's login flow, first request login challenge: ```bash cURL curl --request POST \ --url 'https://{yourDomain}/passkey/challenge' \ --header 'content-type: application/json' \ - --data '{"client_id": "{yourDomain}"}' + --data '{"client_id": "{yourClientId}"}' ``` ```csharp C# var client = new RestClient("https://{yourDomain}/passkey/challenge"); var request = new RestRequest(Method.POST); request.AddHeader("content-type", "application/json"); -request.AddParameter("application/json", "{"client_id": "{yourDomain}"}", ParameterType.RequestBody); +request.AddParameter("application/json", "{"client_id": "{yourClientId}"}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```go Go @@ -466,7 +463,7 @@ func main() { url := "https://{yourDomain}/passkey/challenge" - payload := strings.NewReader("{"client_id": "{yourDomain}"}") + payload := strings.NewReader("{"client_id": "{yourClientId}"}") req, _ := http.NewRequest("POST", url, payload) @@ -485,17 +482,17 @@ func main() { ```java Java HttpResponse response = Unirest.post("https://{yourDomain}/passkey/challenge") .header("content-type", "application/json") - .body("{"client_id": "{yourDomain}"}") + .body("{"client_id": "{yourClientId}"}") .asString(); ``` -```javascript Node.JS +```javascript Node.js var axios = require("axios").default; var options = { method: 'POST', url: 'https://{yourDomain}/passkey/challenge', headers: {'content-type': 'application/json'}, - data: {client_id: '{yourDomain}'} + data: {client_id: '{yourClientId}'} }; axios.request(options).then(function (response) { @@ -515,7 +512,7 @@ curl_setopt_array($curl, [ CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{"client_id": "{yourDomain}"}", + CURLOPT_POSTFIELDS => "{"client_id": "{yourClientId}"}", CURLOPT_HTTPHEADER => [ "content-type: application/json" ], @@ -537,7 +534,7 @@ import http.client conn = http.client.HTTPSConnection("") -payload = "{"client_id": "{yourDomain}"}" +payload = "{"client_id": "{yourClientId}"}" headers = { 'content-type': "application/json" } @@ -561,21 +558,21 @@ http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Post.new(url) request["content-type"] = 'application/json' -request.body = "{"client_id": "{yourDomain}"}" +request.body = "{"client_id": "{yourClientId}"}" response = http.request(request) puts response.read_body ``` -##### Step 2: Authenticate existing user +Next, authenticate existing users: ```bash cURL curl --request POST \ --url 'https://{yourDomain}/oauth/token' \ --header 'content-type: application/json' \ - --data '{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}' + --data '{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}' ``` ```csharp C# var client = new RestClient("https://{yourDomain}/oauth/token"); @@ -598,7 +595,7 @@ func main() { url := "https://{yourDomain}/oauth/token" - payload := strings.NewReader("{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}") + payload := strings.NewReader("{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}") req, _ := http.NewRequest("POST", url, payload) @@ -617,17 +614,17 @@ func main() { ```java Java HttpResponse response = Unirest.post("https://{yourDomain}/oauth/token") .header("content-type", "application/json") - .body("{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}") + .body("{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}") .asString(); ``` -```javascript Node.JS +```javascript Node.js var axios = require("axios").default; var options = { method: 'POST', url: 'https://{yourDomain}/oauth/token', headers: {'content-type': 'application/json'}, - data: '{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}' + data: '{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}' }; axios.request(options).then(function (response) { @@ -647,7 +644,7 @@ curl_setopt_array($curl, [ CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POSTFIELDS => "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}", + CURLOPT_POSTFIELDS => "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}", CURLOPT_HTTPHEADER => [ "content-type: application/json" ], @@ -669,7 +666,7 @@ import http.client conn = http.client.HTTPSConnection("") -payload = "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}" +payload = "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}" headers = { 'content-type': "application/json" } @@ -681,7 +678,7 @@ data = res.read() print(data.decode("utf-8")) ``` ```ruby Ruby -rrequire 'uri' +require 'uri' require 'net/http' require 'openssl' @@ -693,31 +690,171 @@ http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Post.new(url) request["content-type"] = 'application/json' -request.body = "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/" "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}" +request.body = "{ "grant_type": "urn:okta:params:oauth:grant-type:webauthn", "client_id": "{yourClientId}", "scope": "create:me:authentication_methods offline_access", "audience": "https://{yourDomain}/me/", "auth_session": "{sessionIdFromTheFirstRequest}", "authn_response": "{authenticatorResponse}"}" response = http.request(request) puts response.read_body ``` +## Manage authentication methods + +With the My Account API, configure authentication methods so your end users are able to enroll and manage their own authentication methods. Most methods use a two-step flow: start enrollment, then confirm your enrollment. + +Review the table for supported authentication methods. + +| Type | Enrollment behavior | Enrollable via API | +| :--- | :--- | :--- | +| `email`
Secondary (MFA) | `POST { "type": "email" }` Include `email` in the `POST` request. Auth0 sends a one-time code to the address. Submit that code as `otp_code` in the verify request. | Yes | +| `phone`
Secondary (MFA) | `POST { "type": "sms" }` Auth0 sends a one-time code to the phone number. Submit that code as `otp_code` in the verify request. | Yes | +| `totp`
Secondary (MFA) | `POST { "type": "totp" }` The response includes:
  • `barcode_uri`: renders as a QR code for the user to scan with an authenticator app.
  • `manual_input_code`: the TOTP secret for users who cannot scan a QR code.
| Yes | +| `push-notification`
Secondary (MFA) | `POST { "type": "push-notification" }` The response includes a `barcode_uri` for the user to scan and link an authenticator app. The verify request requires only `auth_session` and not `otp_code`. Auth0 completes enrollment after the user approves the push in their app. | Yes | +| `recovery-code`
Secondary (MFA) | `POST { "type": "recovery-code" }` The response includes a `recovery_code`. Display this value to the user immediately since you cannot retrieve it again. The verify request requires only `auth_session`. | Yes | +| `password`
Primary | `POST { "type": "password" }` The response includes a `policy` object describing the tenant's password requirements (e.g. minimum length, allowed character types, history, and dictionary settings). Submit `new_password` along with `auth_session` in the verify request. Auth0 validates the password against the policy before confirming enrollment. | Yes | +| `passkey`
Primary | `POST { "type": "passkey" }`. The response does not include an ID. Instead it returns:
  • `auth_session`: unique session identifier for the enrollment as returned by `POST /authentication-methods`.
  • `authn_params_public_key`: allows the WebAuthn `PublicKeyCredentialCreationOptions` to pass to `navigator.credentials.create()`. In the verify request, submit the full WebAuthn `AuthenticatorAttestationResponse` as `authn_response`. The method ID is returned in the verify response.
| Yes | +| `webauthn-platform`
Secondary (MFA) | Enrollment is not currently supported. | No — read-only | +| `webauthn-roaming`
Secondary (MFA) | Enrollment is not currently supported. | No — read-only | + +### Enrollment flow + +Enrolling an authentication method is a two-step process: +1. To start enrollment, make a `POST` call to `/me/authentication-methods` with the method type and any required fields. Auth0 returns an `auth_session` token and type-specific enrollment. +2. To confirm enrollment, make a `POST` call to `/me/authentication-methods/{id}/verify` with the `auth_session` and the verification credential for that method type (an OTP code, a new password, or a WebAuthn response). + +Once confirmed, Auth0 sets the method's `confirmed` field to `true` in subsequent `GET` responses. + + +Passkey enrollment does not include an ID in the `POST` response. Auth0 only returns the ID after the verify step succeeds. + + +### Manage authentication method examples + +#### Enroll a TOTP authenticator + +Enrolling TOTP is a two-step process: starting TOTP enrollment and confirming TOTP enrollment. + +First, start enrollment to receive a QR code and manual secret for the user to add to their authenticator app: + + + + ```bash + curl --request POST \ + --url 'https://{yourDomain}/me/authentication-methods' \ + --header 'Authorization: Bearer {yourAccessToken}' \ + --header 'Content-Type: application/json' \ + --data '{"type": "totp"}' + ``` + + + ```json + { + "id": "amr_abc123", + "auth_session": "eyJhbGci...", + "barcode_uri": "otpauth://totp/YourApp:user%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=YourApp", + "manual_input_code": "JBSWY3DPEHPK3PXP" + } + ``` + + + +Next, confirm by submitting the one-time code from the user's authenticator app along with the `auth_session` and `id` from the previous response: + + + + ```bash + curl --request POST \ + --url 'https://{yourDomain}/me/authentication-methods/{id}/verify' \ + --header 'Authorization: Bearer {yourAccessToken}' \ + --header 'Content-Type: application/json' \ + --data '{"auth_session": "{yourAuthSession}", "otp_code": "{yourOtpCode}"}' + ``` + + + ```json + { + "id": "amr_abc123", + "type": "totp", + "confirmed": true, + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:35:00.000Z" + } + ``` + + + +#### List authentication methods + +Retrieve all authentication methods enrolled for the current user. The `confirmed` field indicates whether enrollment has been completed. + + + + ```bash + curl --request GET \ + --url 'https://{yourDomain}/me/authentication-methods' \ + --header 'Authorization: Bearer {yourAccessToken}' + ``` + + + ```json + [ + { + "id": "amr_abc123", + "type": "totp", + "confirmed": true, + "created_at": "2024-01-15T10:30:00.000Z", + "updated_at": "2024-01-15T10:35:00.000Z" + }, + { + "id": "amr_def456", + "type": "email", + "email": "user@example.com", + "confirmed": true, + "created_at": "2024-01-10T08:00:00.000Z", + "updated_at": "2024-01-10T08:05:00.000Z" + } + ] + ``` + + + +#### Delete an authentication method + +Remove an enrolled authentication method. Replace `{id}` with the method's `id` from the list response. + + + + ```bash + curl --request DELETE \ + --url 'https://{yourDomain}/me/authentication-methods/{id}' \ + --header 'Authorization: Bearer {yourAccessToken}' + ``` + + + ```text + HTTP 204 No Content + ``` + + ## Rate limits -During Early Access, the My Account API is limited at a tenant level to 25 requests per second. +During Early Access, Auth0 limits the My Account API to 25 requests per second per tenant. -## Cross-Origin Requests +## Cross-origin requests -If you intend to call the My Account API directly from a browser-based application (like a Single Page Application) running on a different domain than your Auth0 tenant, you will encounter browser security policies known as Cross-Origin Resource Sharing (CORS). By default, browsers block these cross-origin requests. +If you intend to call the My Account API directly from a browser-based application (like a Single Page Application) running on a different domain than your Auth0 tenant, you may encounter browser security policies known as [Cross-Origin Resource Sharing (CORS)](/docs/authenticate/passwordless/implement-login/embedded-login/spa#configure-cross-origin-resource-sharing-cors). By default, browsers block these cross-origin requests. To allow your application to successfully make requests to the API, you must add your application's domain (its "origin") to your client's configuration: 1. Navigate to [Dashboard > Applications](https://manage.auth0.com/#/applications). Select the application to view. -2. Under Cross-Origin Authentication, toggle on Allow Cross-Origin Authentication. +2. Under **Cross-Origin Authentication**, toggle on **Allow Cross-Origin Authentication**. 3. Locate **Allowed Origins (CORS)**, and enter your application's origin URL. 4. Select **Save**. To learn more, read [Configure Cross-Origin Resource Sharing](/docs/get-started/applications/set-up-cors). -If you do not need to use CORS for your application, ensure that Allow Cross-Origin Authentication is toggled off. Adding your application's URL to this list tells Auth0 to trust requests from that origin, allowing your client-side application to access the API. + +If you do not need to use CORS for your application, ensure that **Allow Cross-Origin Authentication** is toggled off. Adding your application's URL to this list tells Auth0 to trust requests from that origin, allowing your client-side application to access the API. +