Search code examples
spring-bootspring-securityoauth-2.0google-oauthspring-security-oauth2

Implement "oauth2Login()" and "httpBasic()" same page via MultiHttpSecurityConfig


If the user clicks /api/*, it will load the "formLogin()" page; otherwise loads "httpBasic()." This setup works fine. Below is its code.

    @Configuration
        public class SecurityConfig {
    
        @Configuration
        @Order(1)
        public static class SpecialSecurityConfig extends WebSecurityConfigurerAdapter {
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .antMatcher("/api/**")
                    .authorizeRequests()
                        .anyRequest().authenticated()
                        .and()
                    .formLogin()
                        .loginPage("/api/login");         
            }
            
            @Override
            public void configure(WebSecurity web) throws Exception {
              web.ignoring().antMatchers("/", "/css/**");
            }
        }
    
        @Configuration
        public static class RegularSecurityConfig extends WebSecurityConfigurerAdapter {
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                        .anyRequest().authenticated()
                        .and()
                    .httpBasic();
            }
            
            @Override
            public void configure(WebSecurity web) throws Exception {
              web.ignoring().antMatchers("/", "/css/**");
            }
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .withUser("user")
                    .password("{noop}pass")
                    .roles("USER");
        }
    }

Now I want to remove "formLogin()" and replace it with "oauth2Login()." After that, When I click the google link, it loads the "httpBasic()" login page. If the user clicks google, it should go to the google login page. Please help me to fix this issue. Below is its code.

        http
        .antMatcher("/api/**")
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        .loginPage("/api/oauth_login")
        .permitAll();

oauth_login.html

    <body>
    <div class="container">
    <h1>Social Login</h1>
    <p><a href="/oauth2/authorization/google">Google</a></p>
    </div>
    </body>

Solution

  • You are specifying that requests that match "/api/**" should be secured by SpecialSecurityConfig using OAuth 2 login and all the other requests should be secured by RegularSecurityConfig using HTTP basic.

    Since "/oauth2/authorization/google" does not match "/api/**" it is secured using HTTP basic.

    One option is to change the base URI used for authorization requests to start with "/api/" (the default is "/oauth2/authorization/{registrationId}").

    You will likely also want to customize the loginProcessingUrl and the authorizationRequestResolver.

    public void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/api/**")
            .authorizeRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .loginProcessingUrl("/api/login/oauth2/code/*")
                .loginPage("/api/oauth_login")
                .authorizationEndpoint(ae -> ae
                    .baseUri("/api/oauth2/authorization/{registrationId}")
                    .authorizationRequestResolver(getAuthorizationRequestResolver())
                )
            );
    }
    
    private OAuth2AuthorizationRequestResolver getAuthorizationRequestResolver() {
        return new DefaultOAuth2AuthorizationRequestResolver(
            this.clientRegistrationRepository,
            "/api/oauth2/authorization");
    }
    

    You would then also update your login form

    <p><a href="/api/oauth2/authorization/google">Google</a></p>