08Dec
Spring Security Basics
Spring Security Basics

We have to secure our applications and data since security threats can not be ignored for an application. Spring Security is a framework for securing Spring-based applications. In this article, we will look over the core security concepts and how Spring Security provides solutions for the common security concerns.

Okay, let’s first figure out the problem in terms of security terminology.

Think that we have an asset; that’s a web application and it should be protected against threats.

Here, what a threat is, in information security, it’s a way of exploiting vulnerabilities; it’s a potential for the occurrence of a fatal impact which compromise of confidentiality, integrity or availability of our system. And if a threat is actualized, then we name it as an attack. A typical scenario is depicted in the following diagram.

Application Security Concepts

Application Security Concepts

1. Security Aspects

As you see in the diagram above, we want to protect the following aspects of our assets that are well-known as CIA Triad:

Confidentiality targets the privacy of our system. We have to ensure that our application is accessed only by authorized users. We call this concept authenticity in software development. And this leads us to another concept, identity. Our users have to be identified and authenticated. Besides, we have to make some kind of access controls to map which pieces of data to be accessed by which authenticated users. And this is authorization.

Integrity is about the consistency and accurate modification of our data, and this requires authorized modification of the data. The data have to be modified only by authorized users or processes. Besides, error detection and correction should be made.

Availability is about the continuity of the authorized access to the system. Our assets should be accessible in a reasonable time, and with a capacity enough, our services have to response in an acceptable period of time. If not, we call it denial of service, it’s the opposite of availability.

2. About Spring Security

As you see, authentication and authorization is at the heart of the security. Spring Security provides several configurable servlet filters to provide authentication and authorization for our web applications and also for supplying these aspects, it provides the commons in the presentation layer such as login pages.

To understand the Spring Security, we should first delve into the basics up to the Servlets. In Java EE world, Servlet simply is a web technology with which we can receive and handle the HTTP requests, create HTTP response and return that response back to the client.

Servlet technology makes a basis for other Java web technologies on top of which other frameworks put their extensions. For example JSP, JSF, Spring MVC are such technologies which are uses Servlet technology at behind.

***So we can say that, Java + Http means Servlet in its core.

When we get to a Spring web application from that point, we can now say that it should be a Servlet somewhere managing the http requests. And that is the DispatcherServlet. Let’s look over the following diagram:

Dispatcher Servlet

Dispatcher ServletThe DispatcherServlet, as a front controller, gets the http request and forwards it to the Spring components that can be a Controller or an Actuator Endpoint.

While doing this, some security aspects could be handled by leveraging another Servlet feature, filters.

Filters are heavily used in Servlet technology as pre-processors and/or post-processors and can be chained.

So, in our case, Spring Security configures some security filters on the DispatcherServlet on behalf of us. When a request comes, these filters run and filter the request by making some checks such as CSRF exploits or/and authenticates the request. And after the run of these filters, the DispatcherServlet routes the request to our @Controllers/@RestControllers/@Endpoints.

That’s the outline of the Spring Security, and it’s time to inspect the details.

3. Start-up A Sample Secure Spring Boot Application

Spring Security is mostly about wiring some security filters to the DispatcherServlet and making the configuration of these filters. And as you guess, Spring Boot makes this wiring process easy for us with auto-configuration.

Now, let’s try it out in a simple Spring Boot application and see the default behaviours of an auto-configured security by Spring Boot.

3.1 Security Starter Dependency

Adding security to a Spring Boot application is just one step away from us. We just add the following dependency and see what happens then.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

If we start up the application after adding this dependency, the default security configuration is applied with the use of SecurityAutoConfiguration class. And later on, if we make a form-login request then we will first be directed to a login page and after the authentication with the password printed in the Spring Boot logs, we will be able to access the requested page. Or, if we make a request to any of our rest endpoints we will be authorized automatically with the password printed in the Spring Boot logs and we will be able to access the endpoint.

And all these are happened via the auto-configured security filters over the DispatcherServlet.

3.2 Overriding UserName and Password

As we already know, we can override the auto-configured properties in our application configuration. And here, we can do this to specify our application’s credentials with the following properties:

spring.security.user.name
spring.security.user.password

