-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify configuring authorization server using HttpSecurity.with() #1725
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look great to me! Thank you 😄
I think the only thing additional item I'd be looking for is to update the documentation.
- How to use the updated configuration including:
- A minimal configuration on a single SecurityFilterChain
- A minimal Multiple FilterChains example
- Is it still recommended to use a multiple SecurityFilterChain's? If so, why (so users can know the tradeoffs of having a single or multiple)? The demonstration of the minimal configuration that is preferred (single/multiple) should be the first config users see in Getting Started.
The following sample configuration is the new proposed way of configuring a dedicated authorization server @Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.oidc(Customizer.withDefaults()) // Enable OpenID Connect 1.0
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
)
// Redirect to the login page when not authenticated from the
// authorization endpoint
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
);
return http.build();
} |
The following sample configuration is the current way of configuring a dedicated authorization server @Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
http
// Redirect to the login page when not authenticated from the
// authorization endpoint
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
)
// Accept access tokens for User Info and/or Client Registration
.oauth2ResourceServer((resourceServer) -> resourceServer
.jwt(Customizer.withDefaults()));
return http.build();
} |
@rwinch The reason for updating the comment in the main issue and providing a side-by-side comparison of the new vs. existing sample configuration is to ensure we are truly simplifying the configuration based on feedback from our community users. The content updates here was triggered from this comment. And then it made me realize that we should validate this proposed enhancement from the community first before we merge this. Regardless on whether we merge this PR or not, the one thing that is missing in the reference doc is:
I will be adding this content in the reference doc this week. |
e14e27c
to
96ab59d
Compare
96ab59d
to
15a3355
Compare
I just wanted to share my experience with this new configuration in case someone else lands on this page through their researches. Not sure if this is something specific to my configuration or this is indeed an expected behaviour as part of a wider change in Spring Security, but I had a problem with upgrading to the new configuration style. I have two filter chains where the first one configures the authorization server while the latter deals more specific cases such as allowing certain endpoints, and static files. Unless I put the following in the first security filter, then upgrading to the new configuration style breaks the app. Clients get access denied. http.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated() Only time that the new configuration style works without the above lines being present in the first security filter chain is by removing the following from the second filter chain while leaving http.authorizeHttpRequests(
(authorize) ->
authorize
.requestMatchers(PathRequest.toStaticResources().atCommonLocations())
.permitAll()
.requestMatchers("/error", "/logout")
.permitAll()
.anyRequest() // Remains
.authenticated()); // Remains Docs and your examples here indeed include this line in the first security filter, but it could perhaps be missed by some upgrading their old configurations so I just wanted to share my experience here. Thank you. |
http.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
Line 122 in 6880661
I'm not completely following how the new configuration style broke your app. Can you provide your configuration before the upgrade and then after the upgrade so I can better understand? |
Thank you for the response. The following configuration is working. However, if I remove @Bean
@Order(1)
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(
authorizationServerConfigurer,
(authorizationServer) -> authorizationServer.oidc(Customizer.withDefaults()));
http.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
http.exceptionHandling(
(exceptions) ->
exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)))
.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
@Order(2)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authorize) ->
authorize
.requestMatchers(PathRequest.toStaticResources().atCommonLocations())
.permitAll()
.requestMatchers("/error", "/logout")
.permitAll()
.anyRequest()
.authenticated())
.exceptionHandling(
exception ->
exception.defaultAuthenticationEntryPointFor(
new HxRefreshHeaderAuthenticationEntryPoint(),
new RequestHeaderRequestMatcher("HX-Request")))
.formLogin(formLogin -> formLogin.loginPage("/login").permitAll())
.oauth2Login(oauth2 -> oauth2.loginPage("/login").permitAll());
return http.build();
} The reason I didn't have If I remove the endpoint permissions in the second filter chain, then it works with @Bean
@Order(1)
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(
authorizationServerConfigurer,
(authorizationServer) -> authorizationServer.oidc(Customizer.withDefaults()));
http.exceptionHandling(
(exceptions) ->
exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)))
.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
@Order(2)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authorize) ->
authorize
//
// .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
// .permitAll()
// .requestMatchers("/error", "/logout")
// .permitAll()
.anyRequest()
.authenticated())
.exceptionHandling(
exception ->
exception.defaultAuthenticationEntryPointFor(
new HxRefreshHeaderAuthenticationEntryPoint(),
new RequestHeaderRequestMatcher("HX-Request")))
.formLogin(formLogin -> formLogin.loginPage("/login").permitAll())
.oauth2Login(oauth2 -> oauth2.loginPage("/login").permitAll());
return http.build();
} The following is the old configuration that I upgraded from, which is working. @Bean
@Order(1)
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(withDefaults());
http.exceptionHandling(
(exceptions) ->
exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)))
.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
@Order(2)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authorize) ->
authorize
.requestMatchers(PathRequest.toStaticResources().atCommonLocations())
.permitAll()
.requestMatchers("/error", "/logout")
.permitAll()
.anyRequest()
.authenticated())
.exceptionHandling(
exception ->
exception.defaultAuthenticationEntryPointFor(
new HxRefreshHeaderAuthenticationEntryPoint(),
new RequestHeaderRequestMatcher("HX-Request")))
.formLogin(formLogin -> formLogin.loginPage("/login").permitAll())
.oauth2Login(oauth2 -> oauth2.loginPage("/login").permitAll());
return http.build();
} The reason I don't have the My apologies if I wasn't clearer. |
Both of the sample links you provided use the now deprecated Line 84 in ed0265b
As noted in my previous comment:
This is a standard best practice for all Spring Security configurations in general. Start off with securing all endpoints and then customize the authorization rules for specific endpoints depending on your security requirements. |
Thank you. |
This PR attempts to simplify the default configuration for an authorization server using
HttpSecurity.with()
.We would greatly appreciate if our community users can provide their upvote if you are in favour of:
Issue gh-1707