Skip to content

Support Configuring Authorization Server in HttpSecurity.with(authorizationServer(), ...) #1707

Closed
@rwinch

Description

@rwinch

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 from HttpSecurity and know that this is how to configure oidc (vs another static method import like applyDefaultSecurity or something returned from applyDefaultSecurity, etc).
  • 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.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions