FC
FACADE
CODE
Lesson 10 of 28
FC
FACADE
CODE

Learn Spring Security

Contents

01. Bootstrap The Application
1. Introduction
2. Install Spring Security
3. Enable Basic Auth
4. Authentication with AppUser
5. Password Encoder
02. Web Layer Security - RBAC
6. Permit Public APIs
7. Role Based Authorization
8. Disable CSRF
9. Current Authenticated User
03. Web Layer Security - PBAC
10. Permission Based Authorization
11. Define Permissions
12. Assign Permissions
13. Remove Role Based Access
04. Service Layer Security
14. PreAuthorize
15. PostAuthorize
16. Authorize Using Spring Beans
05. Domain Object Instance Security
17. Domain Object Instance Security
18. PermissionEvaluator Interface
19. PermissionEvaluator Strategy
20. DB Backed UserDetailsService
06. Token Based Authentication
21. Basic Authentication Revisited
22. Generate Token
23. Persist Token
24. Verify Token
25. Invalidate Token
07. Token Based Authentication and Authorization
26. JSON Web Token
27. Generate JWT
28. Verify JWT

Permission Based Authorization

We are yet to implement access restrictions to the below three APIs in order to meet the Security objectives defined in the first chapter.

APIObjective
Update CourseInstructor who created the course can only update it.
Play CourseInstructor who created the course can only play it.
Students who are enrolled on the course can only play it.
View User ProfileUsers can only view their profile.
Any user can view an Instructor's profile.

Downside of Role-based access control

We can apply role-based restrictions using hasRole() or hasAnyRole() on the above API urls. But role-based access control is abstract, coarse grained and less flexible. Any software requirement change in terms of API access control will require code change in the HttpSecurity configuration.

For example, if the Students can view the list of instructors in order to get the list of courses filtered by the selected instructor, we have to relax the access control to ListInstructors API for both Admin and Student users as below:


http
    .csrf().disable()
    .authorizeRequests(auth -> auth
            .antMatchers(GET, PUBLIC_API_LIST).permitAll()
            .antMatchers(API_LIST_STUDENTS).hasRole(ADMIN.name())
            .antMatchers(API_LIST_INSTRUCTORS).hasAnyRole(ADMIN.name(), STUDENT.name())
            .antMatchers(POST, API_CREATE_COURSES).hasRole(INSTRUCTOR.name())
            .anyRequest().authenticated()
    )
    .httpBasic();

So we need a way to define and modify access control dynamically with out changing the code. We can do this by adding another logical layer using Permissions on top of Roles.

Permissions

Permission grants the ability to perform an action on a resource. By defining permissions for each action on each resource we can create fine grained access control. In technical terms we can define permissions for each API and then assign them to the appropriate Roles in the database. Similar to hasRole() Spring Security provides hasAuthority() method to restrict access to the API urls using these permissions.

So we will define each permission in the format ACTION_RESOURCENAME corresponding to each APIs. For example, PLAY_COURSE permission can be used to grant the ability to access PlayCourse API.

Key benefits of Permission-based access control

Securing each API by defining its own permission and then granting those permissions to the roles offer some of the key benefits listed below:

  1. No more code modification, as granting permissions to roles is database driven.
  2. Bird's eye view of who can do what in a single place i.e., database.
  3. Fine grained access control to each API (and other resources).
  4. Same permission-based access model can be used by both API as well as user interface, as every user action in the UI corresponds to an API execution in the application.

First let's apply the permission based access control for PlayCourse API. We will gradually build the concept in the next three chapters. And in the last chapter we will replace existing role-based access control using permissions.