I am working with spring boot resource server and trying to use @PreAuthorize("hasAuthority('SCOPE_xxx')")
for authorization but no matter what scope is used in generating the token, access is always allowed to protected resource.
Here is what I am doing:
My pom.xml has following dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Resource server bring spring security with it, so no need to specify starter security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
and my resource method in controller has following code:
@PostMapping("/with-role-security")
@PreAuthorize("hasAuthority('SCOPE_items.write')")
public ResponseEntity<Order> placeOrderWithRoleBasedSecurity(@RequestBody Order order)
{
var jwt = (Jwt)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println("User : " + jwt.getSubject());
System.out.println("SecurityContextHolder = " + SecurityContextHolder.getContext().getAuthentication());
System.out.println("Received Order For " + order.getItems().size() + " Items");
order.getItems().forEach((lineItem) -> System.out.println("Item: " + lineItem.getItemCode() +
" Quantity: " + lineItem.getQuantity()));
String orderId = UUID.randomUUID().toString();
order.setOrderId(orderId);
orders.put(orderId, order);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
I am using scope "items.write" in PreAuthorize but access is allowed to method even if i generate token with scope "items.read"
Here is the log from 2 different token generated with different scope:
SecurityContextHolder = JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@25490a6c, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[SCOPE_items.write]]
SecurityContextHolder = JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@d3f0f246, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[SCOPE_items.read]]
As you can see scope is different in each token but access to above method is allowed with both token even when I specified that access to allowed to scope "items.write"
I have spend good amount of time in resolving this without any luck.
Any idea where things are going wrong?
You did not show your security configuration, so it's hard to tell with certainty, but you most probably forgot @EnableMethodSecurity
.