Spring Authorization server + spring security with custom user details service for flexible data-driven authentication
Spring Authorization Server The Spring Authorization Server is a framework designed to implement the OAuth 2.1 and OpenID Connect 1.0 specifications, along with other related standards. Built on Spring Security, it offers a secure, lightweight, and customizable foundation for creating Identity Providers compliant with OpenID Connect 1.0 and OAuth2 Authorization Server solutions. Feature List What is Spring Security and how does it work? short answer Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. At its heart, Spring Security is essentially a collection of servlet filters designed to enhance your web application with robust authentication and authorization features. Spring Security also meshes well with frameworks like Spring Web MVC or Spring Boot, supporting standards such as OAuth2 and SAML. It automatically generates login and logout interfaces and safeguards your application from common security vulnerabilities like CSRF. Well, that's not very helpful, is it? Let's delve into web security to grasp the essentials of its security workflow. To become a Spring Security expert, you must first grasp these three core concepts: Authentication Authorization Servlet Filters Note - Don't bypass this section; it lays the groundwork for all Spring Security functionalities. Authentication You need to access your bank account online to check your balance or make a transaction. Typically this is done using UserName and Password User: "I'm John Doe. My username is: johndoe1985." Bank's System: "Please verify your identity. What's your password?" User: "My password is: secureB@nk2023." Bank's System: "Welcome, John Doe. Here's your account overview." Authorization For basic applications, authentication alone might suffice: Once a user logs in, they're granted access to all areas of the application. However, in most applications, there are permissions or roles in play. User: "Let me play with that transaction …." Bank's System: "One second, I need to check your permissions first…..yes Mr. John Doe, you have the right clearance level. Enjoy." User: "I'll transfer 1M ha ha ha … Kidding kidding" Servlet Filters Now, let's explore Servlet Filters. How do they relate to authentication and authorization? Why use Servlet Filters? Every Spring web application revolves around a single servlet: the trusty DispatcherServlet. Its primary role is to route incoming HTTP requests (such as those from a browser) to the appropriate @Controller or @RestController for handling. Here’s the deal: the DispatcherServlet itself doesn’t have any built-in security features, and you probably don’t want to handle raw HTTP Basic Auth headers directly in your @Controllers. Ideally, authentication and authorization should be taken care of before a request even reaches your @Controllers Fortunately, in the Java web environment, you can achieve this by placing filters before servlets. This means you could consider creating a SecurityFilter and setting it up in your Tomcat (servlet container/application server) to intercept and process every incoming HTTP request before it reaches your servlet. A SecurityFilter has roughly 4 tasks First, the filter needs to extract a username/password from the request. It could be via a Basic Auth HTTP Header, or form fields, or a cookie, etc. Then the filter needs to validate that username/password combination against something, like a database. The filter needs to check, after successful authentication, that the user is authorized to access the requested URI. If the request survives all these checks, then the filter can l et the request go through to your DispatcherServlet, i.e. your @Controllers. FilterChains In practice, we'd break a single filter down into several, which you would then link together. Here's how an incoming HTTP request would travel: First, it passes through a LoginMethodFilter... Next, it goes through an AuthenticationFilter... Then, it moves to an AuthorizationFilter... And finally, it reaches your servlet. This setup is known as a FilterChain. By using a filter (or a chain of filters), you can effectively manage all authentication and authorization challenges in your application without altering the core implementation of your @RestControllers or @Controllers. Spring’s DefaultSecurityFilterChain Imagine you’ve configured Spring Security properly and started your web application. You’ll notice a log message that looks like this: 2020-02-25 10:24:27.875 INFO 11116 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@46320c9a, org.springframework.security.web.context.SecurityContextPersistenceFilter@4d98e41b, org.springframework.securi
Spring Authorization Server
The Spring Authorization Server is a framework designed to implement the OAuth 2.1 and OpenID Connect 1.0 specifications, along with other related standards. Built on Spring Security, it offers a secure, lightweight, and customizable foundation for creating Identity Providers compliant with OpenID Connect 1.0 and OAuth2 Authorization Server solutions.
What is Spring Security and how does it work?
short answer
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
At its heart, Spring Security is essentially a collection of servlet filters designed to enhance your web application with robust authentication and authorization features.
Spring Security also meshes well with frameworks like Spring Web MVC or Spring Boot, supporting standards such as OAuth2 and SAML. It automatically generates login and logout interfaces and safeguards your application from common security vulnerabilities like CSRF.
Well, that's not very helpful, is it?
Let's delve into web security to grasp the essentials of its security workflow.
To become a Spring Security expert, you must first grasp these three core concepts:
- Authentication
- Authorization
- Servlet Filters
Note - Don't bypass this section; it lays the groundwork for all Spring Security functionalities.
Authentication
You need to access your bank account online to check your balance or make a transaction. Typically this is done using UserName
and Password
User: "I'm John Doe. My username is: johndoe1985."
Bank's System: "Please verify your identity. What's your password?"
User: "My password is: secureB@nk2023."
Bank's System: "Welcome, John Doe. Here's your account overview."
Authorization
For basic applications, authentication alone might suffice: Once a user logs in, they're granted access to all areas of the application.
However, in most applications, there are permissions or roles in play.
User: "Let me play with that transaction …."
Bank's System: "One second, I need to check your permissions first…..yes Mr. John Doe, you have the right clearance level. Enjoy."
User: "I'll transfer 1M
ha ha ha … Kidding kidding
"
Servlet Filters
Now, let's explore Servlet Filters. How do they relate to authentication and authorization?
Why use Servlet Filters?
Every Spring web application revolves around a single servlet: the trusty DispatcherServlet. Its primary role is to route incoming HTTP requests (such as those from a browser) to the appropriate @Controller or @RestController for handling.
Here’s the deal: the DispatcherServlet itself doesn’t have any built-in security features, and you probably don’t want to handle raw HTTP Basic Auth headers directly in your @Controllers
. Ideally, authentication and authorization should be taken care of before a request even reaches your @Controllers
Fortunately, in the Java web environment, you can achieve this by placing filters before servlets. This means you could consider creating a SecurityFilter and setting it up in your Tomcat (servlet container/application server) to intercept and process every incoming HTTP request before it reaches your servlet.
A SecurityFilter has roughly 4 tasks
- First, the filter needs to extract a username/password from the request. It could be via a Basic Auth HTTP Header, or form fields, or a cookie, etc.
- Then the filter needs to validate that username/password combination against something, like a database.
- The filter needs to check, after successful authentication, that the user is authorized to access the requested URI.
- If the request survives all these checks, then the filter can l et the request go through to your DispatcherServlet, i.e. your @Controllers.
FilterChains
In practice, we'd break a single filter down into several, which you would then link together.
Here's how an incoming HTTP request would travel:
- First, it passes through a LoginMethodFilter...
- Next, it goes through an AuthenticationFilter...
- Then, it moves to an AuthorizationFilter...
- And finally, it reaches your servlet.
This setup is known as a FilterChain.
By using a filter (or a chain of filters), you can effectively manage all authentication and authorization challenges in your application without altering the core implementation of your @RestControllers
or @Controllers
.
Spring’s DefaultSecurityFilterChain
Imagine you’ve configured Spring Security properly and started your web application. You’ll notice a log message that looks like this:
2020-02-25 10:24:27.875 INFO 11116 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@46320c9a, org.springframework.security.web.context.SecurityContextPersistenceFilter@4d98e41b, org.springframework.security.web.header.HeaderWriterFilter@52bd9a27, org.springframework.security.web.csrf.CsrfFilter@51c65a43, org.springframework.security.web.authentication.logout.LogoutFilter@124d26ba, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@61e86192, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@10980560, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@32256e68, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@52d0f583, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5696c927, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5f025000, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5e7abaf7, org.springframework.security.web.session.SessionManagementFilter@681c0ae6, org.springframework.security.web.access.ExceptionTranslationFilter@15639d09, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4f7be6c8]|
Expanding that single line reveals that Spring Security doesn’t just add one filter—it sets up an entire filter chain with 15 (!) different filters.
When an HTTP request arrives, it passes through each of these 15 filters in sequence before finally reaching your @RestControllers. The order of these filters is crucial, as the request is processed from the top of the chain to the bottom.
Analyzing Spring’s FilterChain
Diving into the details of every filter in the chain would take us too far, but here are explanations for a few key filters. For a deeper understanding of the others, you can explore Spring Security’s source code.
- BasicAuthenticationFilter: Tries to find a Basic Auth HTTP Header on the request and if found, tries to authenticate the user with the header’s username and password.
- UsernamePasswordAuthenticationFilter: Tries to find a username/password request parameter/POST body and if found, tries to authenticate the user with those values.
- DefaultLoginPageGeneratingFilter: Generates a login page for you, if you don’t explicitly disable that feature. THIS filter is why you get a default login page when enabling Spring Security.
- DefaultLogoutPageGeneratingFilter: Generates a logout page for you, if you don’t explicitly disable that feature.
- FilterSecurityInterceptor: Does your authorization.
Joke
Question - Why did the HTTP request break up with the Spring Security filter?
Answer - Because every time it tried to get closer, the filter said, "Hold on! Let me check you out first!"
What's Your Reaction?