Skip to main content

OAuth 2.0 in Salesforce: From Web Server to JWT Bearer

About Us
Published by yuliya.dzemidchuk
27 February 2026

Salesforce OAuth 2.0 flows

 

Introduction

When it comes to Identity and Access Management, it’s worth understanding that this is a crucial part of any IT solution. Negligent management can lead to excessive access to private information and ultimately to data leaks or exploitation.

The basic purpose of any access management system is to verify the right user (authentication) accesses the corresponding resources (authorization). There are several essential protocols to perform these actions in a standardized way and safely with the ability to scale and integrate with other systems.

  • OAuth 2.0 - protocol for authorization, controlling external client applications to gain appropriate access to the target resource system.
  • SAML (Security Assertion Markup Language) — protocol for authentication, which provides an authentication access grant for a user that validated their identity by an XML-formatted assertion of whether the user is allowed to access the target system. Used mostly in single sign on (SSO).
  • OpenID Connect (OIDC) - protocol for authentication, which provides an authentication access grant for a user that validated their identity by a JWT token. It’s built on top of OAuth 2.0 and used for social sign on and in some authorization flows.

In Salesforce, OAuth 2.0 is used for authorization — to grant any client applications, such as mobile or desktop applications, IoT devices, or other servers, controlled access to Salesforce REST APIs.

 

Basic concepts

OAuth 2.0 flows are designed to cover all the potential scenarios of secure interconnection between the client application and Salesforce. All Salesforce OAuth flows involve these core actors:

  • Client — the application or device requesting access.
  • Authorization Server — Salesforce’s OAuth service that issues tokens.
  • Resource Server — Salesforce APIs that serve protected resources when presented with valid access tokens.

 

OAuth Tokens

Tokens represent the authorization context between parties and enforce access to protected resources. They are typically issued by an authorization server. In this article the next tokens will be considered.

  • Authorization code - short-lived code that is obtained by the client by performing the call to an /authorize endpoint and typically used to obtain access and refresh tokens.
  • Access token - a token that confirms successful user authorization and used to access protected resources.
  • Refresh token - can be generated along with an access token and used to obtain a new access token after its expiration without conducting the authorization process (with auth code) once again.
  • Asset token - special type of access token designed for IoT devices linking and access to Salesforce.

 

OAuth Scopes

Scopes determine the set of resources or functionality that the client may access during an established connection. The set of available scopes for the client is set up in the external client app in Salesforce. Clients can also further restrict access to a subset of the available set during connection establishment. To look for the full list of possible scopes, see https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm&type=5

 

OAuth Endpoints

OAuth endpoints are the URLs clients use to make a requests to Salesforce during the authorization process. Each OAuth flow defines which endpoints to use during the flow process, but the most used endpoints are listed below.

  • https://hostname/services/oauth2/authorize - clients use this endpoint to authorize their application within Salesforce and obtain authorization code.
  • https://hostname/services/oauth2/token - clients use this endpoint to obtain access and refresh tokens.

Worth mentioning that all OAuth endpoints require HTTPS. For the full list of available endpoints, see https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_endpoints.htm&type=5

 

Headless Identity Flows

Headless identity flows are Salesforce’s version of non-interactive authentication. Unlike some standard OAuth flows that depend on redirecting a user’s browser to a login page, headless identity flows let a client authenticate and authorize using the Salesforce API calls, like login, register, etc. Use these flows if you’d like to have a pure API experience during Salesforce login or registration processes, instead of redirecting the user to the salesforce login page or embedded browser.

Available Headless flows:

  • Headless login using the Authorization Code and Credentials Flow
  • Headless Registration Flow
  • Headless Passwordless Login Flow
  • Headless Guest Flow
  • Headless Forgot Password Flow

 

OAuth 2.0 Web Server Flow

This flow uses OAuth 2.0 authorization code grant type. A client application navigates the user to the separate login page in a browser, where user logins and client obtains the authorization code. Then the client exchanges this code for an access token. The client secret parameter can be used unless the external client app doesn’t have Require Secret for Web Server Flow enabled. Salesforce recommends that this flow is used with Proof Key for Code for Exchange (PKCE). 

Use web server flow with PKCE if your client doesn’t have a secure backend to store the client secret.

 

PKCE

