From b8735abb6366b366fc43e4bb91c2ba6e4d626bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=5BCLOUD4=5D=20=ED=95=9C=ED=98=84?= Date: Fri, 16 Jan 2026 01:00:31 +0900 Subject: [PATCH 1/3] Clarify Resource Server startup expectations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify that Spring Boot defers OIDC discovery by default. Closes gh-16708 Signed-off-by: [CLOUD4] 한현 --- .../servlet/oauth2/resource-server/jwt.adoc | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc b/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc index d5e10dbf83..3cb841115f 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc @@ -40,17 +40,34 @@ And that's it! When this property and these dependencies are used, Resource Server will automatically configure itself to validate JWT-encoded Bearer Tokens. -It achieves this through a deterministic startup process: +It achieves this through a deterministic discovery process when the `JwtDecoder` is initialized from the issuer location: 1. Query the Provider Configuration or Authorization Server Metadata endpoint for the `jwks_url` property 2. Query the `jwks_url` endpoint for supported algorithms 3. Configure the validation strategy to query `jwks_url` for valid public keys of the algorithms found 4. Configure the validation strategy to validate each JWTs `iss` claim against `https://idp.example.com`. -A consequence of this process is that the authorization server must be up and receiving requests in order for Resource Server to successfully start up. +In Spring Security, constructing a decoder via `JwtDecoders.fromIssuerLocation` or `NimbusJwtDecoder.withIssuerLocation(...).build()` performs this discovery immediately. +However, in Spring Boot 2.6+, the auto-configured decoder is lazy and defers discovery until the first request that contains a JWT. +This means that, by default, Resource Server startup is not coupled to the authorization server's availability. [NOTE] -If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup will fail. +==== +If you want the application to fail startup when the authorization server is not available, +explicitly configure a `JwtDecoder` so that discovery happens at startup: + +.Eager Validation Configuration +[source,java] +---- +@Bean +JwtDecoder jwtDecoder() { + return JwtDecoders.fromIssuerLocation(issuerUri); +} +---- + +Otherwise, if discovery is deferred (the default in Spring Boot 2.6+), +the first request bearing a JWT will fail if the authorization server is unavailable. +==== === Runtime Expectations @@ -66,7 +83,7 @@ So long as this scheme is indicated, Resource Server will attempt to process the Given a well-formed JWT, Resource Server will: -1. Validate its signature against a public key obtained from the `jwks_url` endpoint during startup and matched against the JWT +1. Validate its signature against a public key obtained from the `jwks_url` endpoint during startup or on first request, depending on configuration, and matched against the JWT 2. Validate the JWT's `exp` and `nbf` timestamps and the JWT's `iss` claim, and 3. Map each scope to an authority with the prefix `SCOPE_`. From 48112d3d74a2319bb27ecffa82571f2db6a04ece Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:42:41 -0700 Subject: [PATCH 2/3] Polish Resource Server startup expectations Issue gh-16708 Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com> --- .../servlet/oauth2/resource-server/jwt.adoc | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc b/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc index 3cb841115f..7a614104f0 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/resource-server/jwt.adoc @@ -40,33 +40,19 @@ And that's it! When this property and these dependencies are used, Resource Server will automatically configure itself to validate JWT-encoded Bearer Tokens. -It achieves this through a deterministic discovery process when the `JwtDecoder` is initialized from the issuer location: +It achieves this through a deterministic discovery process it launches at the first request containing a JWT: 1. Query the Provider Configuration or Authorization Server Metadata endpoint for the `jwks_url` property 2. Query the `jwks_url` endpoint for supported algorithms 3. Configure the validation strategy to query `jwks_url` for valid public keys of the algorithms found 4. Configure the validation strategy to validate each JWTs `iss` claim against `https://idp.example.com`. -In Spring Security, constructing a decoder via `JwtDecoders.fromIssuerLocation` or `NimbusJwtDecoder.withIssuerLocation(...).build()` performs this discovery immediately. -However, in Spring Boot 2.6+, the auto-configured decoder is lazy and defers discovery until the first request that contains a JWT. -This means that, by default, Resource Server startup is not coupled to the authorization server's availability. +One benefit of deferring this process is that Resource Server startup is not coupled to the authorization server's availability. [NOTE] ==== -If you want the application to fail startup when the authorization server is not available, -explicitly configure a `JwtDecoder` so that discovery happens at startup: - -.Eager Validation Configuration -[source,java] ----- -@Bean -JwtDecoder jwtDecoder() { - return JwtDecoders.fromIssuerLocation(issuerUri); -} ----- - -Otherwise, if discovery is deferred (the default in Spring Boot 2.6+), -the first request bearing a JWT will fail if the authorization server is unavailable. +This deferral is managed by javadoc:org.springframework.security.oauth2.jwt.SupplierJwtDecoder[`SupplierJwtDecoder`]. +Consider wrapping any <> you declare in order to preserve this behavior. ==== === Runtime Expectations @@ -128,7 +114,7 @@ Ultimately, the returned `JwtAuthenticationToken` will be set on the xref:servle [[oauth2resourceserver-jwt-jwkseturi]] == Specifying the Authorization Server JWK Set Uri Directly -If the authorization server doesn't support any configuration endpoints, or if Resource Server must be able to start up independently from the authorization server, then the `jwk-set-uri` can be supplied as well: +If the authorization server doesn't support any configuration endpoints, or if Resource Server must be able to initialize independently from the authorization server, then the `jwk-set-uri` can be supplied as well: [source,yaml] ---- From 4501ae7d1cdd6904c875656b73611aefd14c9ee7 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:43:17 -0700 Subject: [PATCH 3/3] Update Reactive Resource Server startup exceptations Issue gh-16708 Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com> --- .../ROOT/pages/reactive/oauth2/resource-server/jwt.adoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/reactive/oauth2/resource-server/jwt.adoc b/docs/modules/ROOT/pages/reactive/oauth2/resource-server/jwt.adoc index bc9d827f22..b0e125c20c 100644 --- a/docs/modules/ROOT/pages/reactive/oauth2/resource-server/jwt.adoc +++ b/docs/modules/ROOT/pages/reactive/oauth2/resource-server/jwt.adoc @@ -39,17 +39,18 @@ This endpoint is referred to as a https://openid.net/specs/openid-connect-discov When this property and these dependencies are used, Resource Server automatically configures itself to validate JWT-encoded Bearer Tokens. -It achieves this through a deterministic startup process: +It achieves this through a deterministic discovery process it launches at the first request containing a JWT: . Hit the Provider Configuration or Authorization Server Metadata endpoint, processing the response for the `jwks_url` property. . Configure the validation strategy to query `jwks_url` for valid public keys. . Configure the validation strategy to validate each JWT's `iss` claim against `https://idp.example.com`. -A consequence of this process is that the authorization server must be receiving requests in order for Resource Server to successfully start up. +One benefit of deferring this process is that Resource Server startup is not coupled to the authorization server's availability. [NOTE] ==== -If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup fails. +This deferral is managed by javadoc:org.springframework.security.oauth2.jwt.SupplierReactiveJwtDecoder[`SupplierReactiveJwtDecoder`]. +Consider wrapping any <> you declare in order to preserve this behavior. ==== === Runtime Expectations @@ -85,7 +86,7 @@ From here, consider jumping to: [[webflux-oauth2resourceserver-jwt-jwkseturi]] === Specifying the Authorization Server JWK Set Uri Directly -If the authorization server does not support any configuration endpoints, or if Resource Server must be able to start up independently from the authorization server, you can supply `jwk-set-uri` as well: +If the authorization server does not support any configuration endpoints, or if Resource Server must be able to initialize independently from the authorization server, you can supply `jwk-set-uri` as well: [source,yaml] ----