Prerequisites
To follow this guide, you’ll need:- A Superblocks organization with enterprise SSO configured using an OIDC-based identity provider (for example, Okta OIDC or Microsoft Entra ID)
- A Salesforce org (production or sandbox) with API access enabled
- Salesforce System Administrator profile or a profile with the following permissions:
- Manage External Client Apps
- View Setup and Configuration
- Customize Application
- Author Apex
Token exchange flow
When using this auth method:- Your user logs in to Superblocks using your enterprise SSO identity provider (for example, Okta)
- When the user runs a Superblocks API that includes a Salesforce step, a request is sent from the browser to the Superblocks Data Plane, including the user’s identity provider (IDP) JWT
- The Superblocks Agent extracts the user’s IDP access token and sends a token exchange request to Salesforce’s OAuth token endpoint using the
urn:ietf:params:oauth:grant-type:token-exchangegrant type as defined in RFC 8693 - Salesforce invokes the custom APEX Token Exchange Handler you deploy, which validates the IDP token, extracts the user’s email, and maps it to a Salesforce user
- Salesforce returns a scoped access token for that user
- The Superblocks Data Plane uses the access token to execute the Salesforce API call on behalf of the user
Setup instructions
Step 1: Create a Salesforce External Client App
An External Client App registers Superblocks as an OAuth client in your Salesforce org and enables the Token Exchange grant type.- Log in to Salesforce and navigate to Setup
- In the Quick Find box, search for External Client Apps Manager
- Click New External Client App
-
Fill in the Basic Information section:
- External Client App Name:
Superblocks - API Name:
Superblocks(auto-populated) - Contact Email: your administrator email
- External Client App Name:
- In the OAuth Settings section, check Enable OAuth Settings
-
Set Callback URL to
https://login.salesforce.com/services/oauth2/success -
Under OAuth Scopes, add the following scopes:
Manage user data via APIs (api)Perform requests on your behalf at any time (refresh_token, offline_access)— optional, only needed if your use case requires offline access
- Scroll down to the OAuth 2.0 Token Exchange Flows section and check Enable Token Exchange Flow
- Click Save, then click Continue
- From External Client App Manager, click the arrow next to your app and select Edit Settings
- Click the Settings tab, scroll down and open the OAuth Settings dropwdown
- Click on Consumer Key and Secret (you may need to verify via email)
- Copy and save the Consumer Key (Client ID) and Consumer Secret (Client Secret) — you will need these when configuring the Superblocks integration
- Go back to External Client App Manager, click the arrow next to your app and select Edit Policies
- Under OAuth Policies → Permitted Users, select Admin approved users are pre-authorized
Step 2: Write the APEX Token Exchange Handler
Salesforce requires a custom APEX class that extends Auth.Oauth2TokenExchangeHandler. This handler is responsible for validating the incoming JWT and mapping it to a Salesforce user. When Salesforce receives a token exchange request, it invokes this handler, which is responsible for validating the incoming IDP access token and mapping the incoming identity provider token to the Salesforce user for whom Salesforce should issue the exchanged access token. The handler below decodes the IDP access token (a JWT), extracts theemail claim, and looks up the matching active Salesforce user.
Deploy the handler class
- In Salesforce Setup, search for Developer Console and open it (or use the Salesforce CLI / VS Code Salesforce Extension)
- Go to File → New → Apex Class
- Name the class
SuperblocksTokenExchangeHandler - Replace the default content with the following:
- Click Save
Optional: validate the token signature
The example above decodes the JWT payload without verifying the signature. For production environments, you may want to add signature validation using your IDP’s public JWKS endpoint. Salesforce provides theAuth.JWTUtil class for this purpose, or you can make a callout to your IDP’s jwks_uri endpoint to retrieve the public key.
If you implement signature validation, you will need to add your IDP’s JWKS endpoint to the Salesforce Remote Site Settings (Setup → Remote Site Settings → New Remote Site).
Step 3: Create and Configure the Token Exchange Handler
Salesforce requires a Token Exchange Handler record to link your Apex class to your External Client App.- In Salesforce Setup, search for Token Exchange Handlers
- Click New
-
Configure the following:
- Name: Superblocks Token Exchange Handler
- Apex Class: SuperblocksTokenExchangeHandler
- Supported Token Types: JWT
- Save
Link the handler to your app
- Open the Token Exchange Handler you just created
- Click Enable New App
- Select your External Client App
-
Configure:
- Run As User: Select a valid Salesforce user that the handler should run as. This user provides the execution context for the handler itself and must have sufficient permissions to perform user lookup and validation logic. The Salesforce user for whom the access token is issued is still determined dynamically by the handler based on the incoming token.
- Save
Step 4: Configure the Superblocks integration
Once your Salesforce External Client App and APEX handler are in place and the Token Exchange Handler is linked, configure the Salesforce integration in Superblocks.- In Superblocks, navigate to the Integrations page
- Search for Salesforce and click New Integration (or edit an existing one)
- In the Authentication dropdown, select OAuth 2.0 Token Exchange
- Set Subject token source to Login Identity Provider
-
Fill in the remaining fields using the values from your External Client App:
Field
Required Description Token URL ✓ https://login.salesforce.com/services/oauth2/tokenfor production orgs. Usehttps://test.salesforce.com/services/oauth2/tokenfor sandbox orgs.Client ID ✓ The Consumer Key from your External Client App Client secret ✓ The Consumer Secret from your External Client App Scope ✗ api— required to make Salesforce REST API calls. Add additional scopes separated by spaces as needed. - Click Test Connection to verify the configuration, then click Save
Testing & troubleshooting
Test the integration
With the integration configured, verify that it works end-to-end:- In a Superblocks application, create a new Backend API
- Add a step that uses your Salesforce integration
- Add a SOQL query step, for example:
Where
$userIdresolves to the current Salesforce user - Click Run API
Common errors
Error message | Why it’s happening | Resolution |
|---|---|---|
Could not find identity provider token | The user is not logged in via an enterprise SSO connection, or the SSO connection is not configured to issue OIDC access tokens | Confirm that your Superblocks SSO uses an OIDC-based flow. Contact support@superblocks.com if you need assistance. |
Identity provider token expired | The user’s IDP session has expired | Ask the user to refresh the browser or log out and back in to obtain a fresh IDP token |
Could not find a user JWT | The integration is being used in a Workflow, Scheduled Job, or public App where there is no logged-in user context | Token Exchange requires an active user session. Use this integration type in Backend APIs only, not in Workflows or Scheduled Jobs. |
Token exchange failed | Superblocks received an error from the Salesforce token endpoint | Check the error details returned by Salesforce. Common causes: the External Client App is not yet provisioned (wait a few minutes after creation), the Token Exchange Flow is not enabled on the External Client App, or the handler class is not linked. |
MISSING_EMAIL_CLAIM (from your APEX handler) | The IDP access token does not include an email claim | Update the SuperblocksTokenExchangeHandler to use the claim name your IDP includes. Check the IDP access token using jwt.io to confirm the correct claim. |
USER_NOT_FOUND (from your APEX handler) | No active Salesforce user was found with the email from the IDP token | Verify that the user exists in Salesforce with an exactly matching email address (case-insensitive) and that their account is active. |

