apex-jwt-bearer-flow
OAuth 2.0 JWT Bearer Token Flow for server-to-server authentication from Apex — Connected App with certificate, Auth.JWT/Auth.JWS to mint signed assertions, token endpoint exchange, and the failure modes (clock skew, certificate not found, user not pre-authorized). NOT for user-context OAuth (use named-credentials-oauth-user-flow) or external client → Salesforce JWT (that is the inbound flow, configured in Connected App not Apex).
Best use case
apex-jwt-bearer-flow is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
OAuth 2.0 JWT Bearer Token Flow for server-to-server authentication from Apex — Connected App with certificate, Auth.JWT/Auth.JWS to mint signed assertions, token endpoint exchange, and the failure modes (clock skew, certificate not found, user not pre-authorized). NOT for user-context OAuth (use named-credentials-oauth-user-flow) or external client → Salesforce JWT (that is the inbound flow, configured in Connected App not Apex).
Teams using apex-jwt-bearer-flow should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/apex-jwt-bearer-flow/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How apex-jwt-bearer-flow Compares
| Feature / Agent | apex-jwt-bearer-flow | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
OAuth 2.0 JWT Bearer Token Flow for server-to-server authentication from Apex — Connected App with certificate, Auth.JWT/Auth.JWS to mint signed assertions, token endpoint exchange, and the failure modes (clock skew, certificate not found, user not pre-authorized). NOT for user-context OAuth (use named-credentials-oauth-user-flow) or external client → Salesforce JWT (that is the inbound flow, configured in Connected App not Apex).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Apex JWT Bearer Flow
The OAuth 2.0 JWT Bearer Token Flow lets server-side code obtain an
access token without a stored password and without an interactive
login. The client presents a short-lived JSON Web Token signed with
a private key; the authorization server (Salesforce, or an external
IdP) verifies the signature against a registered public key and
returns an access token.
In Salesforce Apex this comes up in two shapes. The outbound shape
is the one this skill covers: Apex calling a non-Salesforce system
(another Salesforce org, a Heroku service, an internal API, a
SaaS that supports JWT bearer) and needing an access token. The
two correct ways to implement it are (a) a Named Credential with
"JWT Bearer" auth — Salesforce manages the assertion and token
exchange for you — and (b) Apex that builds the assertion with
`Auth.JWT` and `Auth.JWS`, posts it to `/oauth2/token`, and parses
the response.
The inbound shape — an external system getting a token *into*
Salesforce via JWT — is configured entirely on the Connected App
("Use digital signatures" + uploaded certificate, "Pre-authorized"
profile/permset). No Apex is needed. That is out of scope for this
skill.
The mistakes are predictable. The JWT `exp` claim must be inside
the next ~5 minutes (Salesforce rejects assertions older than 5
minutes); `aud` must be the *server's* login URL (not your org's);
`sub` must be a username the Connected App has been pre-authorized
to issue tokens for; and the certificate used to sign must match
the public key uploaded to the Connected App. Any one of these
mismatches returns the same opaque `invalid_grant` error.
## Recommended Workflow
1. **Prefer Named Credentials over hand-rolled Apex.** Setup → Named
Credentials → New, choose "JWT Bearer" identity type. Salesforce
manages signing, refresh, and token caching. Reach for Apex
`Auth.JWT` only when the target system requires a non-standard
claim or a non-Salesforce IdP that Named Credentials does not
support.
2. **Generate or import the certificate in Setup → Certificate and
Key Management.** Use a self-signed certificate for sandboxes;
in production use a CA-issued certificate if the target system
requires it. Note the label — you reference it from `Auth.JWS`.
3. **Configure the Connected App on the target side.** Upload the
public key (the .crt exported from Setup), enable "Use digital
signatures", add the API scope you need, and pre-authorize the
user(s) the `sub` claim will identify (Profiles → Manage Profiles
or Permission Sets).
4. **Write the assertion builder.** Use `Auth.JWT` for the claims,
`Auth.JWS` to sign with the certificate label. Set `iss`
(consumer key), `sub` (username), `aud` (target login URL exactly
— `https://login.salesforce.com` or `https://test.salesforce.com`
for Salesforce-to-Salesforce), `exp` to now + 3 minutes.
5. **POST the assertion to the token endpoint.** Use form-encoded
body with `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer`
and `assertion=<jwt>`. Parse the response — `access_token` on
success, `{error, error_description}` on failure.
6. **Handle the failure responses, not just `invalid_grant`.**
`user hasn't approved this consumer` means pre-authorization is
missing; `invalid_assertion` usually means clock skew or wrong
`aud`; `invalid_client_id` means the `iss` doesn't match a
Connected App.
7. **Cache the access token until ~30s before expiry.** The token
endpoint is rate-limited (per-org, per-Connected-App). Re-exchange
only on expiry or on a 401 from the resource server.
## When To Reach For This Skill
Use it when a backend Apex job (Schedulable, Queueable, callout
from a trigger) needs to call an external system as a fixed service
account, and the target supports JWT bearer. Use it for org-to-org
integration where one org calls the other unattended. Use it when
storing a password (even encrypted) in Custom Metadata is
unacceptable — JWT bearer has no password.
Do not use it for user-context callouts. If the calling user's
permissions matter at the destination, use Named Credentials with
"Per User" auth and the standard OAuth web-server flow. JWT bearer
is impersonation by a service principal; it bypasses the user's
interactive login.
## What This Skill Does Not Cover
| Topic | See instead |
|---|---|
| Inbound JWT (external system → Salesforce) | `security/connected-app-jwt-inbound` (Connected App config; no Apex) |
| OAuth 2.0 user-agent / web-server flow | `apex/named-credentials-oauth-user-flow` |
| JWKS rotation and discovery endpoints | `integration/jwt-key-rotation` |
| MuleSoft / external orchestration of JWT | `integration/mulesoft-jwt-passthrough` |Related Skills
ip-range-and-login-flow-strategy
Design and implement Salesforce Login Flows (Screen Flows assigned to profiles or Experience Cloud sites) that run post-authentication to enforce conditional MFA, IP-based branching, terms-of-service acceptance, or user data collection. Covers Login Flow creation in Flow Builder, profile/site assignment, IP-aware decision logic, and ConnectedAppPlugin extension points. NOT for static IP allowlisting or profile Login IP Ranges (see network-security-and-trusted-ips), org-wide session policies, or SSO/SAML IdP configuration.
customer-data-request-workflow
Implement GDPR/CCPA data subject rights (access, deletion, rectification) using Salesforce Privacy Center and/or custom workflow. NOT for general backup or org-level data retention policy.
apex-managed-sharing-patterns
Grant row-level access programmatically via __Share records when declarative sharing rules cannot express the policy. NOT for OWD, role hierarchy, or criteria-based sharing rule design.
omnistudio-vs-flow-decision
Use when choosing between OmniStudio (OmniScript / Integration Procedure / FlexCard / DataRaptor) and Flow / Screen Flow / Apex for a given capability. Triggers: 'omnistudio or flow', 'omniscript vs screen flow', 'integration procedure vs subflow', 'flexcard vs lightning page'. NOT for general automation selection across Workflow/Process Builder/Apex (see automation-selection tree).
lwc-in-flow-screens
Use when building, reviewing, or troubleshooting a custom Lightning Web Component that runs inside a Flow screen element, covering @api props exposed to Flow, FlowAttributeChangeEvent for output, validate() for user input validation, and flow navigation events. Triggers: 'lwc in flow screen', 'FlowAttributeChangeEvent', 'flow screen component not updating', 'flow validate method', 'flow navigation from lwc'. NOT for custom property editors (use custom-property-editor-for-flow), NOT for embedding a flow inside an LWC (use flow/screen-flows), NOT for auto-launched flows.
lwc-imperative-apex
Call Apex methods imperatively from LWC — on button click, lifecycle hooks, or conditional logic. Covers import syntax, cacheable vs non-cacheable, async/await patterns, error handling, loading states, and Promise.all. NOT for wire service (use wire-service-patterns) and NOT for testing Apex mocks (use lwc-testing).
custom-property-editor-for-flow
Use when building or reviewing an LWC Custom Property Editor for Flow screen or action configuration, including the `configurationEditor` metadata hook, builder-side APIs, validation, and value-change events. Triggers: 'custom property editor', 'Flow configuration editor', 'builderContext', 'inputVariables', 'configurationEditor'. NOT for ordinary runtime screen-component behavior when no Flow Builder design-time customization is involved.
slack-workflow-builder
Use this skill when designing or troubleshooting Slack Workflow Builder workflows that call Salesforce — especially the Salesforce connector step Run a Flow, mapping inputs/outputs, handling failures, and understanding limits. Triggers on: Slack Workflow Builder Salesforce, Run a Flow from Slack, autolaunched flow from Slack, Slack automation calling Salesforce. NOT for Salesforce Flow Builder tutorials unrelated to Slack (use flow skills), not for Flow Core Actions that send Slack messages from Salesforce (use flow-for-slack), not for initial org-to-workspace connection (use slack-salesforce-integration-setup), and not for building custom Slack apps outside Workflow Builder.
oauth-flows-and-connected-apps
Use when choosing or reviewing Salesforce OAuth flows and connected-app policy for integrations, including client credentials, JWT bearer, authorization code, device flow, scopes, and token lifecycle controls. Triggers: 'OAuth flow', 'connected app', 'client credentials', 'JWT bearer', 'refresh token', 'integration user'. NOT for record-level sharing design or for simple Named Credential usage when the auth-flow decision is already settled.
dataweave-for-apex
Use when transforming structured data inside Apex — CSV → JSON, XML → SObject list, JSON → flattened CSV, or schema-mapping a third-party payload to a Salesforce model — and the existing options (`JSON.deserialize`, `Dom.Document`, hand-written loops) are getting unwieldy. Triggers: 'apex transform csv json xml without external library', 'system.dataweave script', 'salesforce native dataweave apex execute', 'transform xml to sobject apex no mulesoft', 'json reshape salesforce apex script'. NOT for MuleSoft Anypoint DataWeave running off-platform (use mulesoft-anypoint-architecture), NOT for Apex JSON serialization basics (use apex-json-serialization), NOT for Bulk API CSV ingest (use bulk-api-2-patterns).
workflow-rule-to-flow-migration
Migrate Workflow Rules to record-triggered Flows: field update mapping, email alert migration, outbound message alternatives using Flow Core Actions, time-based workflow replacement with Scheduled Paths. NOT for Process Builder migration (use process-builder-to-flow-migration), NOT for building new flows from scratch.
subflows-and-reusability
Use when extracting reusable Flow logic into subflows, defining input and output variables, keeping parent flows maintainable, and sharing common automation contracts across multiple flows. Triggers: 'reuse this flow logic', 'how should subflow variables work', 'too much duplicated flow logic', 'subflow contract design'. NOT for Apex-called Flow execution direction or Flow Orchestration process design.