OAuth 2.0 Token Exchange Handler Examples
| Available in: Enterprise, Unlimited, Performance, and Developer Editions |
During the OAuth 2.0 token exchange flow, when a user logs in to the primary app via the identity provider, the identity provider issues a token to the primary app. The primary app can’t use this token to directly access Salesforce data, but it can exchange the token for a Salesforce access token. To complete this exchange, the primary app uses an Apex token exchange handler. With the token exchange handler, Salesforce can issue its own access token by validating the identity provider’s token and mapping the token’s subject, which identifies the end user, to a Salesforce user.
To build an Apex token exchange handler, create a class that extends the Auth.Oauth2TokenExchangeHandler abstract class and customize its validation logic and subject mapping.
Token Exchange Handler Abstract Class
The Auth.Oauth2TokenExchangeHandler abstract class contains two methods. Use the first method, validateIncomingToken, to validate the identity provider’s token. Use the second method, getUserForTokenSubject, to map the token’s subject to a Salesforce user.
The way you build your validation and subject mapping processes depends on your use case, identity provider, and token type. Use these examples to get started.
Token Exchange Handler Example Implementation
This example implementation extends the Auth.Oauth2TokenExchangeHandler abstract class.
In this example, the OAuth2TokenExchangeType enum specifies that the token is a JSON Web Token (JWT). The first method, validateIncomingToken, uses a method in the Auth.JWTUtil class to validate the token by calling an endpoint on the external identity provider.
Validating the token returns an instance of the Auth.TokenValidationResult class with information about the token and the user.
With the second method, getUserForTokenSubject, the handler gets information about the user from the token validation result. The example shows two ways to bundle the user data—either by creating a class with a custom data structure or by using the Auth.UserData class.
After the handler gets the user data from the token, it looks for a Salesforce user matching the token subject. In this example, the handler doesn’t find a user, so it creates a User object. To finish creating the user, Salesforce automatically inserts the User object for you.
Examples for Validating Different Token Types
The custom logic for your implementation of the validateIncomingToken method depends on the token type. Here’s an overview of the options for different token types.
- For JWTs and ID tokens, use methods in the Auth.JWTUtil class.
- For opaque tokens, such as opaque access and refresh tokens, call out to the identity provider’s introspection or user info endpoints.
- For SAML assertions, write code to parse the XML from the assertion.
In this example, the handler validates a JWT from the identity provider. The handler determines the token type and uses the validateJWTWithKey method in the Auth.JWTUtil class to validate the JWT with a public key.
For opaque access tokens, which can’t be introspected locally on your app, call out to the introspection or user info endpoints on the external identity provider. In this example for validating an opaque token, the handler sends a POST request to the identity provider’s introspection endpoint and parses the identity provider’s JSON response so that Salesforce can understand it. It then validates the response using the validateIncomingToken method.
Example for Finding and Creating a User
During subject mapping, your handler finds the subject (end user) of the incoming token and tries to link it to a Salesforce user. Optionally, you can configure your handler to help create a Salesforce user if it can’t find one. The handler doesn’t technically create the user—instead, it returns a User object. Salesforce then automatically inserts the new user into the User object for you. To create the User object, the isUserCreationAllowed field on your OauthTokenExchangeHandler metadata definition must be set to true. When you set this metadata field to true, the CanCreateUser parameter in the getUserForTokenSubject Apex method is also set to true.
If necessary, to get more information about the incoming subject, the handler can call out to the external identity provider or another external system.
In this example implementation, the handler gets information about the user from the identity provider’s token and looks for an existing Salesforce user. If no user exists, it creates a User object.