user3105453
user3105453

Reputation: 1981

User can access resource even if he's not part of "@Secured([role])"

I would like to secure my endpoint so only users with the role READ can access a certain resource. Those are my configurations:

Controller:

@RestController
@RequestMapping("/api/status")
public class StatusController {

    @RequestMapping(method = RequestMethod.GET)
    @Secured("READ")
    Map<String, Object> getSecureStatus() {
        Map<String, Object> statusMap = new LinkedHashMap<>();

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        statusMap.put("auth", auth);
        return statusMap;
    }
}

The WebSecurityConfigurerAdapter:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
             // .antMatchers("/").permitAll()
                .antMatchers("/api/**").authenticated()
                .and()
            .httpBasic();
    }
}

GlobalAuthenticationConfigurerAdapter:

@Configuration
public class AuthenticationManagerConfig extends
        GlobalAuthenticationConfigurerAdapter {

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("teddy").password("password").roles("USER");
    }

}

I would assume that Teddy shouldn't be able to access the resource, as his role is USER rather than READ.

But with this call, Teddy gets his information anyway: curl -u teddy:password 'http://localhost:8080/api/status/':

{
  "auth": {
    "details": {
      "remoteAddress": "127.0.0.1",
      "sessionId": null
    },
    "authorities": [
      {
        "authority": "ROLE_USER"
      }
    ],
    "authenticated": true,
    "principal": {
      "password": null,
      "username": "teddy",
      "authorities": [
        {
          "authority": "ROLE_USER"
        }
      ],
      "accountNonExpired": true,
      "accountNonLocked": true,
      "credentialsNonExpired": true,
      "enabled": true
    },
    "credentials": null,
    "name": "teddy"
  }
}

What am I missing?

Edit: removed .antMatchers("/").permitAll()

Upvotes: 0

Views: 115

Answers (2)

user3105453
user3105453

Reputation: 1981

I found the mistake. I overlooked that getSecureStatus() wasn't explicitely defined public. This code fixes it:

@RestController
@RequestMapping("/api/status")
public class StatusController {

    @RequestMapping(method = RequestMethod.GET)
    @Secured("READ")
    public Map<String, Object> getSecureStatus() {
        Map<String, Object> statusMap = new LinkedHashMap<>();

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        statusMap.put("auth", auth);
        return statusMap;
    }
}

Upvotes: 0

reos
reos

Reputation: 8324

Probably it's because you're using .antMatchers("/").permitAll() it's telling spring that you're allowing every request.

Try removing it from your configuration.

Upvotes: 1

Related Questions