Skip to content

Commit

Permalink
Simplify configuring authorization server using HttpSecurity.with()
Browse files Browse the repository at this point in the history
Closes gh-1707
  • Loading branch information
jgrandja committed Oct 3, 2024
1 parent 4d1e2d9 commit 2c79754
Show file tree
Hide file tree
Showing 25 changed files with 751 additions and 726 deletions.
120 changes: 66 additions & 54 deletions docs/modules/ROOT/pages/configuration-model.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@

`OAuth2AuthorizationServerConfiguration` uses xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`] to apply the default configuration and registers a `SecurityFilterChain` `@Bean` composed of all the infrastructure components supporting an OAuth2 authorization server.

[TIP]
`OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity)` is a convenience (`static`) utility method that applies the default OAuth2 security configuration to `HttpSecurity`.

The OAuth2 authorization server `SecurityFilterChain` `@Bean` is configured with the following default protocol endpoints:

* xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[OAuth2 Authorization endpoint]
Expand Down Expand Up @@ -58,11 +55,14 @@ https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect 1.0] is dis
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Initialize `OidcConfigurer`
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.oidc(Customizer.withDefaults()) // Initialize `OidcConfigurer`
);
return http.build();
}
----
Expand Down Expand Up @@ -105,28 +105,31 @@ Furthermore, it lets you customize the request processing logic for the protocol
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.registeredClientRepository(registeredClientRepository) <1>
.authorizationService(authorizationService) <2>
.authorizationConsentService(authorizationConsentService) <3>
.authorizationServerSettings(authorizationServerSettings) <4>
.tokenGenerator(tokenGenerator) <5>
.clientAuthentication(clientAuthentication -> { }) <6>
.authorizationEndpoint(authorizationEndpoint -> { }) <7>
.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { }) <8>
.deviceVerificationEndpoint(deviceVerificationEndpoint -> { }) <9>
.tokenEndpoint(tokenEndpoint -> { }) <10>
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) <11>
.tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) <12>
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <13>
.oidc(oidc -> oidc
.providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <14>
.logoutEndpoint(logoutEndpoint -> { }) <15>
.userInfoEndpoint(userInfoEndpoint -> { }) <16>
.clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <17>
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.registeredClientRepository(registeredClientRepository) <1>
.authorizationService(authorizationService) <2>
.authorizationConsentService(authorizationConsentService) <3>
.authorizationServerSettings(authorizationServerSettings) <4>
.tokenGenerator(tokenGenerator) <5>
.clientAuthentication(clientAuthentication -> { }) <6>
.authorizationEndpoint(authorizationEndpoint -> { }) <7>
.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { }) <8>
.deviceVerificationEndpoint(deviceVerificationEndpoint -> { }) <9>
.tokenEndpoint(tokenEndpoint -> { }) <10>
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) <11>
.tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) <12>
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <13>
.oidc(oidc -> oidc
.providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <14>
.logoutEndpoint(logoutEndpoint -> { }) <15>
.userInfoEndpoint(userInfoEndpoint -> { }) <16>
.clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <17>
)
);
return http.build();
Expand Down Expand Up @@ -232,18 +235,21 @@ It defines extension points that let you customize the pre-processing, main proc
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationConverter(authenticationConverter) <1>
.authenticationConverters(authenticationConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.authenticationSuccessHandler(authenticationSuccessHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationConverter(authenticationConverter) <1>
.authenticationConverters(authenticationConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.authenticationSuccessHandler(authenticationSuccessHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
)
);
return http.build();
Expand Down Expand Up @@ -288,13 +294,16 @@ The following example shows how to configure `JwtClientAssertionAuthenticationPr
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
OAuth2AuthorizationServerConfigurer.authorizationServer();
authorizationServerConfigurer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureJwtClientAssertionValidator())
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureJwtClientAssertionValidator())
)
);
return http.build();
Expand Down Expand Up @@ -339,14 +348,17 @@ If you need to verify another attribute of the client `X509Certificate`, for exa
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
OAuth2AuthorizationServerConfigurer.authorizationServer();
authorizationServerConfigurer
.clientAuthentication(clientAuthentication ->
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureX509ClientCertificateVerifier())
);
.authenticationProviders(configureX509ClientCertificateVerifier())
)
);
return http.build();
}
Expand Down
58 changes: 33 additions & 25 deletions docs/modules/ROOT/pages/core-model-components.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,15 @@ Alternatively, you can configure the `RegisteredClientRepository` through the xr
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
OAuth2AuthorizationServerConfigurer.authorizationServer();
authorizationServerConfigurer
.registeredClientRepository(registeredClientRepository);
...
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.registeredClientRepository(registeredClientRepository)
)
...
return http.build();
}
Expand Down Expand Up @@ -218,13 +220,15 @@ Alternatively, you can configure the `OAuth2AuthorizationService` through the xr
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
OAuth2AuthorizationServerConfigurer.authorizationServer();
authorizationServerConfigurer
.authorizationService(authorizationService);
...
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.authorizationService(authorizationService)
)
...
return http.build();
}
Expand Down Expand Up @@ -290,13 +294,15 @@ Alternatively, you can configure the `OAuth2AuthorizationConsentService` through
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
OAuth2AuthorizationServerConfigurer.authorizationServer();
authorizationServerConfigurer
.authorizationConsentService(authorizationConsentService);
...
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.authorizationConsentService(authorizationConsentService)
)
...
return http.build();
}
Expand Down Expand Up @@ -401,13 +407,15 @@ Alternatively, you can configure the `OAuth2TokenGenerator` through the xref:con
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.tokenGenerator(tokenGenerator);
...
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.tokenGenerator(tokenGenerator)
)
...
return http.build();
}
Expand Down
7 changes: 3 additions & 4 deletions docs/modules/ROOT/pages/guides/how-to-userinfo.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ TIP: Click on the "Expand folded text" icon in the code sample above to display
This configuration provides the following:

<1> A Spring Security filter chain for the xref:{docs-dir}/protocol-endpoints.adoc[Protocol Endpoints].
<2> Resource server support that allows User Info requests to be authenticated with access tokens.
<2> Enabling OpenID Connect 1.0 will autoconfigure resource server support that allows User Info requests to be authenticated with access tokens.
<3> An instance of `JwtDecoder` used to validate access tokens.

[[customize-user-info]]
Expand Down Expand Up @@ -87,9 +87,8 @@ This configuration maps claims from the access token (which is a JWT when using

<1> A Spring Security filter chain for the xref:{docs-dir}/protocol-endpoints.adoc[Protocol Endpoints].
<2> A user info mapper that maps claims in a domain-specific way.
<3> An example showing the configuration option for customizing the user info mapper.
<4> Resource server support that allows User Info requests to be authenticated with access tokens.
<5> An example showing how to apply the `OAuth2AuthorizationServerConfigurer` to the Spring Security configuration.
<3> Enabling OpenID Connect 1.0 will autoconfigure resource server support that allows User Info requests to be authenticated with access tokens.
<4> An example showing the configuration option for customizing the user info mapper.

The user info mapper is not limited to mapping claims from a JWT, but this is a simple example that demonstrates the customization option.
Similar to the xref:guides/how-to-userinfo.adoc#customize-id-token[example shown earlier] where we customize claims of the ID token, you can customize claims of the access token itself ahead of time, as in the following example:
Expand Down
Loading

0 comments on commit 2c79754

Please sign in to comment.