PKCE (pronounced pixy) - an extension to authorization code flow that secures interactions with public clients (usually clients without a backend side, who cannot securely store secrets) like single-page applications (SPAs) and mobile apps. It prevents authorization code interception attacks by requiring a dynamically generated cryptographic secret (code verifier) to be verified by the authorization server. Use the code_challenge and code_verifier parameters to implement PKCE with the web server flow. 

Instead of relying on a pre-shared symmetric client secret, PKCE uses the code_challenge and code_verifier parameters to establish a connection.

  • The client creates a unique, high-entropy cryptographic string called the code_verifier. It then hashes (usually a SHA256 hash) this string and obtains a code_challenge.
  • The client sends the code_challenge to the authorization server along with the authorization request (call to /authorize to obtain the authorization code).
  • When exchanging the authorization code for an access token, the client sends the original code_verifier. The authorization server hashes this verifier and compares it to the original challenge to prove the request comes from the same client.

In a flow without PKCE, an attacker with a stolen authorization code can potentially obtain an access token. With PKCE, the server requires a code verifier to verify the client that started the authorization process. Since this verifier is generated locally on the client and never leaves it until the final step, an attacker who steals only the authorization code has no chance to compromise and use the verifier the same way as the authorization code.

 

OAuth 2.0 User-Agent Flow

This flow uses the OAuth 2.0 implicit grant type. The client navigates the user to Salesforce’s login, and upon success Salesforce returns an access token directly in the redirect URL. This is intended for public clients that cannot securely store a secret. Because the access token is encoded into the redirection URL, it can be exposed to the user and other apps on the device. If you’re using JavaScript to authenticate, call window.location.replace(); to remove the callback from the browser’s history. 

It’s simpler than Web Server Flow but less secure because tokens are minted in a redirect URL fragment. Salesforce recommends to use OAuth 2.0 web server flow with PKCE instead of user-agent flow.

 

OAuth 2.0 Refresh Token Flow

This isn’t a standalone login flow but an extension. Applications that have previously obtained a refresh token use this flow to get a new access token when the old one expires. Can be set up as an extension for OAuth 2.0 web server flow or the OAuth 2.0 user-agent flow to generate refresh token along with access token. 

 

OAuth 2.0 Token Exchange Flow

When Salesforce is part of a larger architecture that uses a central identity provider, the OAuth 2.0 Token Exchange flow simplifies integration. Instead of authenticating separately with Salesforce, your platform first authenticates the user with the identity provider (for example, Okta) and receives a token (access token, refresh token, JWT, ID token, or SAML assertion). That token is then exchanged with Salesforce for a Salesforce access token mapped to the correct Salesforce user. Requires an Apex Token Exchange handler in order to map identity provider token with a corresponding existing user or create a new one. For example, in a conference management platform with an identity provider, multiple service providers (such as SAP or Concur), and AWS-based microservices, all services rely on tokens issued by the central identity provider. After login, the platform exchanges the identity provider’s token for service-specific tokens to access different systems. Using the same pattern, the identity provider’s token is sent to Salesforce, validated, and exchanged for a Salesforce access token. This keeps authentication centralized while allowing secure, delegated access to Salesforce data.

This flow is supported for your org-specific My Domain login URL (for internal users, also known as employees) and your Experience Cloud sites (for external users, also known as customers and partners).

 

OAuth 2.0 for Hybrid Apps

Hybrid app combines elements of native mobile app and web app providing cross-platform functionality. So the OAuth 2.0 for hybrid apps flow is designed for clients that have a web-backend part along with the native mobile component. When you use this flow you use scopes to request session IDs (SID) and domain values. You then use these SIDs and domain values to set browser cookies and establish sessions for the web-backend part of your hybrid app. When you refresh your access token, you receive new SIDs and domains to reset the browser cookies. Within your app you must set the cookies every time the access token is expired or refreshed. But there are some cases when you have to use the frontdoor.jsp to bridge an existing session into the web browser - for more information, see https://help.salesforce.com/s/articleView?id=xcloud.security_frontdoorjsp.htm&type=5

 

OAuth 2.0 JWT Bearer Flow