4. Spring Security Filter Chain In-Depth

Now, we know that Spring Security makes some wirings with servlet filters for us at behind and that filters secure our applications.

We can print all that security filters configured for us by adding the annotation below:

@EnableWebSecurity(debug = true)

And let’s look over the default security filters in detail.

Security Filter Chain

Security Filter ChainHere, we will cover some of these security filters mostly used.

4.1 Security Filters Explained

As you see in the diagram above, Spring provides a special filter named DelegatingFilterProxy which acts as a central filter wiring the Servlet container to the Spring Application Context. This special filter delegates all the work to another special filter named FilterChainProxy provided by Spring Security. Why such a configuration is designed is that; while DelegatingFilterProxy is wired as a standard configuration of Servlet Container, the filters provided by the Spring Security are loaded lazily by the Spring framework. When FilterChainProxy gets the request, it makes an evaluation over the request and routes it to one of the filter-chains configured via the Spring Security named SecurityFilterChain. And later on, the security filters in this chain are executed sequentially and in the order as declared in FilterComparator. That’s it.

As we already know, in a servlet container, URL is the only decision parameter for selecting the filters to be executed. However, SecurityFilterChain has a RequestMatcher that can have a specific matching algorithm on HttpServletRequest and that matcher is checked by the FilterChainProxy to find the correct security filter chain.

4.2 SecurityContextPersistenceFilter

SecurityContextPersistenceFilter is the gateway filter to the authentication mechanism in Spring Security. Basically, it manages the lifecycle of the SecurityContext in a request by getting the SecurityContext probably from HttpSession and associating it with the current execution thread in the SecurityContextHolder and at the response time it simply clears the SecurityContext from the SecurityContextHolder.

Yes, that’s enough to know this much for now. We will deeply cover the authentication process later and we will go over all these concepts.

4.3 HeaderWriterFilter

HeaderWriterFilter is responsible for writing some security headers to the current response to enable browser protection.

Some of the headers inserted by Spring Boot are as follows:

  • X-Content-Type-Options: This header is used to prevent content sniffing by adding such a header:
    • X-Content-Type-Options: nosniff
  • X-XSS-Protection: With this header, XSS protection can be enforced and this makes browsers block rendering the page or sanitize it if an XSS reflection attack is detected. Spring Security defaults this header to block mode.
    • X-XSS-Protection: 1; mode=block
  • Cache-Control: The following headers are inserted to prevent caching if no cache control headers have been specified.
    • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    • Pragma: no-cache
    • Expires: 0
  • Strict-Transport-Security: This header is inserted by Spring Security if the request is transported over HTTPS. The header forces secure connections and prevents session data stored in cookies to be lost.
    • Strict-Transport-Security: max-age=31536000 ; includeSubDomain
  • X-Frame-Options: This header is inserted to help avoiding clickjacking(UI redress attack).
    • X-Frame-Options: DENY
  • Content-Security-Policy: Content Security Policy (CSP) header helps a web application declare the trusted sources from which scripts can be loaded.
    • Content-Security-Policy: script-src https://myscripts.com
    • Spring Security does not insert this header into the response by default. So it can be configured as follows to be inserted into the response header:
.headers()
    .contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/");
  • Referrer-Policy: This header is about the submission of the previous page information to the destination.
    • Referrer-Policy: same-origin
    • Spring Security does not insert this header into the response by default. So it can be configured as follows to be inserted into the response header:
.headers()
    .referrerPolicy(ReferrerPolicy.SAME_ORIGIN);
  • Feature-Policy: This header allows web site owners to enable or disable the features and APIs of the web browser. Feature-Policy will be replaced by Permissions-Policy header.
    • Feature-Policy: camera ‘none’; fullscreen ‘self’;
    • Spring Security does not insert this header into the response by default. So it can be configured as follows to be inserted into the response header:
.headers()
    .featurePolicy("geolocation 'self'");

4.4 CsrfFilter

CsrfFilter is about to prevent the Cross-Site Request Forgery attacks. This filter is executed for any request that allows state to change, so in your API the REST semantics have to be strictly applied and you should not change state with the HTTP methods GET, HEAD, TRACE, OPTIONS.

