Implementing JWT Profile for OAuth2 Access Tokens

Written by Simon Moffatt

image

There is a new IETF draft stream called JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens. This is a very early 0 version, that looks to describe the format of OAuth2 issued access_tokens.

Access tokens, are typically bearer tokens, but the OAuth2 spec, doesn’t really describe what format they should be. They typically end up being two high level types – stateless and stateful. Stateful just means “by reference”, with a long opaque random string being issued to the requestor, which resource servers can then send back into the authorization service, in order to introspect and validate. On their own, stateful or reference tokens, don’t really provide the resource servers with any detail.

The alternative is to use a stateless token – namely a JSON Web Token (JWT). This new spec, aims to standardise what the content and format should be.

From a ForgeRock AM perspective, this is good news. AM has delivered JWT based tokens (web session, OIDC id_tokens and OAuth2 access_tokens) for a long time. The format and content of the access_tokens, out of the box, generally look something like the following:

The out of the box header (using RS256 signing):

image

The out of the box payload:

Note there is a lot of stuff in that access_token. Note the cnf claim (confirmation key). This is used for proof of possession support which is of course optional, so you can easily reduce the size by not implementing that. There are several claims, that are specific to the AM authorization service, which may not always be needed in a stateless JWT world, where perhaps the RS is performing offline validation away from the AS.

In AM 6.5.2 and above, new functionality allows for the ability to rapidly customize the content of the access_token. You can add custom claims, remove out of the box fields and generally build token formats that suit your deployment. We do this, by the addition of scriptable support. Within the settings of the OAuth2 provider, note the new field for OAuth2 Access Token Modification Script.

image
The scripting ability, was already in place for OIDC id_tokens. Similar concepts now apply.

The draft JWT profile spec, basically mandates iss, exp, aud, sub and client_id, with auth_time and jti as optional. The AM token already contains those claims. The perhaps only differing component, is that the JWT Profile spec – section 2.1 – recommends the header typ value be set to “at+JWT” – meaning access token JWT, so the RS does not confuse the token as an id_token. The FR AM scripting support, does not allow for changes to the typ, but the payload already contains a tokenName claim (value as access_token) to help this distinction.

If we add a couple of lines to the out of the box script, namely the following, we cut back the token content to the recommended JWT Profile:

accessToken.removeField(“cts”);
accessToken.removeField(“expires_in”);
accessToken.removeField(“realm”);
accessToken.removeField(“grant_type”);
accessToken.removeField(“nbf”);
accessToken.removeField(“authGrantId”);
accessToken.removeField(“cnf”);

The new token payload is now much more slimmed down:

image
The accessToken.setField(“name”, “value”) method, allows simple extension and alteration of standard claims.

For further details see the following documentation on scripted token content – ForgeRock Access Management 6.5 > OAuth 2.0 Guide