Search code examples
spring-bootspring-securityoauthspring-security-oauth2

Spring oauth2 AuthorizationServer doesn't redirect


I set up an Authorization Service with Spring Security and Oauth2. Everything worked fine until i tried to customize the login page. If I login at my custom login page it redirects back to the login page and not to the callback url.

GET /login -> POST /login -> GET /login

SecurityConfig.java


@Configuration
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    DataSource dataSource;

  

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("oauth/authorize").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll();
               
    }
   

    @Override
    protected void configure(AuthenticationManagerBuilder
                                     auth) throws Exception {
        auth.parentAuthenticationManager(authenticationManagerBean())
                .jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("select mail,password,enabled "
                        + "from users "
                        + "where mail = ?")
                .authoritiesByUsernameQuery("select mail,authority "
                        + "from users "
                        + "where mail = ?");
    }


    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean()
            throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

AuthorizationServerConfig.java

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;


    @Override
    public void configure(final AuthorizationServerSecurityConfigurer
                                  oauthServer) {
        oauthServer.tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()");
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer
                                  clients) throws Exception {
        clients
                .jdbc(dataSource);

  
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer
                                  endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter())
                .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenStore tokenStore() {
        //return new JdbcTokenStore(dataSource);
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("dein-signing-key");
        return converter;
    }

login.html

  <form  action="/login" method="POST">
            <div class="column">
                <div class="title">Anmelden</div>

                <div th:if="${param.error}" class="alert alert-error">
                    Invalid username and password.
                </div>
                <div th:if="${param.logout}" class="alert alert-success">
                    You have been logged out.
                </div>

                <input id="username" name="username" type="email" class="login input" placeholder="E-Mail Adresse"/>

                <input id="password" name="password" type="password" class="login input" placeholder="Passwort"/>
                <br>
                <p style="text-align: center; margin-top: 20px;"><a href="/password-forgotten">Passwort vergessen?</a></p>

                <button  style=" margin-top: 20px; margin-bottom: 20px" type="submit" class="button cancel login">Anmelden</button>
            </div>
        </form>

Solution

  • You have to send the CSRF token with your custom login page, see Spring Security Reference:

    9.21.1 Form Login Java Configuration

    [...]

    An example log in page implemented with JSPs for our current configuration can be seen below:

    [...]

    <c:url value="/login" var="loginUrl"/>
    <form action="${loginUrl}" method="post">       1
        <c:if test="${param.error != null}">        2
            <p>
                Invalid username and password.
            </p>
        </c:if>
        <c:if test="${param.logout != null}">       3
            <p>
                You have been logged out.
            </p>
        </c:if>
        <p>
            <label for="username">Username</label>
            <input type="text" id="username" name="username"/>  4
        </p>
        <p>
            <label for="password">Password</label>
            <input type="password" id="password" name="password"/>  5
        </p>
        <input type="hidden"                        6
            name="${_csrf.parameterName}"
            value="${_csrf.token}"/>
        <button type="submit" class="btn">Log in</button>
    </form>
    

    1 - A POST to the /login URL will attempt to authenticate the user

    2 - If the query parameter error exists, authentication was attempted and failed

    3 - If the query parameter logout exists, the user was successfully logged out

    4 - The username must be present as the HTTP parameter named username

    5 - The password must be present as the HTTP parameter named password

    6 - We must the section called “Include the CSRF Token” To learn more read the Section 5.1.1, “Cross Site Request Forgery (CSRF)” section of the reference