4.5 LogoutFilter

LogoutFilter is executed if the incoming request matches with the RequestMatcher of this filter which is defaulted to /logout. This filter has some default handlers to be executed while logout and you can also write your own custom logout handlers for specific use-cases.

We will deeply cover the logout process, so here that’s enough to know that there is a such filter.

4.6 UsernamePasswordAuthenticationFilter

The RequestMatcher of this filter is defaulted to /login. And if a /login request is made then this filter reads username and password from the request body, if exists then authenticates the user.

4.7 BasicAuthenticationFilter

BasicAuthenticationFilter is executed if Basic Authentication data is provided in the header of the HTTP request. Meaning that, if a value is found for the key Authorization in the header, then the filter tries to authenticate the user.

4.8 RequestCacheAwareFilter

This filter helps to do a very familiar action. When we make a request for a resource that requires authentication, the authentication process starts and we provide our credentials and login. After the authentication process, the request before the authentication process is got from the RequestCache and reconstituted.

4.9 SecurityContextHolderAwareRequestFilter

SecurityContextHolderAwareRequestFilter wraps the original HttpRequest with SecurityContextHolderAwareRequestWrapper. By doing so, the authentication-related methods provided by the HttpServletRequest, such as getRemoteUser, isUserInRole.., can access the Authentication object in the SecurityContext and provide the related data.

4.10 AnonymousAuthenticationFilter

SpringSecurity creates an Authentication object for the authorized requests. For example, if you login with formLogin or basic authenication then a UsernamePasswordAuthenticationToken exists in the SecurityContext as Authentication object. However, an unauthorized user can acces unprivileged resources without authentication. This time no Authentication object exists in the SecurityContext. An unauthorized user can access unprivileged resources with one of two ways:

  • by calling HttpSecurity.anonymous() and giving ANONYMOUS role to related resources.
  • by calling permitAll() and giving access to all roles.

Calling anonymous, guarantees the SecurityContext having an Authentication object having the role ANONYMOUS. But technically this is not different than having no Authentication object.

These are some of the filters executed within an http request. We will cover these and some of other filters in the later topics.

5. Disabling Auto-Configuration

As we have already noted that adding spring-boot-security-starter dependency makes use of default security configuration for us with the use of SecurityAutoConfiguration.

So if we want to disable security completely we can extract these dependency from the pom.xml or we can exclude the SecurityAutoConfiguration as following:

@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })

But in real life scenarios, we generally do not do this, instead, we need to override the default configuration to be able to handle more advanced security requirements.

6. Custom Configuration of Spring Security

For basic scenarios, spring security auto-configuration provides a quick solution, but mostly we need a more customized security configuration, such as separating the roles of the api provided, different authentication schemes and etc.

Custom Configuration can be applied implementing separate configuration classes by extending WebSecurityConfigurerAdapter.

6.1 WebSecurityConfigurerAdapter & SecurityFilterChain

Now let’s look over the overall process and try to understand the custom configuration. We will use the following diagram to understand it better.

Filter Chain Configuration

