So I recently started working with Spring security and I kind of get what it does, however the one thing that is seriously aluding me is how the requestMatchers().hasRole()
and requestMatchers.hasAuthority()
works...
I understand how they get called and I have this piece of code here that I am trying to get working, but I am clearly doing something wrong as the SUPER_USER roll just does not get access to the /userManagement/** endpoints...
http
//CSRF Protection
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(
auth -> {
auth
//Whitelist URLS
.requestMatchers("/auth/**").permitAll()
//Authorize Requests
.requestMatchers("/userManagement/**").hasRole(Role.SUPER_USER.name())
.anyRequest().denyAll();
}
)
I have a Role enum like so...
@RequiredArgsConstructor
public enum Role {
SUPER_USER(
Set.of(
SUPER_USER_READ,
SUPER_USER_UPDATE,
SUPER_USER_CREATE,
SUPER_USER_DELETE
)
);
@Getter
private final Set<Permission> permissions;
public List<SimpleGrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> permissions = getPermissions().stream()
.map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
.collect(Collectors.toList());
permissions.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
return permissions;
}
public static Role fromString(String value) {
for (Role role : Role.values()) {
if (role.name().equalsIgnoreCase(value)) {
return role;
}
}
throw new LoginException("Invalid Role: " + value);
}
}
With the permissions declaired in it's own Enum
@RequiredArgsConstructor
public enum Permission {
SUPER_USER_READ("superuser:read"),
SUPER_USER_UPDATE("superuser:update"),
SUPER_USER_CREATE("superuser:create"),
SUPER_USER_DELETE("superuser:delete");
@Getter
private final String permission;
}
My end goal is to be able to call this endpoint with a User that has a SuperUser role.
@RestController
@RequestMapping("/userManagement")
@RequiredArgsConstructor
public class UserManagementController {
private final UserService userService;
@GetMapping("/getUsers")
public String getUsers() {
return "getUsers";
}
}
I am hoping someone would be able to give me some sort of lead as to what the issue can be?
I have spent hours scouring YouTube videos and looking through sample code that is simmilarly structured. No matter what changes I tried to apply eg. trying diffenent roles or using only the SuperUserRole or with the hasPermission method I am unable to get through this.
If I do this
//.requestMatchers("/userManagement/**").hasRole(Role.SUPER_USER.name())
// .requestMatchers(HttpMethod.GET, "/userManagement/**").hasAuthority(Permission.SUPER_USER_READ.getPermission())
// .anyRequest().denyAll();
.anyRequest.authenticated();
I get to my endpoint and get the expected result. This tells me that the problem lies in how I am handling this config.
And the console is not much help after enabling debug logging for Spring Boot as the only thing that comes up is this
o.s.s.w.a.Http403ForbiddenEntryPoint - Pre-authenticated entry point called. Rejecting access
and there is not much info that I can find as to how to resolve this
Okay so I figured it out...
In the Enum I have the getAuthorities()
method.
What I neglected to do is in my User entity which is implementing org.springframework.security.core.userdetails.UserDetails
In the overridden getAuthorities()
I just needed to return this.role.getAuthorities()