PreAuthorize only works on GET requests

Viewed 271

I have a Spring Boot project utilizing mutual TLS. Everything works fine for any GET endpoints, but my POST endpoints return the following:

{
    "timestamp": "2020-03-26T11:28:38.778+0000",
    "status": 403,
    "error": "Forbidden",
    "message": "Forbidden",
    "path": "/audit/joe"
}

I assume I'm doing something subtly wrong, but I'm not seeing it.

The following is my configuration:

@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class X509AuthenticationServer extends WebSecurityConfigurerAdapter
{
    public static void main(final String[] args)
    {
        SpringApplication.run(X509AuthenticationServer.class, args);
    }


    @Override
    protected void configure(final HttpSecurity http) throws Exception
    {
        http
                .authorizeRequests()
                    .anyRequest().authenticated()
                .and()
                .x509()
                    .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                    .userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService()
    {
        return new UserDetailsService()
        {
            @Override
            public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException
            {
                System.out.println("userDetailsService::loadUserByUsername() :: Username: " + username);

                if (username.equalsIgnoreCase("allowed-user"))
                {
                    return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
                } else
                {
                    throw new UsernameNotFoundException(String.format("User %s not found", username));
                }
            }
        };
    }
}

And the following is my controller:

@RestController
public class AuditController
{
    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/audit/{username}", method = RequestMethod.POST), consumes = "application/json")
    public void audit(@PathVariable("username") final String username,
                      @RequestBody final AuditRequest auditRequest,
                      final HttpServletResponse response) throws JsonProcessingException
    {
        // Business logic

        response.setStatus(201);
    }
}

This controller's GET method works as expected:

@Controller
public class UserController
{
    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String user(final Model model, final Principal principal)
    {
        final UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal();

        model.addAttribute("username", currentUser.getUsername());

        return "user";
    }
}

And here are my dependencies:

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
      <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
      <version>2.2.5.RELEASE</version>
    </dependency>
  </dependencies>
0 Answers
Related