FC
FACADE
CODE
Lesson 21 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

Basic Authentication Revisited

Let's send a GET request to List Students API with Admin user credentials using Basic Auth. Once we get the success response, change the Type of Authorization from Basic to No Auth and send the request again. Surprisingly we get a success response though we did not send Admin user credentials the second time.

Successful response for secured Admin APIs with No Auth
Successful response for secured Admin APIs with No Auth

This is because of the user session created in the first request. By default Spring Security creates a HttpSession and attach the JSESSIONID as cookie in the response. This cookie is sent back on subsequent requests to identify the user without the need to send username and password on those requests.

JSESSIONID cookie sent along with No Auth request to identify the user
JSESSIONID cookie sent along with No Auth request to identify the user

Stateless Session

While we said Basic Auth is stateless where each request must contain username and password, but nothing stops you from making it stateful by creating a HttpSession for the requested user. May be we can say Basic Auth is designed to be stateless when we disable the Cookies (Turn ON Disable cookie jar option in Request settings in Postman) in the user agent. Alternatively we can also override the Spring Security's default behaviour by configuring sessionManagement in HttpSecurity to make it stateless like below.


@Configuration
public class ApiSecurityConfig {
    @Bean
    public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement(
                httpSecuritySessionManagementConfigurer ->
                        httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authorizeRequests(auth -> auth
                .antMatchers(GET, PUBLIC_API_LIST).permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic();
        return http.build();
    }
}

Stateless Basic Auth

The problem with Basic Auth being stateless is the user does not have the option to login or logout. As a result they have to get them identified repeatedly on every request with their username and password. This will not be a nice user experience for the web applications. And having the user credentials in transit for a number of times poses serious security threats.

As these credentials are merely Base64 encoded, and not encrypted, Basic Auth is typically used in conjunction with HTTPS to provide confidentiality. Having said that Basic Auth might suit machine to machine interactions provided the credentials are stored and transferred securely over HTTPS, however it is not suitable for most of the scenarios for the drawbacks mentioned above.

Stateful Basic Auth

Basic Auth over HTTPS with Cookies and Sessions enabled resolves most of the above issues and is still a good choice for some of the use cases. Also Spring Security provides out of the box support to Session management with no extra code as we saw from its default behaviour before making it Stateless in this chapter. But one should be aware of some of the issues inherent to Session.

Spring Session

Spring Session - a container independent solution - can be used to support such clustered sessions without being tied to a specific instance. This can be most suitable when we have multiple instances of homogeneous (same monolithic) applications sharing the same datastore.

However the concept of User Session itself does not go well with Microservice style architecture where we can have multiple instances of heterogeneous applications/services. Each service can have its own datastore and the choice of storage system can also differ.

The way to go forward with Session-free authentication and with no need for sending username and password on every request is Token Based Authentication.