Consuming responses with JWT Security Authorization Response Mode

Consuming responses with JWT Security Authorization Response Mode

tutorials

A draft extension to the OpenID Connect Foundation’s Financial-Grade APIs — JWT Secured Authorization Response Mode for OAuth 2.0 adds another level of security to handling responses from the Authorization Server. When a client receives a redirect response from the Authorization server, it contains sensitive parameters. These can be the authorization code (in the authorization code flow) or an ID and access token (in implicit or hybrid flows). These parameters are subject to substitution attacks and there are applications which require a greater level of certainty of their authenticity. In these scenarios JARM can be used, so that the Authorization Server returns these parameters in a signed JWT.

This tutorial shows how to work with JARM in the Curity Identity Server.

Prerequisites

Make sure that you’re running the Curity Identity Server in version 6.3.0 or later. If running a clean instance of the Curity Identity Server, make sure to configure it at least with the basic configuration.

JWT Response Modes

To enable JARM no specific settings are required. It’s enough to have OIDC enabled (in Profiles -> Token Service -> General) and JSON Web Tokens enabled for the default Token Issuer (in Profiles -> Token Service -> Token Issuers).

When these two settings are on, then The Curity Identity Server is able to issue responses as signed JWTs. You can see if your instance supports JARM by checking the value of the response_modes_supported metadata parameter published at the .well-known/openid-configuration endpoint. It should contain response modes with names ending with .jwt.

Requiring JARM

In some cases it might be useful to require your clients to use JARM. Clients will have to use one of the response modes defined by JARM, if this option is required. Other requests will be rejected. You can enforce secure responses on three different levels in The Curity Identity Server:

  • Globally for all clients, by going to Profiles -> Token Service -> General.
  • For a given client, by going to Profiles -> Token Service -> Clients -> Chosen client -> Client Application Settings -> Advanced.
  • For non-templatized dynamically registered clients, by going to Profiles -> Token Service -> Dynamic Registration -> Non-templatized. Note that the toggle will show only if Code or Implicit flows are enabled.

Require JARM

Test the Flow

To test the flow create a usual authorization request and add the response_mode parameter, with one of those values:

  • query.jwt — the response JWT will be sent in the query string in the response parameter.
  • fragment.jwt — the response JWT will be sent in the fragment part of the URL, in the response parameter.
  • form_post.jwt — the response will contain an auto-submitted HTML form with the response JWT in a hidden field.
  • jwt — this will use the default response mode depending on the response type (e.g. query.jwt for code response type and fragment.jwt for token response type).

For example, this request will receive the response JWT in the query part of the redirect URI (line breaks added for readability):

https://idsvr.example.com/oauth/v2/oauth-authorize?
    client_id=your-client-id
    &response_type=code
    &response_mode=jwt    &redirect_uri=http://localhost:8080/cb

After authenticating the user, the Authorization Server will redirect the user to a URL which will look something like this:

http://localhost:8080/cb?response=eyJra...

The client would now normally take the response JWT, verify the signature and any relevant claims (like the issuer, audience and expiration) and then read the code claim to exchange the authorization code for a set of tokens.

If you copy the response JWT and go to https://oauth.tools#jwt=<your-jwt-here> you can view the contents of the JWT. The payload will look similar to this:

{
  "exp": 1629112321,
  "iss": "https://idsvr.example.com/oauth/v2/anonymous",
  "aud": "your-client-id",
  "iat": 1629112301,
  "purpose": "authz_response",
  "code": "abcdef",
  "state": "12345abcdef"
}

Note that the iss, aud and exp claims should always be present, so that the response can be properly validated. In hybrid or implicit flow (when the response_type contains id_token or token), the payload will also contain the requested tokens.

Conclusion

JWT Security Authorization Response Mode adds another level of security to OAuth flows, and its use is recommended in financial-grade scenarios. The Curity Identity Server supports this draft specification without any specialised configuration required. Customers can thus easily implement JARM in their clients.

Keep up with our latest articles and how-tos RSS feeds.