Introduction to Spring Security
Overview
Security is the ability of a system to protect data and information from unauthorized access while still providing access to authorized people and systems.
Security is one of the vital architectural characteristics which can not be compromised. It becomes a critical requirement when GDPR is also to be considered.
Software security is a complex subject and what kind of security measures are applicable depends on which layer of OSI model we are talking about.
Here, we are explicitly referring to application-level security and how spring security helps application developers enable it without hassle and effort in spring-based projects.
Introduction to Spring Security
Spring Security is a highly customizable security framework that provides authentication, authorization, and protection against common attacks like CSRF, session fixation, XSS, etc.
Features of Spring Security
Some important spring security features include:
- Authentication
- Authorization
- Remember me
- Single sign-on
- LDAP
- Reactive support
Benefits of Spring Security
Benefits offered by spring security include:
- Open source security framework.
- Highly customizable.
- Out-of-box support for authentication and authorization.
- Protect against typical attack.
- Integrate easily with spring and spring boot framework.
- Easy to develop and unit test.
Spring Security Modules
Maven Setup for Spring Security
With a regular spring framework, two dependencies are required to be added to the application's POM
- Spring security core - This jar is the core module of spring security, and it's required for all types of applications.
- Spring security web - This JAR contains servlet filters and related web security code. Add this dependency for web based application.
When working with spring boot based application, then the job is much easier. One single starter JAR brings and includes all the required dependencies spring- security-core, spring-security-web, etc.
Spring Security Authentication and Authorization
Authentication
Authentication is the process of verifying the identities of the user or system to check if they are truly who they claim to be.
We will first understand how to implement basic authentication using spring security with spring boot and then how to customize based on the application need.
The only maven dependency required for the application are web and security.
We are exposing one rest endpoint /hello using HelloController.java
Run the application, and let's try to invoke the endpoint using the cURL utility.
Response to the above call
The response status is HTTP 401 Unauthorized. As soon as dependency spring-boot-starter-security is added, the framework activates the default security policy.
By default, Spring Security expects the default username (user) with the auto-generated password printed on the console. Let’s try it again but now with the proper credentials:
The response to the call now is
Let's understand how spring security provides authentication and the main actors involved.
Out of all the above User details service and Password encoder are the most important ones.
- UserDetailsService - An object of this class is responsible for managing user details. If no implementation is provided, then spring defaults to the in-memory implementation of the user, which is InMemoryUserDetailsManager. This framework provided an implementation register credential in the memory of the application. Default credentials are "user" with a default password, a randomly generated UUID. When you restart the application, a new password will be generated and printed on the console.
- PasswordEncoder - It is responsible for encoding the password and ensuring provided password matched encoding.
That is how spring security can protect our endpoints by adding a starter-security dependency.
Note - The default implementation serves only as proof of concept to verify if security is activated or not. It should not be used for the production application.
Override Default Authentication
For proof of concept purpose, default InMemoryUserDetailsManager is alright, but it does not solve the practical authentication problem.
A practical solution is to store the user and credential details in the database and use the information for authentication. For this to happen, the application has to abide by the contract provided by spring security to override default framework behavior.
To implement databased-backed authentication, four interfaces are provided by spring security are involved.
Interface | Detail |
---|---|
UserDetail | Representation of a user to spring security framework. Users in the system should either implement or convert to this interface. |
GrantedAuthority | Represents authorities a user has. Useful for authorization. |
UserDetailsService | Responsible for retrieving and support in actual authentication. It contains only one method, loadUserByUsername. |
UserDetailsManager | Extends UserDetailsService with extra behavior of creating, modifying, and deleting a user. |
The relationship among all four is as below:
Step by Step Implementation
- Create a user entity mapped to the corresponding database table and corresponding repository.
- Create a secure user which should implement userdetails contract and wraps UserEntity.
- Provide a custom implementation of UserDetailsService
Voila! Authentication is ready.
Authorization
Authorization is process of validating what action an authorized user can perform on the system.
This is where the GrantedAuthority object plays the role. First corresponding tables should be created in DB for which schema is from official spring security.
Let's assume we have two user types in the system to understand the authorization.
User | Authority | Descriptin |
---|---|---|
Bob | ADMIN | Administrator |
Alice | USER | Regular user |
- Administrator - They should have access to all the endpoint matches with pattern /admin.
- Regular User - They are users other than admin and should have access to all the endpoint matches with pattern /user.
To configure the above authorization implement the interface WebSecurityConfigurerAdapter to customize the behavior of our application based on the specific need.
For admin user code will be:
And configuration for regular users will be:
Password Encoding
We are using user name and password based authentication. Therefore passwords are to be dealt with securely. Obviously, storing passwords in plain text is a bad idea.
In actual applications, the password must be stored securely, for which hashing is a popular and well-tested solution. The good thing is that we don't need to develop those hashing algorithms ourselves. Spring security supports several hashing algorithms out of the box.
- bcrypt
- scrypt
- SHA
- MD5 and others.
We need to configure hashing algorithm with the framework.
Servlet Filters
Spring security architecture is entirely based on servlet filters. Framework maintains the servlet filter chain wherein each filter in the chain has a particular responsibility—a great example of the single responsibility principle.
How exactly does the servlet filter chain work? Spring Security uses FilterChainProxy to decide which filter chain to use.
Some of the existing filters available with the framework are:
- BasicAuthenticationFilter - Takes care of basic authentication.
- FormBasedAuthenticationFilter - Takes care of form based authentication.
- CsrfFilter - Takes care of cross-site request forgery.
- CorsFilter - Takes care of cross-origin resource sharing.
The spring security framework is flexible enough to allow us to configure different chains based on the URI path. For example, URI path /admin can use a filter chain different from endpoint /user.
When configuring authorization for each type of user, we used the same arrangement. Let's inspect the filter chain for each type of configuration from FilterChainProxy class.
AdminSecurityConfig | BasicSecurityConfig |
---|---|
From the above screenshot, we can see that when authentication is type basic, the framework configures a security chain with BasicAuthenticationFilter and a form-based authentication filter chain contains UsernamePasswordAuthenticationFilter.
Spring Security with OAuth2
OAuth 2.0, which stands for “Open Authorization”, is a standard designed to allow a website or application to access resources hosted by other web apps on behalf of a user.
If a user wants to sign up or log in to a website, it can use the list of authorization providers like Facebook, Google, Github, etc. Instead of implementing database-backed authentication in our application, it can delegate it to the authorization provider.
How to configure OAuth login with spring security?
As usual, spring security provides a configuration-based approach, whereas the spring security framework takes care of heavy lifting work.
To configure the OAuth client, add maven dependencies.
And in application properties, add provider-specific properties. The sample below is shown for GitHub.
As soon as the home page is opened application will redirect the authentication request to Github.
That's it! :) It is super easy to configure OAuth with spring boot and security.
Conclusion
- Spring security provides a convenient way to implement authentication and authorization.
- Spring security provides application security of the top most layer(application layer) of the OSI model.
- Spring security framework is highly configurable and can be customized for individual applications.
- Spring security architecture leverages servlet filters wherein each filter has exactly one responsibility.