spring-projects / spring-projects/spring-security

Support generating RFC 9068 compliant JWT access tokens

Open
#18,325 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Expected Behavior

NimbusJwtEncoder should allow the user to specify whether it should generate JWT access tokens complying to RFC 9068 or not. If RFC 9068 compliant JWT access tokens are anticipated, it should validate the existence of required claims before generation, and produces a JWT with the typ header as "at+jwt" as well as required claims; otherwise the typ should be "JWT" as before for compatibility.

For ease of use, we could consider adding support for configuring the default values of shared claims in the builders (i.e., RsaKeyPairJwtEncoderBuilder, EcKeyPairJwtEncoderBuilder, and SecretKeyJwtEncoderBuilder), and allow these values to be merged with (and overriden by) JwtEncoderParameters.claims passed to NimbusJwtEncoder#encode().

The code could look like:

JwtClaimsSet sharedClaims = JwtClaimsSet.builder()
    .issuer("https://as.example.com")
    .audience("https://rs.example.com")
    .build();
JwtEncoder jwtEncoder = NimbusJwtEncoder.withKeyPair(publicKey, privateKey)
    .useAtJwt(true)
    .defaultClaims(sharedClaims)
    .build();

Instant now = Instant.now();
JwtClaimsSet detailedClaims = JwtClaimsSet.builder()
    .subject("5ba552d67")
    .issuedAt(now)
    .expiresAt(now.plus(Duration.ofMinutes(30)))
    .clientId("s6BhdRkqt3")
    .build();
Jwt jwt = jwtEncoder.encode(JwtEncoderParameters.from(detailedClaims);
// It should throw JwtEncodingException because of missing the required `jti` claim.

We should also consider adding configurer options to set up RFC 9068 JWT access token generation for Spring Security OAuth2 Authorization Server.

Current Behavior

Spring Security supports validation of RFC 9068 JWT access tokens. However, NimbusJwtEncoder can only generates a JWT without typ or with typ as "JWT":

  • if it's constructed with public NimbusJwtEncoder(JWKSource<SecurityContext> jwkSource), there's no typ in the JWS header;
  • if it's built by a builder using private NimbusJwtEncoder(JWK jwk), the typ will be "JWT".

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with NimbusJwtEncoder and the RsaKeyPairJwtEncoderBuilder, EcKeyPairJwtEncoderBuilder, and SecretKeyJwtEncoderBuilder entry points. Trace how JwtEncoderParameters.claims become the JWS header and JWT claims, then define the RFC 9068 mode, required-claim validation, typ value, and default-claim merging behavior. Done means RFC 9068 tokens are generated when enabled while existing JWT behavior remains compatible.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
authentication, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.