JWT-secured OAuth 2.0 authorisation request (JAR)

JWT-secured authorisation request, JAR for short, is an OAuth 2.0 extension for encapsulating the request parameters in a signed (JWS) JWT, which can be additionally encrypted (JWE). It makes the parameters impervious to tainting as they pass through the browser while also authenticating their source (the client). The optional encryption makes them confidential.

The JAR can be passed to the authorisation endpoint of the server in two ways:

  • Inline, in a parameter called request.

  • By URI reference, passed in a request_uri parameter. Has the benefit that the JAR will not be subjected to any URL size limitations by the browser.

The authorisation request with a JAR must also include the client_id.

Example request with inlined JAR (JWT signed with RS256):

https://c2id.com/login?client_id=123
&request=eyJraWQiOiJRRU1sUFozQzNuaE5LaUhCVXpTd2t2Y29HTTBueE5pVzVseVBPdXpoLUd
nIiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZSI6InJlYWQgd3JpdGUiLCJyZXNwb25zZV90eXBlIjoi
Y29kZSIsInJlZGlyZWN0X3VyaSI6Imh0dHBzOlwvXC9leGFtcGxlLmNvbSIsInN0YXRlIjoiODFj
MzNkNTctNTljNy00YjQxLTlhMTUtODBlMmVkMTQ4MmUyIiwiY2xpZW50X2lkIjoiMTIzIn0.Ugtg
GOG8cHdJ2uUswhxyUb2s16BZ_lG8g3HGHaebbr1rv5wSWE2IGn3dr3yTR4lwikbuE7pUlYcNwuac
SKe1GwHvwnbmPppLA0Ihy2sDk3JI0npe7aqNXjU32tAdCIoaMDV0piVY8_PPLacpb1vv_5JcJjcl
AwNcfdZXJQ3Raun2IvJF_YCxJOD0OH1sey7nvldbNIgs0OE70TX1RK3Wa3nf_FKAd6Nuz7PUXnB9
viBqXHrhRkIFGZZW6XZky8qU-wcsMDWfFHrve6E-7DmcIR9LzNZMLMKqh6u3695ap9u8p5hKZlh2
IVb6l1ajJ3yW1HT-QKPhT8VA9aO6ih4w8g

Example request with JAR passed by URI reference (at https://client.example.com/jar-0560158f0806.jwt):

https://c2id.com/login?client_id=123
&request=https%3A%2F%2Fclient.example.com%2Fjar-0560158f0806.jwt

How to construct a JAR request in the SDK. Assumes draft 29 of the JAR specification and v8.25 of the SDK.

import java.net.URI;
import com.nimbusds.oauth2.sdk.*;
import com.nimbusds.jose.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jwt.*;
import com.nimbusds.oauth2.sdk.id.*;

// The client's RSA key, registered with the OAuth 2.0 server
RSAKey rsaJWK = ...;

// The authorisation request parameters
URI endpointURI = URI.create("https://c2id.com/login");
ResponseType rt = new ResponseType("code");
ClientID clientID = new ClientID("123");
URI redirectURI = new URI("https://example.com");
Scope scope = new Scope("read", "write");
State state = new State("81c33d57-59c7-4b41-9a15-80e2ed1482e2");

// Create the JAR - a signed JWT carrying the request parameters
SignedJWT jar = new SignedJWT(
    new JWSHeader.Builder(JWSAlgorithm.RS256)
        .keyID(rsaJWK.getKeyID())
        .build(),
    new AuthorizationRequest.Builder(rt, clientID)
        .redirectionURI(redirectURI)
        .scope(scope)
        .state(state)
        .build()
        .toJWTClaimsSet()
);

// Sign the JAR with client's private RSA JWK
jar.sign(new RSASSASigner(rsaJWK));

// Compose the final authorisation request, the minimal required query
// parameters are "request" and "client_id"
AuthorizationRequest ar = new AuthorizationRequest.Builder(jar, clientID)
    .endpointURI(endpointURI)
    .build();

System.out.println(ar.toURI());

// The resulting request (with line wraps):
// https://c2id.com/login?client_id=123
// &request=eyJraWQiOiJRRU1sUFozQzNuaE5LaUhCVXpTd2t2Y29HTTBueE5pVzVseVBPdXpoLUd
// nIiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZSI6InJlYWQgd3JpdGUiLCJyZXNwb25zZV90eXBlIjoi
// Y29kZSIsInJlZGlyZWN0X3VyaSI6Imh0dHBzOlwvXC9leGFtcGxlLmNvbSIsInN0YXRlIjoiODFj
// MzNkNTctNTljNy00YjQxLTlhMTUtODBlMmVkMTQ4MmUyIiwiY2xpZW50X2lkIjoiMTIzIn0.Ugtg
// GOG8cHdJ2uUswhxyUb2s16BZ_lG8g3HGHaebbr1rv5wSWE2IGn3dr3yTR4lwikbuE7pUlYcNwuac
// SKe1GwHvwnbmPppLA0Ihy2sDk3JI0npe7aqNXjU32tAdCIoaMDV0piVY8_PPLacpb1vv_5JcJjcl
// AwNcfdZXJQ3Raun2IvJF_YCxJOD0OH1sey7nvldbNIgs0OE70TX1RK3Wa3nf_FKAd6Nuz7PUXnB9
// viBqXHrhRkIFGZZW6XZky8qU-wcsMDWfFHrve6E-7DmcIR9LzNZMLMKqh6u3695ap9u8p5hKZlh2
// IVb6l1ajJ3yW1HT-QKPhT8VA9aO6ih4w8g