Filter Chain Configuration

  • An http request comes in and routed to the DispatcherServlet by the servlet container.
  • The servlet container first runs the servlet filters mapped to the DispatcherServlet.
  • One of these filters is DelegatingFilterProxy, which is a standart servlet filter and eagerly wired to the DispatcherServlet.
  • DelegatingFilterProxy, on the ther hand, delegates all the work to another special filter named FilterChainProxy.
  • FilterChainProxy makes an evaluation over the request and routes it to one of the filter-chains configured via the Spring Security named SecurityFilterChain.
  • A SecurityFilterChain contains security filters and these filters are not eagerly bounded to the DispatcherServlet. They are configured via a special configuration class which implements WebSecurityConfigurerAdapter.
  • In a typical scenario, if i need to secure my /api/** endpoints, i write a class that implements WebSecurityConfigurerAdapter and configure it to bind several security filters to it. If i need to secure my /web/** endpoints with the different security mechanisms than the former one then i write another security configuration class that again implements WebSecurityConfigurerAdapter and configure it to bind the relevant security filters to it. That’s all i do to handle the security configuration.

Here is a sample of the custom configuration of a SecurityFilterChain:

@Configuration 
@Order(value = 101)
public class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.headers().contentSecurityPolicy("script-src 'self'");
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.antMatcher("/api/**")
        	.authorizeRequests()
                .antMatchers("/api/order/**").hasRole("USER")
                .anyRequest().authenticated()
                .and().httpBasic();
    }
	
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
            .antMatchers("/register", "/api/public/**");
    }
	
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
      	    .withUser("test_usr").password(encoder.encode("test_passw")).roles("USER")
      	    .and()
      	    .withUser("admin_usr").password(encoder.encode("admin_passw")).roles("USER", "ADMIN");
    }
}

6.2 WebSecurityConfigurerAdapter

WebSecurityConfigurerAdapter provides 3 overloaded methods to configure the web security:

  • configure(AuthenticationManagerBuilder auth)
    This method can be overriden to configure application-specific user realms into Spring Security.
  • configure(WebSecurity web)
    This method can be overriden to ignore certain requests.
  • configure(HttpSecurity http)
    This method can be overriden to configure certain url matches and their filter bindings.

In this section, we will look over the third one and inspect how the HttpSecurity is used to configure security filter bindings.

6.3 HttpSecurity

HttpSecurity allows configuring web based security for specific http requests. This is where the security filters we have listed above are configured for certain url paths. Let’s look over the methods provided by HttpSecurity.

First of all, the order of method calls on the HttpSecurity matters and the common usage is as follows:

  • First configure the general purpose filters to be applied to all requests such as csrf(), headers().
  • Then restrict the HttpSecurity to specific paths.
  • Apply specific configurations such as authentication on the restricted paths.

6.3.1 antMatcher

As we have noted earlier, a WebSecurityConfigurerAdapter is the configuration of a SecurityFilterChain that we have inspected with the diagrams above. A SecurityFilterChain is targeted if and only if its RequestMatcher is evaluated and matched with the incoming request url. antMatcher provides a single url matching option for the SecurityFilterChain. Meaning that, if a single url pattern is enough to map the requests for the current SecurityFilterChain then antMatcher is an appropriate option to use.

@Configuration
public class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
	
        http.antMatcher("/api/**")
        	    .authorizeRequests()
                .antMatchers("/api/order/**").hasRole("USER")
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}

In the code above, the SecurityFilterChain is matched only for the requests starting with /api and so the antMatcher is an option to match the requests.

6.3.2 requestMatchers

If we need to map multiple urls to the SecurityFilterChain then we can combine the url paths using requestMatchers and antMatchers.

@Configuration
public class MultipleUrlConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
            .antMatchers(HttpMethod.GET, "/web/**")
            .antMatchers(HttpMethod.POST, "/web/**")
            .and().authorizeRequests()
            .anyRequest().authenticated()
            .and().formLogin(); 		 		 		
    }
}

This is basically how HttpSecurity matches the urls and maps the requests to the relevant SecurityFilterChains. We will have a lot to go with HttpSecurity in the next articles since it provides a wide range of configuration methods.

7. Summary

In this article, we have looked over the Spring Security basics. First, we defined the security aspects and threats, then we introduced the Spring Security architecture based on the Servlet technology. We have started up a basic Spring Boot application with auto-configured Spring Security. Later on, we have made some custom configuration and looked over the RequestMatcher pattern.

We have a lot to go on Spring Security. In the next article, we will examine the authentication and authorization process in Spring Security in detail.

Keep following for the next article.

You can see the sample code for this article on my Github page:

https://github.com/erolhira/spring/tree/master/spring-security

2 Replies to “Spring Security Basics”

  1. Felix.mellado 4 years ago

    Really nice explanation about security process. Thanks

  2. Nice article but I have a question.
    Your last diagram shows that requests are going from a client then passing to security filters and after this will hit the dispatcherServlet.
    This means that all the filters that we implement will be handled externally by the servlet server (e.g Tomcat) and Tomcat will apply all this filters and only if everything is valid the request will hit our spring application?

    So we have something like filters and the servlet container level (Tomcat) and filters at application level (spring)?

    Thanks

Leave a Reply