Document RFC 8414 Support

Fixes gh-7462
This commit is contained in:
Josh Cummings 2019-09-20 10:53:53 -06:00
parent b91668a34d
commit 3a9ee46719
No known key found for this signature in database
GPG Key ID: 49EF60DD7FF83443
4 changed files with 56 additions and 24 deletions

View File

@ -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();

View File

@ -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 <<webflux-oauth2resourceserver-jwt-jwkseturi-dsl,DSL>>.
@ -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<Jwt> 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<Jwt> audienceValidator = new AudienceValidator();
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);

View File

@ -75,6 +75,7 @@ The following sections will go into more detail on the core components used by O
* <<oauth2Client-core-interface-class>>
** <<oauth2Client-client-registration, ClientRegistration>>
** <<oauth2Client-client-registrations, ClientRegistrations>>
** <<oauth2Client-client-registration-repo, ClientRegistrationRepository>>
** <<oauth2Client-authorized-client, OAuth2AuthorizedClient>>
** <<oauth2Client-authorized-repo-service, OAuth2AuthorizedClientRepository / OAuth2AuthorizedClientService>>
@ -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

View File

@ -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 <<oauth2resourceserver-jwt-jwkseturi-dsl,DSL>>.
@ -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<Jwt> 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<Jwt> audienceValidator = new AudienceValidator();
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);