OAuth 2.0 SAML Bearer Assertion Flow for Previously Authorized Apps
With the OAuth 2.0 SAML bearer assertion flow, a client—via a connected app—can use previous authorization by supplying a signed SAML 2.0 assertion to request an OAuth access token. The digital signature applied to the SAML assertion authenticates the authorized app. A SAML assertion is an XML security token issued by an identity provider and consumed by a service provider. The service provider relies on its content to identify the assertion’s subject for security-related purposes.
Required Editions
| Available in: both Salesforce Classic and Lightning Experience |
| Available in: All Editions |
The OAuth 2.0 SAML bearer assertion flow is similar to a refresh token flow within OAuth. The
SAML assertion is posted to the OAuth token endpoint, which in turn processes the assertion
and issues an access_token based on prior approval of the
app. However, the client isn’t required to have or store a refresh_token, nor is it required to pass a client_secret to the token endpoint.
The OAuth 2.0 SAML bearer assertion flow involves these steps.
- Create a connected app and register an X509 Certificate. This certificate corresponds to
the private key of the app. When the connected app is saved, a consumer key (OAuth
client_id) is generated and assigned to the app. - Write an app that generates a SAML assertion and signs it with the private key.
- To implement the flow, the connected app posts the SAML bearer assertion to the Salesforce token endpoint.
- Salesforce validates the signature using the certificate registered for the connected app. In addition, it validates the audience, issuer, subject, and validity of the assertion.
- Assuming that the assertion is valid and that the user or admin authorized the app
previously, Salesforce issues an access token.
Note This flow doesn’t support refresh tokens.
Create a SAML Bearer Assertion
Create a valid SAML bearer assertion that includes these parameters.
| Parameter | Description |
|---|---|
Issuer
|
The value must be the connected app’s OAuth client_id for which the developer registered their certificate. |
Audience
|
The value must be https://login.salesforce.com or https://test.salesforce.com. |
Recipient
|
The value must be one of these URLs.
|
Subject NameID
|
This value must be the username of the Salesforce user. |
The SAML bearer assertion must also conform to these rules.
- The assertion must be signed according to the XML Signature specification, using RSA and either SHA-1 or SHA-256.
- The SAML assertion must conform with the general format rules specified here: http://tools.ietf.org/html/draft-ietf-oauth-saml2-bearer.
- When posted to the token endpoint, the assertion must be encoded using base64url encoding as defined here: http://tools.ietf.org/html/rfc4648#page-7
Here’s a sample assertion.
<?xml version="1.0" encoding="UTF-8"?>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_cd3649b3639560458bc9d9b33dfee8d21378409114655" IssueInstant="2013-09-05T19:25:14.654Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">3MVG9PhR6g6B7ps45QoRvhVGGMmR_DT4kxXzVXOo6TTHF3QO1nmqOAstC92 4qSUiUeEDcuGV4tmAxyo_fV8j</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_cd3649b3639560458bc9d9b33dfee8d21378409114655">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>N8DxylbIeNg8JDO87WIqXGkoIWA=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
XV0lFJrkhJykGYQbIs0JBFEHdt4pe2gBgitcXrscNVX2hKGpwQ+WqjF8EKrqV4Q3/Q4KglrXl/6s
xJr6WOmxWtIQC4oWhSvVyfag34zQoecZeunEdFSMlnvPtqBVzJu9hJjy/QDqDWfMeWvF9S50Azd0
EhJxz/Ly1i28o4aCXQQ=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIICOzCCAaSgAwIBAgIGAR7RRteKMA0GCSqGSIb3DQEBBQUAMGExCzAJBgNVBAYTAlVTMQswCQYD
VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzENMAsGA1UEChMEUEFDUzENMAsGA1UECxME
U0ZEQzEPMA0GA1UEAxMGU0FNTDIwMB4XDTA5MDExMzE4MzUyN1oXDTE0MDExMTE4MzUyN1owYTEL
MAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQK
EwRQQUNTMQ0wCwYDVQQLEwRTRkRDMQ8wDQYDVQQDEwZTQU1MMjAwgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAJNGcu8nW6xq2l/dAgbJmSfHLGRn+vCuKWY+LAELw+Kerjaj5Dq3ZGW38HR4BmZk
sG3g4eA1RXn1hiZGI1Q6Ei59QE/OZQx2zVSTb7+oIwRcDHEB1+RraYT3LJuh4JwUDVfEj3WgDnTj
E5vD46l/CR5EXf4VL8uo8T40FkA51AhTAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAehxggY6tBl8x
1SSvCUyUIHvxssAn1AutgZLKWuR1+FXfJzdVdE2F77nrV9YifIERUwhONiS82mBOkKqZZPL1hcKh
KSnFZN2iWmm1sspL73I/eAwVsOUj+bS3v9POo4ceAD/QCCY8gUAInTH0Mq1eOdJMhYKnw/blUyqj
Zn9rajY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">test@example.org</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:SubjectConfirmationData NotOnOrAfter="2013-09-05T19:30:14.654Z" Recipient="https://login.salesforce.com/services/oauth2/token"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2013-09-05T19:25:14.654Z" NotOnOrAfter="2013-09-05T19:30:14.654Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:AudienceRestriction xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Audience>https://login.salesforce.com/services/oauth2/token</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2013-09-05T19:25:14.655Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:AuthnContext xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
Request an Access Token
The connected app posts SAML bearer assertions to the Salesforce token endpoint.
Here’s a sample token request.
POST /services/oauth2/token HTTP/1.1
Host: login.salesforce.com
Content-Type: application/x-www-form-urlencoded
grant_type= urn:ietf:params:oauth:grant-type:saml2-bearer&
assertion=PHNhbWxwOl...[omitted for brevity]...ZT
When posted, these parameters must be provided.
| Parameter | Description |
|---|---|
grant_type
|
The OAuth 2.0 grant type that the connected app requests. The value must be urn:ietf:params:oauth:grant-type:saml2-bearer |
assertion
|
The SAML bearer assertion, encoded using base64url as defined here: http://tools.ietf.org/html/rfc4648#page-7. |
You can also include these standard parameters.
| Parameter | Description |
|---|---|
format
|
If not included in the request’s header, you can specify the expected return
format. The
|
scope
|
You can’t specify scopes in a SAML bearer assertion flow. Instead, the value for this parameter is the combination of scopes issued from previous access tokens. |
Salesforce Grants an Access Token
After the request is verified, Salesforce sends a response to the client. Token responses
for the OAuth 2.0 SAML bearer token flow follow the same format as authorization_code flows, although a refresh_token is never issued.

