Loading
Salesforce now sends email only from verified domains. Read 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 Username-Password Flow for Private Clients

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

          To set up username-password login for an off-platform app developed by your company, use this headless username-password login flow, which implements the OAuth 2.0 for First-Party Applications draft standard protocol. With this flow, you can entirely control the front-end login 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 username-password login 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—headless username-password login 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 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.

          By default, users enter their username to log in. To give users more options, set up headless user discovery. For example, develop a flow where users enter their email address, phone number, or even an order number. See Headless Login without a Username.

          Here's an overview of how the flow works.

          • Step 1: An end user goes to your first-party app and logs in via their username and password. Or, if you're using headless user discovery, they enter an identifier such as an email address, phone number, or order number, along with their password.
          • Step 2: Your first-party app mints a client attestation JWT and generates parameters for the Proof Key for Code Exchange (PKCE) extension.
          • Step 3: To get an authorization code, your first-party app sends a headless POST request to the services/oauth2/v1/authorization_challenge endpoint on your Experience Cloud site. The request includes a client attestation JWT along with the user's credentials.
          • Step 4: To confirm that your first-party app sent the request, Salesforce validates the client attestation JWT and then validates the other parameters.
          • (Optional) If you're using headless user discovery, your Apex handler finds the user based on the identifier that they used to log in. If the user credentials are valid and the user has a verified email address or phone number, the login proceeds.
          • Step 5: If the request is successful, Salesforce returns an authorization code.
          • Step 6: To exchange the code for an access token, your first-party app sends a request to the /services/oauth2/token endpoint.
          • Step 7: Salesforce returns a token response containing the access token.
          • Step 8: Your first-party app processes the access token and creates the user's session.
          • Step 9: The end user is now logged in and performs an action in your app that requires access to a protected Salesforce resource.
          • Step 10: Your first-party app makes an authenticated call to a Salesforce API.
          • Step 11: The user can now access their Salesforce data in your first-party app.

          Step 1: End User Opens First-Party App and Logs In

          An end user opens your first-party app intending to log in. In your app, your login form appears showing username and password fields and a login button. Salesforce doesn’t provide this login form. Its look and feel are up to you. Your user enters their username and password and clicks the login button.

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

          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 3: First-Party App Headlessly Requests an Authorization Code

          From the browser, your app sends the user's credentials, along with other parameters, to the services/oauth2/v1/authorization_challenge endpoint on your Experience Cloud site via a headless POST request.

          There are no required headers for this request. Optionally, to connect this flow to the headless guest flow, you can include a Uvid-Hint header with a JWT-based access token containing a unique visitor ID (UVID) value.

          Initial POST Request to Authorization Challenge Endpoint: Headers
          Header Required? Description
          Uvid-Hint

          No. If you implement the guest user flow on your app, you can optionally use this header to pass in a JWT-based access token containing a UVID tied to a guest user’s identity. By passing the UVID into a named user flow, you can carry contextual information from a guest user session, like the user’s cookie preferences, into a named user session.

          Instead of passing a JWT-based token with a UVID in a header, you can also pass the plain UVID value in the request body.

          A JWT-based access token containing a UVID value, which is a Version 4 universally unique identifier (UUID) that’s generated and managed entirely by your app. To get an access token with a UVID, you must enable your external client app or connected app to issue JWT-based access tokens and implement the headless guest flow on your app.

          Include these parameters in the request body.

          Initial POST Request to Authorization Challenge Endpoint: Body Parameters
          Parameter Required? Description
          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.

          username Yes. The username that the user submitted to your login form.
          client_id Yes. The consumer key of the external client app.
          password Yes. The password that the user submitted to your login form.
          client_assertion Yes. The client attestation JWT that you generated, signed by the certificate configured for your external client app.
          recaptcha

          Required if these conditions apply to you:

          • You enabled Require reCAPTCHA to access the OAuth 2.0 authorization challenge endpoint for username-password login authorization flows 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 the OAuth 2.0 authorization challenge endpoint for username-password login authorization flows 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.

          scope No.

          Permissions that define the type of protected resources that the external client app can access. You assign scopes to the external client app when you build it, and they’re included with the OAuth tokens during the authorization flow.

          Use this parameter to request a subset of the scopes assigned to your external client app. If you don’t include this parameter, all scopes assigned to the app are requested

          uvid_hint

          No. If you implement the guest user flow on your app, you can optionally use this parameter to pass in a UVID value tied to a guest user’s identity, carrying contextual information from a guest user session into a named user session.

          Instead of passing the UVID in the request body, you can also pass it in a JWT-based token with a UVID via the UVID-Hint header.

          A plain UVID value, which is a Version 4 UUID that’s generated and managed entirely by your app. To get a UVID, you must enable your app to issue JWT-based access tokens and implement the headless guest flow on your app. You can optionally use this parameter to pass in a UVID value tied to a guest user’s identity, carrying contextual information from a guest user session into a named user session.

          Instead of passing the UVID in the request body, you can also pass it in a JWT-based token with a UVID via the UVID-Hint header.

          login_hint Required if you're using a headless user discovery Apex handler. An identifier that your Apex handler uses to find a user's Salesforce account. For example, collect a user's order number in your app and pass it in the login_hint parameter. We send the login_hint value straight to your Apex handler.
          customdata

          Required if you're using a headless user discovery handler that handles custom data. For example, if you're also using the handler with a login flow that handles custom data, you must pass custom data in the forgot password flow.

          Otherwise, it's optional but can be useful to help your handler find the user.

          A JSON string containing additional data that your Apex headless discovery handler uses to find a user's Salesforce account. For example, pass information about the user's locale.

          Here's an example request to the authorization challenge endpoint.

          POST /services/oauth2/v1/authorization_challenge? HTTP 1.1
          Host: MyExperienceCloudSite.my.site.com
          
          username=janice.edwards@example.com&
          password=*****&
          client_assertion=******&
          recaptcha=********&
          scope=profile&
          code_challenge=********
          

          Step 4: 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.

          HTTP/1.1 403 Forbidden
          Content-Type: application/json
          Cache-Control: no-store
          
          {
            "error": "invalid_attestation",
            "error_code": "client_attestation_failed"
          }
          

          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. Here's an example response that's returned if the user submits the wrong username or password.

          HTTP/1.1 403 Forbidden
          Content-Type: application/json
          Cache-Control: no-store
          
          {
            "error": "authorization_required",
            "auth_session": "uY29tL2F1d*****",
            "error_code": "invalid_credentials"
          }

          The response 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. Salesforce already knows that you submitted these parameters because they're linked to 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.

          Here are a few examples of common error scenarios. This list isn't comprehensive.

          • The user submitted the wrong username or password. Resubmit the request with only the username, password, and auth_session.
          • The reCAPTCHA token was incorrect. Resubmit the request with only the reCAPTCHA token, password, and auth_session.

          After 5 minutes from when the auth session was issued, it doesn't work anymore and you get an auth_session_invalid error. In that case, resubmit the full request with all the parameters that you originally included.

          (Optional) Headless User Discovery Handler Finds the User

          If you're using a headless user discovery handler, the handler takes the login_hint and customdataparameters and finds the associated user. The handler confirms that the email address or phone number for the user is verified.

          For an example handler, see Auth.HeadlessUserDiscoveryHandler.

          Step 5: Salesforce Returns an Authorization Code

          When your request to the authorization challenge endpoint is successful—whether that happens on the first try or after several retries with the auth_session—Salesforce returns an authorization code. Here's an example of a successful authorization code response.

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

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

          After you get the authorization code, your app sends a request to the services/oauth2/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 7: 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 8: App Creates the User’s Session

          The app receives the access token response and creates the user’s session.

          Step 9: The User Is Logged In and Performs an Action in the App

          The end user is now logged in, and they perform an action in your app that requires access to Salesforce data. For example, they click a button to view their order 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 10: 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 11: User Can Access Salesforce Data

          The user can now access protected Salesforce data in your app. For example, they can see their order history. From the user’s perspective, the entire process from logging in to accessing their data happened without ever requiring them to leave the app.

           
          Loading
          Salesforce Help | Article