Description
Expected Behavior
It would be nice if all of the Authorization Server configuration options could be made/discoverable from a single entry point & on an existing SecurityFilterChain
.
For example, it would be very nice if adding a default Authorization Server to an existing application could be done with a single invocation of the HttpSecurity
DSL using something like this:
http
.with(authorizationServer(), Customizer.withDefaults())
// ...
If a user wanted to make changes to the defaults, then they would do so using the Customizer
. For example, if OIDC was not enabled by default, then the user would be able to use:
http
.with(authorizationServer(), authz -> authz
.oidc(Customizer.withDefaults())
)
// ...
NOTE: I'm not saying that OIDC should or should not be a default, but I'm just using this as an example of how a user would be able to change the defaults.
Using this approach:
- Should feel familiar to Spring Security users
- It will make all of the features available via autocomplete after a single static import
- Should allow users to enable a feature (authorization server) rather than needing to know about the implementation details such as exception handling.
Current Behavior
Currently the recommendation is:
@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();
}
The disadvantages of this approach are:
- It is less concise
- Having multiple SecurityFilterChain is less familiar and adds additional complexity to understanding/debugging
- Using
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity
is unfamiliar to users - Using
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
is also unfamiliar to users - It is more difficult to discover. In the proposal, a user only needs to remember a single static import and every other option can be auto completed. With the current configuration a user must:
- Remember to use multiple
SecurityFilterChain
- Remember to use
@Order
(and know where to import it from) - Remember
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity
so it can be imported - Remember
OAuth2AuthorizationServerConfigurer.class
and how to get it fromHttpSecurity
and know that this is how to configureoidc
(vs another static method import likeapplyDefaultSecurity
or something returned fromapplyDefaultSecurity
, etc).
- Remember to use multiple
- The user must remember to configure
exceptionHandling
and how to configure it. - The user must enable the resource server support
Context
I'd like to only need to remember a single thing (ideally a concept) in order to add Spring Authorization Server to an existing SecurityFilterChain
.
This came up a few times (in various contexts) around trying to simplify (remove) the additional SecurityFilterChain and align more with webauthn in @joshlong and my Goodbye Passwords Hello Security talk.