One of the common misconceptions about OAuth is that it provides identity federation by itself. Although supporting OAuth with federated identities is a valid pattern and is essential to many API providers, it does require the combination of OAuth with an additional federated authentication mechanism. Note that I’m not talking about leveraging OAuth for federation (that’s OpenID Connect) but rather an OAuth handshake in which the OAuth authorization server (AS) federates the authentication of the user.
There are different ways to federate the authentication of an end user as part of an OAuth handshake. One approach is to simply incorporate it as part of the authorization server’s interaction with the end user (handshake within handshake). This is only possible with grant types where the user is redirected to the authorization server in the first place, such as implicit or autz code. In that case, the user is redirected from the app, to the authorization server, to the identity provider (IDP), back to the authorization server and finally back to the application. The federated authentication is transparent to the client application participating in the OAuth handshake. The OAuth spec (which describes the interaction between the client application and the OAuth authorization server) does not get involved.
Another approach is for the client application to request the access token using an existing proof of authentication in the form of a signed claims (handshake after handshake). In this type of OAuth handshake, the redirection of the user (if any) is outside the scope of the OAuth handshake and is driven by the application. However, the exchange of the existing claim for an OAuth access token is the subject of a number of extension grant types.
One such extension grant type is defined in the SAML 2.0 Bearer Assertion Profiles for OAuth 2.0 specification, according to which a client application presents a SAML assertion to the OAuth authorization server in exchange for an OAuth access token. The Layer 7 OAuth Toolkit has implemented and provided samples for this extension grant type since its inception.
Because of the prevalence of SAML in many environments and its support by many identity providers, this grant type has the potential to be leveraged in lots of ways in the enterprise and across partners. There is, however, an emerging alternative to bloated, verbose SAML assertions – one that is more “API-friendly”, based on JSON: JSON Web Token (JWT). JWT allows the representation of claims in a compact, JSON format and the signing of such claims using JWS. For example, OpenID Connect’s ID Tokens are based on the JWT standard. The same way that a SAML assertion can be exchanged for an access token, a JWT can also be exchanged for an access token. The details of such a handshake are defined as part of another extension grant type defined as part of JSON Web Token (JWT) Bearer Token Profiles for OAuth 2.0.
Give me a JWT, I’ll give you an access token. Although I expect templates for this extension grant type to be featured as part of an upcoming revision of the OAuth Toolkit, the recent addition of JWT and JSON primitives enables me to extend the current OAuth authorization server template to support JWT bearer grants with a Layer 7 Gateway today.
The first thing I need for this exercise is to simulate an application getting a JWT claim issued on behalf of a user. For this, I create a simple endpoint on the Gateway that authenticates a user and issues a JWT returned as part of the response.
Pointing my browser to this endpoint produces the following output:
Then, I extend the authorization server token endpoint policy to accept and support the JWT bearer grant type. The similarities between the SAML bearer and the JWT bearer grant types are most obvious in this step. I was able to copy the policy branch and substitute the SAML and XPath policy constructs for JWT and JSON path ones. I can also base trust on HMAC-type signatures that involve a share secret, instead of a PKI-based signature validation, if desired.
I can test this new grant type using a REST client calling the OAuth authorization server’s token endpoint. I inject into this request the JWT issued by the JWT issuer endpoint and specify the correct grant type.
I can now authorize an API call based on this new access token, as I would any other access token. The original JWT claim is saved as part of the OAuth session and is available throughout the lifespan of this access token. This JWT can later be consulted at runtime when API calls are authorized inside the API runtime policy.