Skip to content

withIssuerLocation RFC 9068 support is broken/undocumented in 7.0.4 #19115

@jansepke

Description

@jansepke

Describe the bug

The Spring Security docs and migration guide for RFC 9068 support contain multiple inconsistencies that make it impossible to follow them for a resource server using withIssuerLocation.

  1. The RFC 9068 docs section shows .validateTypes(false) (plural) which does not exist in 7.0.4. The actual method is .validateType(false) (singular), and it only exists on JwkSetUriJwtDecoderBuilder, not on the builder returned by withIssuerLocation.

  2. The migration guide recommends replacing the old pattern with JwtValidators.createDefaultWithIssuer(location). However it does not mention how to accept at+jwtcreateDefaultWithIssuer only adds JwtTypeValidator.jwt() which accepts JWT, not at+jwt.

  3. JwtValidators.createAtJwtValidator() appears to be the correct API for accepting at+jwt, but it mandates a .clientId() call, throwing "client_id must be validated" at startup. For a resource server this is unexpected — validating client_id is not a resource server concern, and the docs show no indication of this requirement.

To Reproduce

Configure a Spring Boot 4 / Spring Security 7.0.4 resource server against an authorization server issuing RFC 9068 at+jwt tokens:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://example.cidaas.eu
          audiences: my-audience

Follow the RFC 9068 section of the docs:

val decoder = NimbusJwtDecoder.withIssuerLocation(issuerUri)
    .validateTypes(false) // compile error: unresolved reference
    .build()

Or follow the migration guide recommendation:

val decoder = NimbusJwtDecoder.withIssuerLocation(issuerUri).validateType(false).build()
// validateType exists but only on JwkSetUriJwtDecoderBuilder — unresolved reference on this path

Or use createAtJwtValidator():

JwtValidators.createAtJwtValidator().issuer(issuerUri).audience("my-audience").build()
// throws at startup: "client_id must be validated"

Expected behavior

A clear, working code example in the RFC 9068 docs section for the withIssuerLocation path that accepts at+jwt tokens without requiring clientId. The working workaround we arrived at (not documented anywhere):

val decoder = NimbusJwtDecoder.withIssuerLocation(issuerUri).validateType(false).build()
decoder.setJwtValidator(
    JwtValidators.createDefaultWithValidators(listOf(
        JwtIssuerValidator(issuerUri),
        JwtTypeValidator(listOf("at+jwt", "application/at+jwt")),
        JwtClaimValidator(JwtClaimNames.AUD) { aud: List<String>? -> aud?.any { it == audience } == true },
    ))
)

Even better would be an option to configure the accepted types via properties or JwtTypeValidator Bean.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions