Spring Security Architecture
Spring Security is a popular security framework for Java Enterprise applications. It helps to customize the access & authentication processes. It mainly focuses on authentication, authorization, and other security features.
Spring Security is based on a set of filter chains that are responsible for handling different aspects of the security process.
When clients send an HTTP request to our API, before it reaches the actual endpoint it goes through a series of filters. Filters are responsible for performing security checks based on the configuration. If any condition in the filters is not met, then it just returns a 401 or 403 response which means we are not authorized to perform the action.
Filters act as an interceptor for every request. It checks if the token has been sent to the server and if the token is valid. If not, it just rejects the request with 401 as the response.
Authentication Manager is the one that defines how the Spring Security filters perform authentication. Authentication Manager takes the request and performs authentication based on the provider. Authentication Manager is responsible for validating user credentials and Authentication Provider is responsible for loading user details & verifying user credentials.
If the authentication succeeds the user is added to the Security Context else is removed from Security Context.
Spring Security provides flexibility to create custom filter classes, Authentication Managers, and Authentication Providers. By adding custom filters, developers can extend the functionality of Spring Security and add their custom security checks.
To create a custom filter class, developers need to create a class that implements the Filter interface. This interface defines the methods that are required for a filter like init(), doFilter(), and destroy().
To create a custom Authentication Manager, developers need to create a class that implements the AuthenticationManager interface. This interface defines a single method, authenticate(), which takes an Authentication object as input and returns an authenticated Authentication object.
To create a custom Authentication Provider, developers need to create a class that implements the AuthenticationProvider interface. This interface defines two methods, authenticate() and supports(), which are used to authenticate user credentials and decide whether the Authentication Provider can handle a specific authentication request.
Once the custom classes are created, they should be added to the Security Configuration class which contains a configure() method where the authentication mechanism can be configured.
The custom filter can be added by calling addFilterBefore() or addFilterAfter(). And Authentication Manager is added by calling authenticationManager(), and Authentication Provider by authenticationProvider() methods.
Spring Security executes Authentication first and then Authorization is done.
- Authentication — verifies the identity of the user;
- Authorization — check access rights like roles
Bonus Content
The recommended order of method calls in the Spring Security Configuration configure() method is as follows,
cors()
— Cross-Origin Resource Sharing is a security mechanism that allows webpages from one domain to another.csrf()
— Cross-Site Request Forgery is a security mechanism that prevents malicious websites from executing unwanted actions on behalf of a user who is authenticated to a different website.sessionManagement()
— creates session managementaddFilterBefore()
oraddFilterAfter()
— called to add custom filtersauthorizeRequests()
— used to configure authorization rules for HTTP requests.exceptionHandling()
— configures how exceptions should be handled during the authentication & authorization process. By default, in case of exceptions Spring Security redirects to the login error page.authenticationProvider()
oruserDetailsService()
— called to add a custom Authentication ProviderformLogin()
— Provides Authentication using a login page. A session will also be created after successful authentication. Can be disabled if not required. This is more secure than httpBasic() as the credentials are encrypted on the network.httpBasic()
— Basic authentication where username & password are passed in headers to perform authentication. Credentials are verified with the database. Easy authentication but not secure. Can be disabled.logout()
— used to configure the logout behavior of the application.
This order ensures that filters and handlers are applied properly and the authentication & authorization process is executed correctly.
antMatchers() vs requestMatchers()
requestMatchers() should be used when we want to apply matching to request URLs only.
antMatchers() should be used when we want to apply matching to all requests including static resources.
requestMatchers(“/**”).authenticated() vs antMatchers(“/**”).authenticated()
requestMatchers(“/**”) matches all requests but applies to request URLs only. This means that static resources such as CSS, JavaScript, and image files are excluded from the matching and will not require authentication.
antMatchers(“/**”) matches all requests, including requests to static resources such as CSS, JavaScript, and image files. Therefore, if we use antMatchers(“/**”).authenticated(), even requests to static resources that do not require authentication will be intercepted and require authentication, resulting in a 403 error.
Below is the sample code of configure() from SecurityConfiguration class.
Spring Security is a powerful security framework. By understanding the architecture of Spring Security, developers can build secure web applications that protect sensitive data & resources from unauthorized access.
Thank you!!