Search code examples
springspring-bootspring-securitythymeleafpostman

Authorize endpoint with Spring "Secured" annotation


In my Spring Boot application, I have created a WebSecurityConfigurerAdapter with the following configuration:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
        .withUser("student").password(passwordEncoder().encode("password")).roles("STUDENT")
        .and()
        .withUser("teacher").password(passwordEncoder().encode("admin")).roles("TEACHER");
}

I use the browser to log in, and get a Cookie token, stored as a JSESSIONID. I then proceed to take that cookie, and use it in postman as: enter image description here

When calling the following endpoint from Postman:

@PostMapping(consumes = "application/json", produces = "application/json", path="/rest/class/{classId}/student")
@org.springframework.security.access.annotation.Secured({"ROLE_TEACHER"})

I get a 403 Forbidden (without the cookie, I get 401, understandably).

I am also using the following dependencies:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    </dependency>

Using these dependencies, my thymeleaf login page is generated automatically.

How can I solve this authentication/authorization issue?

Do I need to disable csrf? If not, how could I use a csrf token in my postman request? I tried adding it to Postman header request, using the X-CSRF-TOKEN, and used the _csrf token, which was sent to the backend, during the login process. If I disable csrf, then the login page will not even show up, and I get the following exception:

NotReadablePropertyException: Invalid property 'principal.authorities' of bean class


Solution

  • Your approach is valid, but note that the CSRF token is associated with the session and the session ID is updated after login.
    If you send in the pre-login CSRF token and the post-login session ID, then the CSRF token will not match the expected token.
    To get the updated CSRF token, after you have logged in, you can navigate in your browser to the page that makes the desired POST request.
    Then you can find the updated CSRF token on that page.
    For example it may be a hidden input field <input type="hidden" name="_csrf" value="123"> or a meta tag <meta name="_csrf" content="123"/> depending on how you have set it up on your page.