Spring Security Architecture fundamentals
Authentication and authorization are fundamental to the security of web applications. While authentication determines if the user can be identified by the system, Authorization determines if the user has the access to the specific resource.
The authentication, as well as authorization design paradigm, is continuously evolving. The main reason behind it is the continuous evolution in different methods of exploits used against the applications.
Spring security tries to solve this problem by packaging all the possible solutions together.
The purpose of this article is to provide a high level understanding of spring security architecture for Servlet applications. It may not help you to immediately implement spring security in your application but it would definitely help you in the subsequent steps when you dive deeper.
Filter pattern in spring security
Spring Security for web applications uses the filter pattern to implement different types of security solutions. At the very core of it are Servlet filters. Spring framework provides DelegatingFilterProxy
filter and Spring security adds FilterChainProxy
filter on top of it. Both these filters are pivotal in Spring security.
DelegatingFilterProxy Filter
Similar to the Servlet filters, the Spring Security filters implement Filter
interface but they are also Spring beans which mean they are managed by Spring ApplicationContext
.
Since these filters are not registered via Servlet container standards(configured in web.xml), the servlet Container is not aware of them.
Spring provides DelegatingFilterProxy
filter which sits in the filter chain. It bridges the Servlet containers lifecycle and Spring ApplicationContext
.
When a request is delegated to DelegatingFilterProxy
. It looks up bean filters from the application context and then invokes the relevant bean filter. DelegatingFilterProxy
filter also allows for delayed bean Filter lookup.
FilterChainProxy Filter
Spring security provides a special bean filter named as FilterChainProxy
. This filter is a single entry point that enables spring security for a web application.
It allows delegating requests through a set of filters bundled as SecurityFilterChain
. In order to determine which Spring Security Filter’s should be invoked, FilterChainProxy
uses SecurityFilterChain
. There could be multiple SecurityFilterChains
present.
FilterChainProxy
is also used to perform some security-specific tasks such as clearing SecurityContext
. FilterChainProxy
is more flexible than traditional Servlet Filters. It can determine which securityFilterchain
to invoke by leveraging the RequestMatcher
interface.
SecurityFilterChain
It is a list of security filters that are also Spring managed beans. These are registered with FilterChainProxy. The advantage of being registered with SecurityFilterChain
are following:
FilterChainProxy
leverages RequestMatcher
interface to determine invocation based upon anything in ServletRequest
including the URL. In case of multiple SecurityFilterChains
, FilterChainProxy
can determine which SecurityFilterChain
should be used. It also clears SecurityContext
to avoid any memory leaks.
Customizing the default SecurityFilterChain
Spring security creates an instance of WebSecurity
via WebSecurityConfiguration
. WebSecurity
is responsible for creating an instance of FilterChainProxy
filter.
We can create customizations to the built-in functionality by —
- Either extending
WebSecurityConfigurerAdapter
and exposing it as a Configuration - Or implementing
WebSecurityConfigurer
and exposing it as a Configuration.
This configuration is imported when using @EnableWebSecurity
annotation.
AuthenticationEntryPoint
- When a client sends a request without authentication credentials, an implementation of
AuthenticationEntryPoint
will be used to send the response to the client to ask for credentials.
The AuthenticationEntryPoint
implementation might perform a redirect to a log-in page, respond with an WWW-Authenticate header, etc.
AbstractAuthenticationProcessingFilter
This is the base filter used for authenticating the requests. When the user request comes in
- If it has credentials pre-populated, the implementation of
AbstractAuthenticationProcessingFilter
is directly called. - If the credentials are not populated, the implementation of
AuthenticationEntryPoint
is called first to request credentials from the client- After that
AbstractAuthenticationProcessingFilter
is directly called.
- After that
Authentication Architecture API
AuthenticationManager
This is a strategy interface that provides the API to perform authentication. It is invoked by spring security filters. The authentication
object that is returned is set on SecurityContextHolder
.
It basically checks the authentication and decides
- If the principle is valid
- If the principle is invalid
- If the authentication is null
In case, Security Filters are not used such as when using user-defined filters, Authentication
can be set on SecurityContextHolder
manually.
ProviderManager
It is a common implementation of AuthenticationManager
. It delegates to a list of AuthenticationProvider
s. Each AuthenticationProvider
has the opportunity to authenticate as well as to show that it can not.
It also allows an optional parent AuthenticationManager
. If no AuthenticationProvider
is provided, the parent AuthenticationManager
is consulted for authentication.
If no authenticationProviders
can authenticate, authentication fails.
AuthenticationProvider
Its implementations performs a specific type of authentication. For example, DaoAuthenticationProvider
supports username/password based authentication while JwtAuthenticationProvider
supports authenticating a JWT token.
SecurityContextHolder
This object contains the authentication information about a request.
It contains SecurityContext
which by default is a threadLocal
object. thus every request thread has its own SecurityContext
object.
Security Context
The securityContext
object contains Authentication
Object. The Authentication
object serves two main purposes within Spring Security —
It acts as an input to
AuthenticationManager
to provide the credentials a user has provided to authenticate.AuthenticationManager.authenticate(Authentication authentication)
It also represents the currently authenticated user. The current
Authentication
can be obtained from theSecurityContext.
SecurityContextHolder.getContext().getAuthentication()
Authentication provides the below details regarding an authenticated user:
Principal
— which identifies the user. When authenticating with a username/password this is often an instance ofUserDetails
interface.Credentials
— is basically the passwordGrandtedAuthorities
— provide the authorization scope for the principal. It is fine grained scope for authorization.GrantedAuthorities
can be obtained from theAuthentication.getAuthorities()
method.
if you have reached this far and want to explore more on spring security. Here are a few posts to get you going.