Search code examples
spring-bootspring-securityoauth-2.0keycloakspring-oauth2

How to skip the default spring security OAuth2 provider prompt on login


I have a basic integration with spring boot/security and Keycloak. When I click on a protected resource I am redirected to the default Keycloak login page, but when I access the /login path on my application I am redirected to this prompt: OAuh2 provider selection prompt

As you can see there is only one OAuth2 provider configured and this renders this page completely impractical.

How can I skip this page or disable the /login path leading to this page?

Spring security config:

Properties file:

spring.security.oauth2.client.registration.keycloak.client-id=some-client
spring.security.oauth2.client.registration.keycloak.client-secret=copied_secret
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8180/realms/some_realm
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8180/realms/some_realm

Security config:

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class WebSecurityConfig {

    private final KeycloakLogoutHandler keycloakLogoutHandler;
    
    WebSecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {    
         this.keycloakLogoutHandler = keycloakLogoutHandler;    
    }

    @Bean   
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {   
         return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());   
     }

     @Bean  
     public SecurityFilterChain clientFilterChain(HttpSecurity http) throws Exception { 
         http.authorizeHttpRequests(authorize ->
            authorize.requestMatchers(
                 "/",
                 "/themes/**",
                 "/login")
            .permitAll()
            .anyRequest().authenticated()
         );
         http.oauth2Login(Customizer.withDefaults())
             .logout(logoutCustomizer ->
                     logoutCustomizer.addLogoutHandler(keycloakLogoutHandler)
                             .logoutSuccessUrl("/"));
         return http.build();
     }

     @Bean
     public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
         return http.getSharedObject(AuthenticationManagerBuilder.class)
                 .build();
     }
}

I have tried

  1. Disabling the page with formLogin().disable(). Also tried replacing this obsolete method with the new one accepting the customizer and disabling it from there.

  2. Creating and securing another path for example : loggedInUser to take advantage of the skipping of this page but the path /login still exists and seems like unfinished work.

  3. Creating a @Controller for /login path - controller is ignored.


Solution

  • You have two options:

    • instead of redirecting to /login, you redirect to the URI of the link in the login page (the authorization endpoint on Keycloak, something like http://localhost:8180/oauth2/authorization/some-client)
    • configure http.oauth2Login(oauth2 -> oauth2.loginPage("/login")); and provide with your own @Controller for /login and respond with a 302 with Location header pointing at at the URI of the link in the login page (same as above)

    First option allows to keep the default page if you ever need it.