-1

I was using version 2.6.x of spring boot with success. I've switched to 2.7.1. and adapted some of my security config to match the new format.

But now the CSRF token are no longer generated for me and injected in my login form, maybe the same with other forms, but I can't test it out.

Here is my security config

@Order(1)
  @Bean
  public SecurityFilterChain actuatorFilterChain(final HttpSecurity http) throws Exception {
    // @formatter:off
    return http
      .requestMatchers().antMatchers("/jobs/**", "/actuator/**").and()
      .authorizeRequests().antMatchers("/jobs/**", "/actuator/**").hasRole("SYSTEM").and()
      .httpBasic()
        .and()
      .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .build()
      ;
    // @formatter:on
  }

  @Bean
  public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {

      // @formatter:off
      return http
        .requestMatchers().antMatchers(applicationRoutes).and()
        .authorizeRequests()
          .antMatchers(applicationRoutes).hasAnyRole(applicationAuthorities).and()
        .csrf().disabled().and()
        .formLogin()
          .loginPage("/login")
          .defaultSuccessUrl("/")
          .and()
        .logout()
          .logoutSuccessUrl("/")
          .and()
        .headers()
          .httpStrictTransportSecurity().disable()
        .and()
        .build()
      ;
      // @formatter:on
    }
  }

Here is my login page

<html>

<head>
</head>

<body>

          <form th:action="@{/login}"
                method="POST"
                >
            <div class="field">
              <input type="text"
                     id="username"
                     name="username"
                     placeholder="&#xf007   Nom d'utilisateur"
                     style="font-family:Lato,'Helvetica Neue', FontAwesome">
            </div>
            <div class="field">
              <input type="password"
                     id="password"
                     name="password"
                     placeholder="&#xf023    Mot de passe"
                     style="font-family:Lato,'Helvetica Neue', FontAwesome">
            </div>

            <button class="ui primary button"
                    style="width:100%"
                    type="submit">Connexion</button>
          </form>

</body>

</html>

The error that is shown to me is a 405 saying /login doesn't support POST. But the form sended to the browser doesn't include CSRF token in the form.

I suspect that I miss some new bits of configuration. But I don't know where to look for.

benzen
  • 6,204
  • 4
  • 25
  • 37
  • I've scanned this page https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes, didn't found usefull any info for my problem. – benzen Jul 19 '22 at 18:53
  • 1
    What is in `applicationRoutes`? If it doesn't include `"/login"` that would probably be the issue. Otherwise, can you provide a [minimal sample](https://stackoverflow.com/help/minimal-reproducible-example) or more information about what's not shown in your configuration? – Steve Riesenberg Jul 19 '22 at 20:10
  • Why do you have `csrf().disabled()`? – Toerktumlare Jul 20 '22 at 00:00
  • @Toerktumlare I did a lot of testing, forgot to remove this bit. I'll update my question – benzen Jul 20 '22 at 12:18
  • @SteveRiesenberg in `applicationRoutes` there is only route that I've declared in my app with controllers. I did'nt put /login in it since it would require a user loged in in order to access the login page. – benzen Jul 20 '22 at 12:22
  • Please proof read your question before posting – Toerktumlare Jul 20 '22 at 12:26
  • @benzen, when testing your snippet of configuration, I verified that when `/login` is missing in `http.requestMatchers()` the CSRF token is not generated for your custom login page. This is because the Spring Security filter chain is not available for the `GET /login` request. See answer. – Steve Riesenberg Jul 22 '22 at 17:15

1 Answers1

1

When adding http.requestMatchers() to a filter chain, the FilterChainProxy will ignore routes that do not match. In your case, /login is not matched by a filter chain. Therefore, no CSRF token is available for your login page.

Ensure /login is available in the applicationRoutes field in your example to fix the issue. You can add a permitAll rule to your /login route with .mvcMatchers("/login").permitAll() or adding .permitAll() to the .formLogin() DSL.

Steve Riesenberg
  • 4,271
  • 1
  • 4
  • 26