JWT and SAML assertion grants
All domains, credentials, assertions, and tokens in these examples are fictional.
Harbor Studio, a small design agency, keeps its client photo shoots in a business account with the photo service. Its designers sign in each morning to the agency's project portal through Harbor's own identity provider. When a designer opens a project, the portal should show that designer the photos they are allowed to see.
The portal could send each designer through the photo service's authorization flow. But Harbor has already authenticated them, and Harbor's administrator has already arranged with the photo service which designers may see which shoots. Another round of redirects and approval screens would repeat a decision that has been made.
Bringing proof from somewhere else
An assertion is a signed statement from an issuer about a subject, such as "this is designer-42, and Harbor's identity provider vouches for it until 09:05." The assertion grants let a client present an assertion like that at the token endpoint in place of an authorization code. If the authorization server trusts the issuer, it can issue an access token directly.
That trust has to be arranged in advance. For this example, the photo service has been configured to accept assertions signed by Harbor's identity provider, for Harbor's business account, when presented by Harbor's portal. Without that arrangement, a well-formed assertion from Harbor would mean nothing to the photo service, just as a letter of introduction means nothing from someone you have never heard of.
Two formats are common. A JSON Web Token, or JWT, is compact and widely used between services. A SAML assertion is written in XML and is common where an organization already uses SAML for single sign-on. The idea is the same in both, and so are most of the checks.
Presenting a JWT
Harbor's identity provider issues a short-lived JWT for the photo service. Decoded, its claims might read:
{
"iss": "https://idp.harbor.example",
"sub": "designer-42",
"aud": "https://auth.photos.example/token",
"iat": 1790758800,
"exp": 1790759100,
"jti": "demo-assertion-61"
}
iss names the issuer, and sub names the designer. aud names the photo service's authorization server as the intended recipient. iat and exp record when it was issued and when it expires, five minutes apart. jti gives this assertion a unique identifier. The whole token is signed with a key that belongs to Harbor's identity provider.
The portal sends it to the token endpoint:
POST /token HTTP/1.1
Host: auth.photos.example
Authorization: Basic aGFyYm9yLXBvcnRhbDpkZW1vLW9ubHktbm90LWEtcmVhbC1zZWNyZXQ=
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6ImhhcmJvci0yMDI2In0...
&scope=photos.read
The assertion is shortened here for display. The portal also authenticates as a client in this example. The assertion speaks for the designer, and the client authentication speaks for the portal. Keeping both lets the photo service limit which applications may present Harbor's assertions.
The same assertion format appears in another place, which is easy to confuse with this one. A client can also use a signed JWT to authenticate itself, instead of a client secret. That JWT is about the client, and it is sent in separate client authentication parameters. Here, the JWT is the grant: it is about the designer, and it takes the place of the authorization code. Clients and registration will cover signed JWTs used for client authentication.
Presenting a SAML assertion
If Harbor's identity provider speaks SAML, it can issue a SAML assertion for the same purpose. A heavily abbreviated version shows the parts that matter here:
<saml:Assertion ID="demo-assertion-62" IssueInstant="2026-09-30T09:00:00Z">
<saml:Issuer>https://idp.harbor.example</saml:Issuer>
<ds:Signature>...</ds:Signature>
<saml:Subject>
<saml:NameID>designer-42</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData
Recipient="https://auth.photos.example/token"
NotOnOrAfter="2026-09-30T09:05:00Z"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions>
<saml:AudienceRestriction>
<saml:Audience>https://auth.photos.example/token</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
</saml:Assertion>
The same questions have different spellings. Issuer says who vouches, NameID names the designer, Audience and Recipient name the photo service's token endpoint, and NotOnOrAfter sets the deadline. The portal Base64url-encodes the XML and sends it with the grant type urn:ietf:params:oauth:grant-type:saml2-bearer.
Look closely at the audience. The assertion Harbor's identity provider gave the portal when the designer signed in that morning was addressed to the portal. This one is addressed to the photo service. An assertion is written for a particular recipient, and a recipient should reject one addressed to someone else, even if the signature is genuine. The portal cannot simply forward its own sign-in assertion.
What the server checks
Before issuing anything, the photo service's authorization server works through the assertion:
- The issuer is one it has been configured to trust, and the signature verifies with that issuer's key.
- The audience names this authorization server.
- The assertion has not expired, and it is not being used before it became valid.
- It has not been seen before, when the server tracks identifiers such as
jtito stop replays. - The subject maps to an account covered by the trust arrangement, here a designer in Harbor's business account.
- This client is allowed to present assertions from this issuer, and the requested scope fits the arrangement.
Notice what is missing: nobody saw a consent screen. The authority for this access comes from the arrangement Harbor's administrator made with the photo service. That is appropriate for an organization's own accounts, and it is why the arrangement should be narrow. It should name the issuers, the accounts they may speak for, the clients that may present their assertions, and the scopes available. An identity provider trusted to vouch for Harbor's designers should not be able to vouch for your personal photo account.
These are bearer assertions. Anyone who obtains one can present it, so they are short-lived and addressed to one recipient, and the portal should treat them as carefully as tokens. The access token that comes back is an ordinary access token. The photo API never sees the assertion and validates the token as usual.
Assertion grants turn one kind of trusted statement into an access token. Token exchange, covered in Advanced OAuth, generalizes the idea to trading one token for another with a different audience or scope, and to recording when one party acts on behalf of another.