What is JWT flow in Salesforce?

Overview

The JWT (JSON Web Token) Bearer Token Flow in Salesforce is an OAuth 2.0 server-to-server authentication method that allows a trusted application to obtain an access token without interactive user login. It is ideal for automated integrations, backend services, and CI/CD pipelines where human intervention is not possible or desirable.

When to use JWT flow

Use JWT flow when you need:

  • Server-to-server authentication without redirecting a user to a login page.
  • Short-lived access tokens issued by Salesforce based on a signed JWT assertion.
  • Secure integrations where a private key can be safely stored on the client/server side.

High-level steps

JWT flow in Salesforce follows these steps:

  1. Create a Connected App in Salesforce and enable the digital signature (upload the public certificate).
  2. Generate a key pair (private key + public certificate). Keep the private key secure; upload the certificate to the Connected App.
  3. Build a JWT assertion (header, payload) that includes the connected app client_id and the Salesforce username (sub).
  4. Sign the JWT using the private key (typically RS256).
  5. POST the JWT assertion to Salesforce’s token endpoint with grant_type set to urn:ietf:params:oauth:grant-type:jwt-bearer.
  6. Salesforce validates the signature, the certificate, the audience (aud), and the subject (sub) and, if valid, returns an access_token.

JWT structure (Salesforce specifics)

Typical JWT elements for Salesforce:

  • iss (issuer) — the connected app’s Consumer Key (client_id).
  • sub (subject) — the username (user’s login) or user id of the Salesforce user on whose behalf the request is made.
  • aud (audience) — the Salesforce token endpoint. Use https://login.salesforce.com for production / developer orgs or https://test.salesforce.com for sandboxes. Using the full token endpoint URL (including /services/oauth2/token) is also accepted.
  • exp (expiration) — must be a short-lived timestamp (e.g., current time + 3 minutes). Salesforce requires a short expiry to limit replay attacks.

Example JWT payload

{
"iss": "3MVG9...your_consumer_key...",
"sub": "[email protected]",
"aud": "https://login.salesforce.com",
"exp": 1620000000
}

Example: Requesting a token with curl

curl -X POST https://login.salesforce.com/services/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=BASE64URL_ENCODED_JWT"

If the assertion is valid, Salesforce returns JSON including access_token, instance_url, and token lifetime.

Creating keys & certificate

Generate an RSA key pair and create a certificate (self-signed if acceptable for your org):

# Generate private key
openssl genrsa -out server.key 2048

# Create a self-signed certificate
openssl req -new -x509 -key server.key -out server.crt -days 365

Upload server.crt (public certificate) in your Connected App under “Use Digital Signature”. Keep server.key safe on the client/server side to sign JWTs.

Connected App settings

  • Enable OAuth settings and add required scopes (e.g., Full access (full) or api).
  • Enable “Use Digital Signature” and upload the certificate.
  • Note the Consumer Key (client_id) — it becomes the iss in the JWT.
  • Ensure the target user (the sub) has access to the connected app if the app policy requires admin approval.

Common pitfalls & troubleshooting

  • invalid_grant: Causes include wrong audience (aud), incorrect sub (username), mis-signed JWT, or expired exp.
  • Certificate mismatch: Make sure the uploaded certificate in the Connected App matches the public key used to verify the JWT signature.
  • User not authorized: If the connected app has profile/permission restrictions, ensure the user is assigned or admin-approved.
  • Clock skew & expiration: Ensure your server clock is accurate and the exp is not in the past. Keep the expiration short (a few minutes).

Security considerations

Keep the private key protected (hardware security module or secure key store). Rotate keys/certificates periodically. Limit Connected App scopes and require admin approval where needed.

Code examples / libraries

Many languages have JWT libraries to create and sign assertions (Node.js: jsonwebtoken, Java: nimbus-jose-jwt, Python: PyJWT). Example Node.js flow:

// Node (pseudo)
const jwt = require('jsonwebtoken');
const payload = { iss: CONSUMER_KEY, sub: USERNAME, aud: 'https://login.salesforce.com', exp: Math.floor(Date.now()/1000) + 180 };
const token = jwt.sign(payload, PRIVATE_KEY, { algorithm: 'RS256' });
// POST token as assertion to /services/oauth2/token

Summary

The JWT Bearer Token Flow provides a secure, non-interactive OAuth 2.0 flow for server-to-server integrations with Salesforce. It requires setting up a Connected App with a public certificate, signing a short-lived JWT with a private key, and exchanging the assertion at the Salesforce token endpoint to receive an access token.