This is a server-to-server flow where the client constructs a signed JWT (JSON Web Token) assertion using an asymmetric signing (certificate-based) that Salesforce consequently validates. The process of creating and signing a valid JWT consists of several steps.

  • Client constructs the JWT Header object and JSON Claims Set object with required parameters, along with the username of the current user. 
  • Objects are encoded using Base64url encoding and the string in the format of encoded_JWT_Header + "." + encoded_JWT_Claims_Set is created.
  • This string is signed using RSA SHA256 from the certificate. Which means it’s firstly hashed with SHA256 and then signed with an RSA private key. Then this signed string is encoded with Base64url.
  • The final payload looks like this: existing_string + "." + base64_encoded_signature.

Afterwards, Salesforce verifies the signature using the public key and hashes the original string to compare with the received hash and check whether it was altered during the transfer.

Why is the signing process done by using a reversed asymmetric approach, i.e. signing with a private key, not the public? Because the fundamental goal of a digital signature is to provide authenticity and non-repudiation. A private key is known only to its owner. By creating a signature with this key, the signer creates a unique digital footprint that cannot be produced by anyone else. Anyone holding the corresponding public key can verify that the signature was created by that specific private key, proving the identity of the sender. In contrast with the signing approach, in the standard asymmetric encryption sender uses the public key to encrypt, but only the owner of the private key can decrypt the message, ensuring confidentiality.

No user interaction required. Refresh token issuance is supported only if your external client app policy is set to All users may self-authorize. Use this flow when a client needs to impersonate a specific user or requires stronger, asymmetric security for server-to-server communication. For example, B2B, cross-domain architectures.

 

OAuth 2.0 Client Credentials Flow

This is the server-to-server flow where the client exchanges the client ID and secret, obtained from Salesforce’s external client app, directly for an access token. When accessing Salesforce using this flow, the client doesn’t impersonate the specific user. But on the Salesforce side there is still a Salesforce user predefined in the external client app, on behalf of which the Salesforce is accessed.

No user interaction required. It does not support refresh tokens.

Use this flow for cases when it’s not required to do complex asymmetric (certificate-based) connection or no need to impersonate a specific user. But also make sure that client secret is stored securely on the client’s backend. For example, accessing single service-level data.

 

OAuth 2.0 Device Flow

This flow supports devices with limited input or display capability, such as Smart TVs, appliances, and other IoT devices. The device shows a code to the user who then enters it on a separate browser to authenticate and grant permission. Once the user authorizes, Salesforce provides tokens to the device. Supports refresh token.

Use this for IoT devices, smart appliances, or command-line tools where direct login is impossible. For example, a Bluetooth home device requests access to a user’s Salesforce data. The user enters the provided code on their phone browser to authorize, and the device eventually receives an access token.

 

OAuth 2.0 Asset Token Flow

This flow extends OAuth for IoT assets. An application exchanges an existing access token and an actor token (representing a specific device metadata) for an asset token. Access token is provided by a consequent call to the /authorize and /token endpoints, whereas the asset token is a JWT signature built based on the device identification metadata. Salesforce then automatically registers the asset based on unique device identifiers from the JWT. 

  • If the JWT claim contains an ID claim, Salesforce attempts to link to an existing asset with a matching ID.
  • If the JWT claim contains a serial number claim, Salesforce attempts to link to an existing asset with a matching serial number.
  • If the JWT claim contains a name claim, Salesforce creates (registers) an asset.
  • Otherwise, Salesforce doesn’t link to or create an asset. You can separately link an asset later, via the API.

In order to refresh an asset token the same access token and actor token should be used for the device.

Use it when integrating IoT devices that need specific tokens tied to unique device identities and Salesforce assets. For example, smart fridge installed at customer locations need to send telemetry to Salesforce in order to track the device state and automatically create repair/maintenance cases based on the telemetry data.

 

OAuth 2.0 Username-Password Flow

The client sends username, password, client ID and client secret, to directly obtain an access token. This flow is strongly discouraged in production because it transmits credentials back and forth. Refresh tokens are not issued for this flow. No user interaction needed.

Not intended for use in newly developed solutions. Can be supported for legacy systems integrations. 

 

OAuth 2.0 SAML Bearer Assertion Flow for Previously Authorized Apps

This flow uses a SAML assertion (signed XML) from an identity provider to get a Salesforce access token. Salesforce validates the SAML assertion and issues an access token. The only prerequisite is that the app should be already authorized for the client, for example, during the OAuth 2.0 authorization or preauthorized by the admin. No user interaction required. If the app has not been previously authorized, Salesforce may reject the request because the user has not granted access to that external client app.

