Learn Spring Security
Contents
Remove Role-Based Access
We have intentionally left the role-based access restrictions to few APIs in order to show you how to combine roles and permissions together. But going forward we will replace it completely with permission-based access control.
Let's modify HttpSecurity configuration by replacing hasRole() with hasAuthority() for each API using the appropriate permissions we have created in PermissionEnum.
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests(auth -> auth
.antMatchers(GET, PUBLIC_API_LIST).permitAll()
.antMatchers(API_LIST_STUDENTS).hasAuthority(LIST_STUDENTS.name())
.antMatchers(API_LIST_INSTRUCTORS).hasAuthority(LIST_INSTRUCTORS.name())
.antMatchers(API_VIEW_PROFILE).hasAuthority(VIEW_PROFILE.name())
.antMatchers(POST, API_CREATE_COURSES).hasAuthority(CREATE_COURSE.name())
.antMatchers(PUT, API_UPDATE_COURSES).hasAuthority(UPDATE_COURSE.name())
.antMatchers(API_PLAY_COURSE).hasAuthority(PLAY_COURSE.name())
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
Remove roles from Authorities
With only hasAuthority() used to secure each REST API we no longer need to provide the roles assigned to each user. So we can directly map getPermissions() in authorities() and remove getRoles() and getRolesAndPermissions() altogether in DbUserDetailService.
public List<UserDetails> getAllUserDetails() {
return appUserRepository.findAll()
.stream()
.map(appUser -> User.builder()
.username(appUser.getUsername())
.password(appUser.getPassword())
.authorities(this.getPermissions(appUser.getRoles()))
.build()
)
.collect(Collectors.toList());
}
private String[] getPermissions(Set<AppRole> roles) {
return roles.stream()
.flatMap(role -> role.getPermissions().stream())
.map(permission -> permission.getName().name())
.collect(Collectors.toSet())
.toArray(new String[0]);
}
This got even more simplified where we no longer required to combine roles (by prefixing it with ROLE_) and permissions. And we no longer need to care about the authorities override issues we highlighted in Chapter 7.
Finally we will have each APIs secured against its own permission, and users with only the permissions corresponding to the APIs they can access as their authorities as mentioned in the below table.
User | Authorities |
---|---|
Bob, Kevin, Stuart | PLAY_COURSE, VIEW_PROFILE |
Gru, Lucy | CREATE_COURSE, UPDATE_COURSE, PLAY_COURSE, VIEW_PROFILE |
Admin | LIST_STUDENTS, LIST_INSTRUCTORS, VIEW_PROFILE |
Note
- There will be no change in the API access behaviour after replacing the Role-based API access with Permission-based API access.
- In addition to Play Course, we have secured Update Course as well as View Profile APIs with its own permissions, but still these three APIs have not met the Security Objectives defined in Chapter 1