diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc index 09fc66dc04..dd1f6d4bf5 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc @@ -89,7 +89,7 @@ At this point, the OAuth Client retrieves your email address and basic profile i == Using OpenID Provider Configuration For well known providers, Spring Security provides the necessary defaults for the OAuth Authorization Provider's configuration. -If you are working with your own Authorization Provider that supports https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[OpenID Provider Configuration], you may use the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OpenID Provider Configuration Response] the issuer-uri can be used to configure the application. +If you are working with your own Authorization Provider that supports https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[OpenID Provider Configuration] or https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata], the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OpenID Provider Configuration Response]'s `issuer-uri` can be used to configure the application. [source,yml] ---- @@ -106,7 +106,11 @@ spring: client-secret: 6cea952f-10d0-4d00-ac79-cc865820dc2c ---- -The `issuer-uri` instructs Spring Security to leverage the endpoint at `https://idp.example.com/auth/realms/demo/.well-known/openid-configuration` to discover the configuration. +The `issuer-uri` instructs Spring Security to query in series the endpoints `https://idp.example.com/auth/realms/demo/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/auth/realms/demo`, or `https://idp.example.com/.well-known/oauth-authorization-server/auth/realms/demo` to discover the configuration. + +[NOTE] +Spring Security will query the endpoints one at a time, stopping at the first that gives a 200 response. + The `client-id` and `client-secret` are linked to the provider because `keycloak` is used for both the provider and the registration. @@ -120,7 +124,7 @@ A minimal OAuth2 Login configuration is shown below: @Bean ReactiveClientRegistrationRepository clientRegistrations() { ClientRegistration clientRegistration = ClientRegistrations - .fromOidcIssuerLocation("https://idp.example.com/auth/realms/demo") + .fromIssuerLocation("https://idp.example.com/auth/realms/demo") .clientId("spring-security") .clientSecret("6cea952f-10d0-4d00-ac79-cc865820dc2c") .build(); diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc index afb899f29d..9bba4fb40a 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc @@ -1,5 +1,5 @@ [[webflux-oauth2-resource-server]] -= OAuth2 Resource Server += OAuth 2.0 Resource Server Spring Security supports protecting endpoints using two forms of OAuth 2.0 https://tools.ietf.org/html/rfc6750.html[Bearer Tokens]: @@ -36,15 +36,15 @@ spring: oauth2: resourceserver: jwt: - issuer-uri: https://idp.example.com + issuer-uri: https://idp.example.com/issuer ---- -Where `https://idp.example.com` is the value contained in the `iss` claim for JWT tokens that the authorization server will issue. +Where `https://idp.example.com/issuer` is the value contained in the `iss` claim for JWT tokens that the authorization server will issue. Resource Server will use this property to further self-configure, discover the authorization server's public keys, and subsequently validate incoming JWTs. [NOTE] -To use the `issuer-uri` property, it must also be true that `https://idp.example.com/.well-known/openid-configuration` is a supported endpoint for the authorization server. -This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint. +To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. +This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint or a https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata] endpoint. And that's it! @@ -54,7 +54,7 @@ When this property and these dependencies are used, Resource Server will automat It achieves this through a deterministic startup process: -1. Hit the Provider Configuration endpoint, `https://idp.example.com/.well-known/openid-configuration`, processing the response for the `jwks_url` property +1. Hit the Provider Configuration or Authorization Server Metadata endpoint, processing the response for the `jwks_url` property 2. Configure the validation strategy to query `jwks_url` for valid public keys 3. Configure the validation strategy to validate each JWTs `iss` claim against `https://idp.example.com`. @@ -95,7 +95,7 @@ From here, consider jumping to: [[webflux-oauth2resourceserver-jwt-jwkseturi]] === Specifying the Authorization Server JWK Set Uri Directly -If the authorization server doesn't support the Provider Configuration endpoint, or if Resource Server must be able to start up independently from the authorization server, then `issuer-uri` can be exchanged for `jwk-set-uri`: +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: [source,yaml] ---- @@ -104,6 +104,7 @@ spring: oauth2: resourceserver: jwt: + issuer-uri: https://idp.example.com jwk-set-uri: https://idp.example.com/.well-known/jwks.json ---- @@ -111,7 +112,7 @@ spring: The JWK Set uri is not standardized, but can typically be found in the authorization server's documentation Consequently, Resource Server will not ping the authorization server at startup. -However, it will also no longer validate the `iss` claim in the JWT (since Resource Server no longer knows what the issuer value should be). +We still specify the `issuer-uri` so that Resource Server still validates the `iss` claim on incoming JWTs. [NOTE] This property can also be supplied directly on the <>. @@ -169,10 +170,12 @@ For example, the second `@Bean` Spring Boot creates is a `ReactiveJwtDecoder`, w ---- @Bean public ReactiveJwtDecoder jwtDecoder() { - return ReactiveJwtDecoders.fromOidcIssuerLocation(issuerUri); + return ReactiveJwtDecoders.fromIssuerLocation(issuerUri); } ---- +[NOTE] +Calling `{security-api-url}org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.html#fromIssuerLocation-java.lang.String-[ReactiveJwtDecoders#fromIssuerLocation]` is what invokes the Provider Configuration or Authorization Server Metadata endpoint in order to derive the JWK Set Uri. If the application doesn't expose a `ReactiveJwtDecoder` bean, then Spring Boot will expose the above default one. And its configuration can be overridden using `jwkSetUri()` or replaced using `decoder()`. @@ -494,7 +497,7 @@ Resource Server uses `JwtTimestampValidator` to verify a token's validity window @Bean ReactiveJwtDecoder jwtDecoder() { NimbusReactiveJwtDecoder jwtDecoder = (NimbusReactiveJwtDecoder) - ReactiveJwtDecoders.fromOidcIssuerLocation(issuerUri); + ReactiveJwtDecoders.fromIssuerLocation(issuerUri); OAuth2TokenValidator withClockSkew = new DelegatingOAuth2TokenValidator<>( new JwtTimestampValidator(Duration.ofSeconds(60)), @@ -536,7 +539,7 @@ Then, to add into a resource server, it's a matter of specifying the `ReactiveJw @Bean ReactiveJwtDecoder jwtDecoder() { NimbusReactiveJwtDecoder jwtDecoder = (NimbusReactiveJwtDecoder) - ReactiveJwtDecoders.fromOidcIssuerLocation(issuerUri); + ReactiveJwtDecoders.fromIssuerLocation(issuerUri); OAuth2TokenValidator audienceValidator = new AudienceValidator(); OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri); diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc index 44fa8214d4..c5e93eabac 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc @@ -75,6 +75,7 @@ The following sections will go into more detail on the core components used by O * <> ** <> +** <> ** <> ** <> ** <> @@ -153,6 +154,26 @@ The name may be used in certain scenarios, such as when displaying the name of t The supported values are *header*, *form* and *query*. <15> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user. +[[oauth2Client-client-registrations]] +==== ClientRegistrations + +A `ClientRegistration` can be initially configured by hitting an authorization server's https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint or a https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata] endpoint. + +`ClientRegistrations` provides convenience methods for generating a `ClientRegistration` in this way, as can be seen in the following example: + +[source,java] +---- +@Bean +public ClientRegistrationRepository clientRegistrationRepository() { + ClientRegistration clientRegistration = + ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build(); + return new InMemoryClientRegistrationRepository(clientRegistration); +} +---- + +The above code will query in series `https://idp.example.com/issuer/.well-known/openid-configuration`, and then `https://idp.example.com/.well-known/openid-configuration/issuer`, and finally `https://idp.example.com/.well-known/oauth-authorization-server/issuer`, stopping at the first to return a 200 response. + +As an alternative, you can invoke `ClientRegistrations#fromOidcIssuerLocation` to only hit the OIDC Provider Configuration endpoint. [[oauth2Client-client-registration-repo]] ==== ClientRegistrationRepository diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-resourceserver.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-resourceserver.adoc index c45c763b6f..c6bfd557e1 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-resourceserver.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-resourceserver.adoc @@ -36,15 +36,15 @@ spring: oauth2: resourceserver: jwt: - issuer-uri: https://idp.example.com + issuer-uri: https://idp.example.com/issuer ---- -Where `https://idp.example.com` is the value contained in the `iss` claim for JWT tokens that the authorization server will issue. +Where `https://idp.example.com/issuer` is the value contained in the `iss` claim for JWT tokens that the authorization server will issue. Resource Server will use this property to further self-configure, discover the authorization server's public keys, and subsequently validate incoming JWTs. [NOTE] -To use the `issuer-uri` property, it must also be true that `https://idp.example.com/.well-known/openid-configuration` is a supported endpoint for the authorization server. -This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint. +To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. +This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint or a https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata] endpoint. And that's it! @@ -54,7 +54,7 @@ When this property and these dependencies are used, Resource Server will automat It achieves this through a deterministic startup process: -1. Hit the Provider Configuration endpoint, `https://idp.example.com/.well-known/openid-configuration`, processing the response for the `jwks_url` property +1. Hit the Provider Configuration or Authorization Server Metadata endpoint, processing the response for the `jwks_url` property 2. Configure the validation strategy to query `jwks_url` for valid public keys 3. Configure the validation strategy to validate each JWTs `iss` claim against `https://idp.example.com`. @@ -95,7 +95,7 @@ From here, consider jumping to: [[oauth2resourceserver-jwt-jwkseturi]] === Specifying the Authorization Server JWK Set Uri Directly -If the authorization server doesn't support the Provider Configuration endpoint, or if Resource Server must be able to start up independently from the authorization server, then `issuer-uri` can be exchanged for `jwk-set-uri`: +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: [source,yaml] ---- @@ -104,6 +104,7 @@ spring: oauth2: resourceserver: jwt: + issuer-uri: https://idp.example.com jwk-set-uri: https://idp.example.com/.well-known/jwks.json ---- @@ -111,7 +112,7 @@ spring: The JWK Set uri is not standardized, but can typically be found in the authorization server's documentation Consequently, Resource Server will not ping the authorization server at startup. -However, it will also no longer validate the `iss` claim in the JWT (since Resource Server no longer knows what the issuer value should be). +We still specify the `issuer-uri` so that Resource Server still validates the `iss` claim on incoming JWTs. [NOTE] This property can also be supplied directly on the <>. @@ -165,10 +166,13 @@ For example, the second `@Bean` Spring Boot creates is a `JwtDecoder`, which dec ---- @Bean public JwtDecoder jwtDecoder() { - return JwtDecoders.fromOidcIssuerLocation(issuerUri); + return JwtDecoders.fromIssuerLocation(issuerUri); } ---- +[NOTE] +Calling `{security-api-url}org/springframework/security/oauth2/jwt/JwtDecoders.html#fromIssuerLocation-java.lang.String-[JwtDecoders#fromIssuerLocation]` is what invokes the Provider Configuration or Authorization Server Metadata endpoint in order to derive the JWK Set Uri. + If the application doesn't expose a `JwtDecoder` bean, then Spring Boot will expose the above default one. And its configuration can be overridden using `jwkSetUri()` or replaced using `decoder()`. @@ -512,7 +516,7 @@ Resource Server uses `JwtTimestampValidator` to verify a token's validity window @Bean JwtDecoder jwtDecoder() { NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) - JwtDecoders.fromOidcIssuerLocation(issuerUri); + JwtDecoders.fromIssuerLocation(issuerUri); OAuth2TokenValidator withClockSkew = new DelegatingOAuth2TokenValidator<>( new JwtTimestampValidator(Duration.ofSeconds(60)), @@ -554,7 +558,7 @@ Then, to add into a resource server, it's a matter of specifying the `JwtDecoder @Bean JwtDecoder jwtDecoder() { NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) - JwtDecoders.fromOidcIssuerLocation(issuerUri); + JwtDecoders.fromIssuerLocation(issuerUri); OAuth2TokenValidator audienceValidator = new AudienceValidator(); OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);