Spring Security Authentication Process Explained In Detailed
Omar Ismail
Senior Software Engineer @ Digitinary | Java & Spring Expert ? | AWS & Microservices Architect ? | FinTech & Open Banking Innovator ?? | Digital Payments Expert ?? | Top 200 IT Content Creator in Jordan ?? | 40K+ ??
Core classes and interfaces
Before getting into the details of how actually authentication process works in spring security we would first like to understand some of the core important classes and interface that we need to use in the authentication process.
“AuthenticationManager”
It is a core interface that spring security uses for the authentication process. It has only one method?authenticate?which when implemented in a class that implements an Authentication Manager has?all the logic for authenticating a user request.
The authenticate method takes an “Authentication”?object as its parameter and returns an “Authentication”?object on successful authentication of the user or else we can have an exception thrown indicating that the user is not authenticated.
Spring security has a default implementation for Authentication Manager that is “ProviderManager”?which itself delegates the authentication request to list of configured “AuthenticationProvider”s which can either return a fully populated “Authentication”?object,?throw an exception?when authentication is failed?or return null?if it needs to skip the authentication for a particular authentication request.
We will not go in detail of “ProviderManager”?or “AuthenticationProvider”?as proceeding further in this article we will create our own class that implements “AuthenticationManager”?that would actually substitute “AuthenticationProvider”s as well as “ProviderManager” itself.
Below is a code snippet from my demo application in which I have implemented “AuthenticationManager”:
“Authentication”
It is a core interface that represents security information(Principal, Credentials, Authority list, etc.) in a spring security-specific manner.
It is used by the entire framework whenever there is a need to get authentication details of a particular request.
Frequently used implementation of the “Authentication”?interface is “UsernamePasswordAuthenticationToken”. It is not a direct subclass of “Authentication”?but it is a child of an abstract class that implements an “Authentication”?interface.
“UserDetailsService”
It is a core interface that is used by spring security to return the “UserDetails”?object. It is purely used to return user data wrapped in the form of “UserDetails”.
It has one method?loadUserByUsername(String userName).?As you can see it takes one String-based argument username and it returns a “UserDetails”?object.
The only purpose of “UserDetailsService”?is to provide a “UserDetails” object to other components of the spring security framework.
Below is a code snippet from my demo application in which I have implemented “UserDetailsService”:
“UserDetails”
It acts as an?adapter?between your application’s user representation and the representation of the user’s details that are needed by the spring security framework in the “SecurityContextHolder”?which is basically used to build the “Authentication”?object and have other functionality too which is described in next section.
“UserDetails”?basically holds principals, credentials, authorities and other information that is regarding a particular user.
“GrantedAuthority”
It is an interface that represents authorities that are granted to the user. A class implementing this interface should provide the representation of the user authority that is supported by “AccessDecisionManager”?that we will cover in the next article that is on Authorization in spring security.
领英推荐
It is provided in the “UserDetails”?object and used to give application-wide permissions. It should not be used to give per object permission for that spring security provided other interface.
It is usually loaded in “UserDetailsService”?implementation.
“SecurityContextHolder”
It is a core class of the framework that is used to store “SecurityContext”?information of the principal currently using the application.
“SecurityContext”: Information that represents the Authentication and Authorization information of the user currently access the application.
SecurityContextHolder uses “ThreadLocal”?variables to store the principal details.
ThreadLocal class provides variables that are local to a thread. Each thread has a copy of these variables and these variables are not shared between the threads in a multi-threaded environment.
So basically “SecurityContextHolder”?uses “ThreadLocal”?variables to store user information and so handles multiple requests that work in a multi-threaded environment in which each thread consists of the “SecurityContext”?information.
It's important to clear/remove security information once the request is processed and that is taken care of by the “SecurityContextHolder”?in the framework.
We can configure “SecurityContextHolder”?in a way our application wants the security information to be handled throughout the application requests that are made by the user.
There are three ways as follows:
So we can see that “SecurityContextHolder”?stores security information in the “SecurityContext”?interface implementation which is actually stored in thread-local.
And in “SecurityContext”?security information is represented in the form of an “Authentication”?object which in turn stores the information in the form of the “UserDetails”?object that actually represents user information in the framework.
Below is a code snippet from my demo application in which I have used “SecurityContextHolder”:
Below is a flow diagram that will describe the authentication process in a more understandable manner and will connect all the dots from the above-described classes and interfaces:
Thanks To : Developer’s World