A Crash Course in the Assertion Framework for OAuth 2.0 Client Authentication and
Authorization Grants

It’s as exciting as it sounds

James Collerton
4 min readFeb 3, 2023
Granting you access!

Audience

This article assumes you have a solid understanding of OAuth2.0, HTTP and JWT tokens, and are looking to get an overview of RFC7521. We will be covering how to use assertions (defined shortly) to authenticate clients and/ or procure access tokens.

We will be demonstrating using an example from RFC7523 and implementing JWT tokens as assertions.

If you’re not quite up to speed on OAuth2.0, I recommend reading through my previous articles, which I’ve compiled in a list here.

Argument

Before we go any further, here’s some core definitions: assertions, relying parties and authorization grants.

Defining Core Terms

An assertion is a collection of information for sharing identity and security information across security domains. A good example is a JWT token.

Normally assertions include a subject (who the assertion relates to), the issuer (who stamps their approval of the subject) and the context of when it’s valid (where and when it can be used). The exact requirements for our RFC are here.

In a JWT these could correspond to the iss , sub , nbf and exp claims (where nbf is ‘not before’, or when it’s valid from).

How an assertion is retrieved, formed, and exactly what it looks like, can be different depending on the implementation. For the purpose of the spec we can assume we have obtained one somehow, as procuring assertions is outside the spec scope.

For the sake of the RFC, assertions must always be signed to prove their authenticity (which JWTs usually are).

The relying party is whoever is consuming the assertion. In our case it will be the authorization aerver.

An authorization grant is a set of intermediate credentials representing the authorization granted by a resource owner, which can be exchanged for access tokens. In this case it’s our assertion.

Now we’ve got the basics down, let’s outline the two use cases.

Client Authentication

There are two types of client in OAuth2.0: public and confidential. What separates the two is that confidential clients can keep a client secret. There is a step in the OAuth2.0 spec where confidential clients can authenticate to the authorization server to prove they are who they say they are.

Assertions can be used for this authentication step as they demonstrate that a client has access to a key, via the signature. This key (or key pair) forms the client secret.

Pictoral representation of using assertions for client authentication

The above is use case one. This is not the same thing as using an assertion to procure access tokens!

This authentication implementation can be used as part of other authorization grants that don’t rely on assertions at all! An example of using it alongside the authorization code grant is below:

POST /token HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&
client_assertion=ABChbW...[omitted for brevity]...ZT

Note the extra parameters.

Using Assertions to Get Access Tokens

The second use case involves how we get access tokens using an assertion. Let’s introduce one other entity, the secure token server.

The secure token server is a party separate to the client, which issues the assertion. This is synonymous with the issuer inside the assertion itself, and they should have the keys used to sign it.

Generally we assume there is a trust-relationship between the authorization server and the secure token server. This relationship can be manifest in the secure token server exposing the public keys used to sign assertions, and the authorization server being happy to use them for verifying signatures.

We use the regular /token endpoint, with the grant type as a URI the authorization server has defined and knows the format of (for example urn:ietf:params:oauth:grant-type:jwt-bearer). We attach the assertion to the assertion parameter and can optionally specify scopes. An example request is below.

     POST /token HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&assertion=abcdeVydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU
[...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-

The authorization server then:

  • Retrieves the issuer from the assertion and can use it to do things like get the required keys for checking the signature.
  • Acknowledges they are issuing access tokens for the party in the subject field.
  • Check the audience is the authorization server.
  • Check the assertion is valid according to any fields it has specified (e.g. nbf or exp).

Error responses are defined here, and the success response is the standard one as defined in the OAuth2.0 core spec. A pictoral representation is below.

How to use an assertion as an authorization grant

Conclusion

And that’s it! It’s a tricky one to get your head round at the start, but knowing what assertions are conceptually, and separating out the authentication and procuring access tokens use cases, should help.

--

--

James Collerton

Senior Software Engineer at Spotify, Ex-Principal Engineer at the BBC