Loading
Salesforce now sends email only from verified domains. Read More
Help Agent Performance DegradationRead More
Identify Your Users and Manage Access
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          OAuth 2.0 for First-Party Applications: Headless Registration Flow for Private Clients

          OAuth 2.0 for First-Party Applications: Headless Registration Flow for Private Clients

          To set up a headless user registration process for an off-platform app developed by your company, use this flow, which implements the OAuth 2.0 for First-Party Applications draft standard protocol. This flow is supported only for private clients, such as client-server apps. With this flow, you can entirely control the front-end registration experience in your first-party app while Salesforce handles the backend work of authenticating users and granting access to protected resources. This flow is supported only for private clients, such as client-server apps, and is supported only for external users.

          Required Editions

          Available in: both Salesforce Classic and Lightning Experience
          Available in: Enterprise, Unlimited, and Developer Editions

          To set up headless registration for a private client, you can also use this version of the Authorization Code and Credentials Flow, which implements Headless Identity APIs. Both flows accomplish the same use case—registration for an app outside of the Salesforce platform. But there are a few key differences to keep in mind.

          OAuth For First-Party APPS Headless Identity APIS
          Supported only for private clients. Supported for public and private clients.
          Conforms to the OAuth 2.0 for First-Party Applications draft standard protocol. Proprietary Salesforce flow that's built on top of the OAuth 2.0 standard.
          Supported only for the Salesforce external client app framework. Also, the only way to configure external client app settings for this flow is via Metadata API. Supported for both the Salesforce external client app and connected app frameworks.
          For security, this flow always requires a client attestation JWT. Salesforce uses the client attestation JWT to validate that the app was developed by your company. For security, requires either authentication or reCAPTCHA, but not a client attestation JWT.

          Before setting up this flow, complete these steps.

          Here's an overview of how the flow works.

          • Step 1: An end user opens your first-party app and clicks Register.
          • Step 2: In your app, you natively display a registration form to collect user data. You design this form and customize the information that you want to collect.
          • Step 3: The user enters their information in your app For example, they enter their username, password, and first name.
          • Step 4: Your app mints a client attestation JWT. It also generates parameters for the Proof Key for Code Exchang (PKCE) extension.
          • Step 5: To initialize registration, your app submits the user information to the services/oauth2/v1/authorization_challenge endpoint on your Experience Cloud site. The request includes a client attestation JWT.
          • Step 6: To confirm that your first-party app sent the request, Salesforce validates the client attestation JWT, and then validates the other parameters sent in the request.
          • Step 7: When the request is successful, Salesforce returns a response with an auth_session. The response indicates that Salesforce initialized registration and sent a one-time password (OTP) to the user.
          • Step 8: In your app, you natively display a verification form. You choose how you want this form to look.
          • Step 9: The user receives their OTP and enters it in the verification form.
          • Step 10: To request an authorization code, your app sends another POST request to the services/oauth2/v1/authorization_challenge endpoint. The request includes the auth_session and the OTP.
          • Step 11: If the request is successful, Salesforce returns an authorization code to your app and terminates the auth_session.
          • Step 12: To exchange the code for an access token, your first-party app sends a request to the /services/oauth2/token endpoint.
          • Step 13: Salesforce returns a token response containing the access token.
          • Step 14: Your first-party app processes the token response and creates the user's session.
          • Step 15: The user is now logged in and they perform an action in your app that initiates a request for Salesforce data.
          • Step 16: Your app makes an authenticated request to a protected Salesforce endpoint, such as a Salesforce API.
          • Step 17: The user can now access their protected data in your app.

          Step 1: User Opens First-Party App and Clicks Register

          A user opens your first-party app and clicks a registration link. Or they click a link to access a resource that requires registration.

          Step 2: First-Party App Displays Registration Form

          In your first-party app, you natively display a registration form to collect information about the user. You control everything about this form, including its look, feel, and the user information that you want to collect.

          There are a few considerations about what information you want to gather from users. When your app submits user information to the authorization challenge endpoint, Salesforce checks for an email address, username, last name, and password. You can collect this information from users or autogenerate it, but it must be included in your POST request. When deciding what information to include, make sure to collect an email address or phone number so that the user can verify their identity.

          Step 3: User Enters Their Information

          In your app's registration form, the user enters their information.

          Step 4: First-Party App Mints a Client Attestation JWT and Generates code_verifier and code_challenge Values for PKCE

          The app mints a client attestation JWT.

          The app also generates values for the PKCE parameters used to verify the authorization code.

          Note
          Note We strongly recommend that you always implement PKCE for this flow. Otherwise, you don't get its security benefits.

          For more information on PKCE, see the specificationRFC 7636: Proof Key for Code Exchange by OAuth Public Clients provided by the Internet Engineering Task Force (IETF).

          The PKCE specification defined in RFC 7636 also includes an optional code_challenge_method parameter that you can send in the authorization request. Salesforce ignores any value that you send in this parameter and defaults to SHA256.

          Step 5: App Sends Initial Request to the Authorization Challenge Endpoint

          From the browser, your app sends a POST request to the services/oauth2/v1/authorization_challenge endpoint on your Experience Cloud site.

          Include this header in your request if necessary.

          Initial Registration Request: Headers
          Header Required? Description
          Authorization: Bearer Required if you enable Require authentication to access this API in the headless registration section on the Experience Cloud Login & Registration page. Contains an access token issued to an internal integration user. To get the access token, you can use any standard OAuth flow that Salesforce supports. Ensure that you assign the user_registration_api scope to your connected app or external client app, or pass it as a parameter during your flow.

          Include these parameters in the request body.

          Initial Registration Request: Body Parameters
          Parameter Required? Description
          password Yes. The user’s password. The password is subject to any password policies configured for the profile or org.
          userdata Yes. Even if you don’t collect this information from the user, you must autogenerate it and pass it in the userdata parameter.

          Contains all required user information. At minimum, Salesforce requires this information in the userdata parameter.

          • username
          • lastName
          • email address
          recaptcha

          Required if these conditions apply to you:

          • You enabled Require reCAPTCHA to access this API for headless registration in your Experience Cloud Login & Registration settings.
          • You're using reCAPTCHA v2 or v3.
          An encrypted token issued by the Google reCAPTCHA API when a user completes a reCAPTCHA challenge.
          recaptchaevent

          Required if these conditions apply to you:

          • You enabled Require reCAPTCHA to access this API for headless registration in your Experience Cloud Login & Registration settings.
          • You're using reCAPTCHA Enterprise.

          A JSON object containing these subparameters.

          • token—An encrypted token issued by the Google reCAPTCHA API when a user completes a reCAPTCHA challenge.
          • siteKey—The Google reCAPTCHA site key.
          • (Optional)expectedAction—The action that you expect the user to take to initiate reCAPTCHA, such as login. This parameter maps to Google's action parameter.
          • projectId—The project ID from Google.

          For more information, see Google's reCAPTCHA documentation.

          client_assertion Yes. The client attestation JWT that you generated, signed by the certificate configured for your external client app.
          login_type No. If you don’t include this parameter, Salesforce defaults to verifying the user’s identity with email. The method used to verify the user’s identity. Salesforce supports two values for the verification method: email and sms.
          customdata No. Contains any custom user information that you collect. For example, you can include the user’s street address.
          emailtemplate

          Required to specify multiple email templates if email template allowlisting is enabled.

          If you didn’t enable email template allowlisting, you can’t include this parameter.

          If you don’t include this parameter, Salesforce uses the default email template configured in your Experience Cloud settings, regardless of whether allowlisting is enabled. If there’s no template configured, Salesforce uses a default OTP email template.

          The custom email template developer name. This parameter can include only an email template from the allowlist.
          code_challenge Required if you required PKCE for your external client app. For this flow's security features to work correctly, we strongly recommend that you always require PKCE.

          Specifies the SHA256 hash value of the code_verifier value in the token request. Set this parameter to help prevent authorization code interception attacks. The value must be Base-64 URL encoded as defined in https://tools.ietf.org/html/rfc4648#section-5

          If a code_challenge is provided in the authorization request and a code_verifier is provided in the token request, Salesforce compares the two values. If the code_challenge is invalid or doesn’t match, the login fails with the invalid_request error code.

          If the code_challenge is provided in the authorization request, but there’s no code_verifier in the token request, the login fails with the invalid_grant error code.

          Here's an example initial registration request.

          POST /services/oauth2/v1/authorization_challenge? HTTP 1.1
          Host: MyExperienceCloudSite.my.site.com
          {
              "userdata": {
                  "firstname": "Janice"
                  "lastname": "Edwards"
                  "email": "janice.edwards@example.com"
                  "username": "jedwards@myapp.com"
                  }
              "customdata": {
                  "mobilePhone"="<mobile phone number>"
                  }
              "password":"*********"
              "recaptcha": "*******"
              "login_type": "email"
              "emailtemplate": "unfiled$public/SalesNewCustomerEmail"
              "client_assertion": "Y2xpZW50YXNzZXJ0aW9u..."
          }

          Step 6: Salesforce Validates the Request

          Salesforce first attempts to validate the client attestation JWT by validating that the signature passed in the client_asssertion parameter matches the signature for the certificate configured for the external client app.

          If the client attestation JWT isn't valid, Salesforce returns an invalid_attestation error and you must resubmit the request with all of the parameters you originally submitted. Here's an example error response.

          If the client attestation JWT is valid, but there are other issues with the request, Salesforce returns an error response specifying what was wrong with the request. The response also includes an auth_session parameter that remains valid for 5 minutes after it's issued. During the timeframe while the auth_session is valid, you can use it to resubmit the request. In the corrected versions that you resubmit, include only the corrected values for the parameters that caused the request to fail. You must also resubmit the password with each request because Salesforce doesn't store it. But for other parameters, if they didn't cause the request to fail, you can leave them out. They're already represented by the auth_session.

          Note
          Note reCAPTCHA parameters don't get linked to the auth_session, but you can resubmit the request without them, unless they caused the request to fail.

          For example, if your client attestation JWT is valid but the request fails because the username was incorrect, resubmit a request that includes only the auth_session, username, and password.

          Step 7: Salesforce Sends an OTP to the User

          If the request is successful, Salesforce still returns an error response because it can't yet grant the authorization code. But this time, the error response indicates that login was initialized and that Salesforce sent an OTP to the user's email address or phone number. To confirm that the request was successful, look out for the error code login_initialized and the state otp_sent. The response also includes an auth_session parameter, which is important for the next step.

          Here's an example response.

          HTTP/1.1 403 Forbidden
          Content-Type: application/json
          Cache-Control: no-store
          
          {
            "error": "authorization_required",
            "auth_session": "uY29tL2F1dGhlbnRpY",
            "error_code": "login_initialized",
            "login_status": {
              "type": "SMS",
              "state": "otp_sent",
              "displayData": "+120******58"
             }
          }

          Step 8: Your App Natively Displays a Verification Form

          In your first-party app, you display a verification form where the end user can enter their OTP. The look and feel of this form are entirely up to you.

          Step 9: User Enters OTP in Verification Form

          The user receives the OTP and enters it in the verification form in your first-party app.

          Step 10: Your App Requests an Authorization Code

          To request an authorization code, your app sends the auth_session and the OTP that the user entered to the authorization challenge endpoint using another POST request to the services/oauth2/v1/authorization_challenge This request has no required headers. Include these parameters in the request body.

          Authorization Code Request: Body Parameters
          Parameter Required? Description
          auth_session Yes. Represents the login attempt. Use the auth_session value that you received in the response from your first request to the authorization challenge endpoint. Make sure to use the auth_session from the request that indicated that login was initialized and the OTP was sent.
          login_otp Yes. The OTP that the end user entered in your app's verification form.

          Here's an example request.

          POST /authorize HTTP/1.1
          Host: MyExperienceCloudSite.my.site.com
          
          auth_session=uY29tL2F1dGhlbnRpY*
          login_otp=<otp_from_sms>

          Step 11: Salesforce Returns an Authorization Code

          If the OTP is correct and the auth_session request is valid, Salesforce returns an authorization code and terminates the auth_session. Here's an example authorization code response.

          HTTP/1.1 200 OK
          Content-Type: application/json;charset=UTF-8
          Cache-Control: no-store
          
          {
            "authorization_code": "uY29tL2F1d******"
          }

          Step 12: Your App Exchanges the Authorization Code for an Access Token

          After you get the authorization code, your app sends a request to the Salesforce token endpoint.

          This request has no headers. Include these parameters in the request body.

          Token Request: Body Parameters
          Parameter Required? Description
          code Yes. The authorization server creates an authorization code, which is a short-lived token, and passes it to the client after successful authentication. The client sends the authorization code to the authorization server to obtain an access token and, optionally, a refresh token.
          client_id Yes. The consumer key of the external client app.
          client_secret Yes. The consumer secret of the external client app. In this flow, it acts as a password that the app uses to access Salesforce.
          redirect_uri Yes. The URL where users are redirected after a successful authentication. The redirect URI must match one of the values in the external client app Callback URL field. Otherwise, the approval fails. This value must be URL encoded.
          grant_type Yes. The type of validation that the app can provide to prove it’s a safe visitor. For this flow, the value must be authorization_code.
          code_verifier Required if you required PKCE for your external client app. For this flow's security features to work correctly, we strongly recommend that you always require PKCE.

          Specifies 128 bytes of random data with high entropy to make guessing the code value difficult. Set this parameter to help prevent authorization code interception attacks. The value must be base64url-encoded as defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5.

          If there’s a code_verifier value in the token request and a code_challenge value in the authorization request, Salesforce compares the two values. If the code_verifier is invalid or doesn’t match, the login fails with the invalid_grant error code.

          If the code_verifier value is in the token request, but there’s no code_challenge value in the authorization request, the login fails with the invalid_grant error code.

          Here's an example token request.

          POST services/oauth2/token? HTTP 1.1
          Host: MyExperienceCloudSite.my.site.com
          
          code=********&
          client_id=**********&
          client_secret=*********&
          redirect_uri=<callback_URL>&
          grant_type=authorization_code&
          code_verifier=*******

          Step 13: Salesforce Grants an Access Token

          After validating the app’s credentials. Salesforce returns an access token. Here’s an example access token response in JSON format.

          {
          "access_token":"*******************",
          "sfdc_community_url":"https://MyDomainName.my.site.com",
          "sfdc_community_id":"0DBxxxxxxxxxxxx",
          "signature":"ts6wm/svX3jXlCGR4uu+SbA04M6qhD1SAgVTEwZ59P4=",
          "scope":"openid api",
          "id_token":"XXXXXX",
          "instance_url":"https://yourInstance.salesforce.com",
          "id":"https://yourInstance.salesforce.com/id/00Dxxxxxxxxxxxx/005xxxxxxxxxxxx",
          "token_type":"Bearer",
          "issued_at":"1667600739962"
          }

          The access token response contains these parameters.

          Token Response Parameters
          Parameter Required? Description
          access_token Yes. OAuth token that an external client app uses to request access to a protected resource on behalf of the client application. Additional permissions in the form of scopes can accompany the access token.
          id Yes. An identity URL that can be used to identify the user and to query for more information about the user. See Identity URLs.
          id_token No. A signed data structure that contains authenticated user attributes, including a unique identifier for the user and a timestamp indicating when the token was issued. It also identifies the requesting app. See OpenID Connect specifications.
          instance_url Yes. A URL indicating the instance of the user’s org. For example, https://yourInstance.salesforce.com/.
          issued_at Yes. A timestamp of when the signature was created, expressed as the number of milliseconds from 1970-01-01T0:0:0Z UTC.
          refresh_token No. Token obtained from the web server, user-agent, or hybrid app token flow. This value is a secret. Take appropriate measures to protect it. This parameter is returned only if your external client app or connected app is set up with a refresh_token scope.
          signature Yes. Base64-encoded HMAC-SHA256 signature signed with the client_secret. The signature can include the concatenated ID and issued_at value, which you can use to verify that the identity URL hasn’t changed since the server sent it.
          sfdc_community_url Yes. The URL of the Experience Cloud site.
          sfdc_community_id Yes. The user’s Experience Cloud site ID.
          state No. The state requested by the client. This value is included only if the state parameter is included in the original query string.
          token_type Yes. A Bearer token type, which is used for all responses that include an access token.

          Step 14: App Creates the User’s Session

          Your first-party app processes the token response and creates the user's session.

          Step 15: User Is Registered and Performs an Action in the App

          Your user is now registered and logged in. They perform an action in your app that requires access to Salesforce data. For example, they click a button to view their travel booking history, which is stored in Salesforce.

          Note
          Note When you set up your external client app or connected app for the Authorization Code and Credentials Flow, you set the Permitted Users policy to Admin-approved users are pre-authorized and configure which profiles or permission sets can access the app. With this policy, users access the app without authorizing it, so they don’t get an authorization screen prompting them to let the app access their data.

          Step 16: App Makes an Authenticated Call to a Salesforce Endpoint

          To access the user’s Salesforce data, your app uses the access token to make an authenticated call to a protected Salesforce endpoint, such as a Salesforce API.

          Step 17: User Can Access Salesforce Data

          The user can now access protected Salesforce data in your app. For example, they can see their travel booking history.

           
          Loading
          Salesforce Help | Article