Use when your users log in via an external SAML identity provider and you want to use that SAML assertion to obtain a Salesforce token without interactive login. For example, corporate SSO setup (like Okta) issues SAML assertions. An ERP system (client) uses a SAML assertion obtained during SSO from an identity provider to request a Salesforce access token and then calls Salesforce APIs on behalf of the user.

 

Below you will find a comparison table of all the OAuth 2.0 flows available.

Flow

Requires User Interaction

Security Level (relative)

Typical Use Case

Web Server

Yes

High

Authenticating an external web application that can securely store a client secret to access the Salesforce API impersonating a specific user.

User-Agent

Yes

Medium

Authenticating mobile or desktop apps where the source code is accessible and a client secret cannot be safely stored.

Refresh Token

No

High 

Maintaining long-term access for an application without requiring the user to re-authenticate when the initial access token expires.

Token Exchange

No

High

Exchanging a token from an external identity provider for a Salesforce access token to access data within a complex multi-app architecture.

Hybrid App

Yes

High

Seamlessly transitioning a mobile user from a native mobile app container to an embedded web view without a second login.

JWT Bearer

No

Very High

Enabling server-to-server integrations that need to impersonate a specific user.

Client Credentials

No

Medium

Allowing an application to access its own service-level data or perform administrative tasks as a system identity rather than a specific user.

Device Flow

Yes

High

Authorizing devices with limited input capabilities, such as smart TVs or IoT devices, by having the user complete the login on a separate web browser.

Asset Token

No

High

Efficiently registering and linking connected devices to Service Cloud Asset data using a specialized asset token.

Username-Password

No

Low

Legacy

SAML Bearer

No

High

Utilizing an existing SAML 2.0 assertion from a trusted identity provider to request an OAuth access token.

Headless Identity

No

High

Integrating fully non-interactive services

For more information, see https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_flows.htm&type=5


Dmitry Hatsenka
Certified Salesforce Developer
image
Expertise
Question to the expert
image

We have available resources to start working on your project within 5 business days

1 UX Designer

image

1 Admin

image

2 QA engineers

image

1 Consultant

image
Related Articles
All articles
image
Is Salesforce Winning the Public Sector Race?
An analysis of Salesforce's rapid expansion into the U.S. public sector, tracing its path from cautious early government licensing deals in the 2010s through the launch of Government Cloud in 2012, its pivotal role in COVID-19 vaccine rollouts, and its 2025–2026 push into military and intelligence work via Agentforce and Missionforce. The piece covers major 2026 contracts — including a $5.6 billion Army deal, a $1.6 billion VA agreement, and Pentagon Impact Level 5 authorization — alongside real-world case studies like California's REAL ID processing and the UK's NHS back-office operations. It also examines the structural obstacles still facing Salesforce and other vendors in government tech: legacy IT systems decades old, outdated federal procurement rules, budget constraints, and organizational caution around AI adoption, plus the competitive pressure from Palantir, Microsoft, and Oracle in the race for public sector AI spending.
28 August 2026
image
Why Your Salesforce Flows Are Agentforce's Biggest Problem
This article argues that the most underestimated risk in Agentforce deployments isn't data quality — it's the automation layer: years of overlapping Flows, Process Builder processes, Apex triggers, and managed package logic that no one has reviewed end-to-end. It explains why AI agents inherit automation complexity without the tribal knowledge human admins carry, why technical debt only becomes visible after an agent hits it in production, and why a clean demo is no indicator of production readiness. The article closes with a concrete, tool-by-tool inventory approach using Flow Trigger Explorer, Salesforce Optimizer, Setup Audit Trail, Apex Debug Logs, Agent Builder, and Health Check — scoped to the specific processes the agent will actually use rather than the whole org.
23 July 2026
image
How to Wire Multiple Salesforce Projects in One Org Without Breaking Everything
This article maps the real integration patterns that emerge when multiple Salesforce projects — both managed packages and unpackaged code — share a single org. It covers four concrete patterns: attaching custom triggers to package-owned objects, calling global members exposed by managed packages, writing directly into another project's objects, and runtime-guarded reads of package data. It then addresses access control for authenticated and guest users, including the Master-Detail wall and the without sharing elevation pattern. The piece closes with eight concrete risks (compile-time dependencies that block uninstall, upgrade coupling, silent cascade failures, access invisible to admins) and six actionable recommendations for keeping cross-project coupling manageable.
08 July 2026