Description
Expected Behavior
Given a client registration with authorization-grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
and an arbitrary authentication, an implementation of OAuth2AuthorizedClientProvider should build a Jwt bearer with claim sub =authentication.getName()
, sign it the same way Jwt Bearer client authentication does and use it as the assertion of the JwtBearer grant request.
It should be as simple as
Authentication authentication = new MyAuthentication(new MyPrincipal("john"));
String body = webClient
.get()
.attributes(authentication(authentication).andThen(clientRegistrationId("client-jwt-bearer")))
.retrieve()
.bodyToMono(String.class)
.block();
Current Behavior
JwtBearerOAuth2AuthorizedClientProvider works only if the given authentication principal is a Jwt.
Which means when using this grant type, we must add a lot of code (which is for a most part the same as building the Jwt Bearer client assertion.
ClientRegistration clientRegistration = ...;
JWK jwk = jwkResolver.apply(clientRegistration);
NimbusJwsEncoder jwsEncoder = new NimbusJwsEncoder(new ImmutableJWKSet<>(new JWKSet(jwk)));
JoseHeader joseHeader = ...;
JwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder()
.issuer(clientRegistration.getClientId())
.subject("john")
.audience(Collections.singletonList(clientRegistration.getProviderDetails().getIssuerUri())) // audience is the issuer uri
.id(UUID.randomUUID().toString())
.issuedAt(issuedAt)
.expiresAt(expiresAt);
JwtClaimsSet jwtClaimsSet = claimsBuilder.build();
Jwt jws = jwsEncoder.encode(joseHeader, jwtClaimsSet);
Authentication authentication = new JwtAuthenticationToken(jws);
String body = webClient
.get()
.attributes(authentication(authentication).andThen(clientRegistrationId("client-jwt-bearer")))
.retrieve()
.bodyToMono(String.class)
.block();
Is it the way we should use it ?
Context
JwtBearer grant type is not for exchanging the request bearer token but to allow a client to build/sign an Assertion of type Jwt with a subject specified by the client.