Golden Recursion Inc. logoGolden Recursion Inc. logo
Advanced Search
Spring Security

Spring Security

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements.

Spring Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development. If you're not using Spring for developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity with Spring - and in particular dependency injection principles - will help you get up to speed with Spring Security more easily.

People use Spring Security for many reasons, but most are drawn to the project after finding the security features of J2EE's Servlet Specification or EJB Specification lack the depth required for typical enterprise application scenarios. Whilst mentioning these standards, it's important to recognise that they are not portable at a WAR or EAR level. Therefore, if you switch server environments, it is typically a lot of work to reconfigure your application's security in the new target environment. Using Spring Security overcomes these problems, and also brings you dozens of other useful, customisable security features.

As you probably know two major areas of application security are “authentication” and “authorization” (or “access-control”). These are the two main areas that Spring Security targets. “Authentication” is the process of establishing a principal is who they claim to be (a “principal” generally means a user, device or some other system which can perform an action in your application). “Authorization” refers to the process of deciding whether a principal is allowed to perform an action within your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. These concepts are common, and not at all specific to Spring Security.

At an authentication level, Spring Security supports a wide range of authentication models. Most of these authentication models are either provided by third parties, or are developed by relevant standards bodies such as the Internet Engineering Task Force. In addition, Spring Security provides its own set of authentication features. Specifically, Spring Security currently supports authentication integration with all of these technologies:

  • HTTP BASIC authentication headers (an IEFT RFC-based standard)
  • HTTP Digest authentication headers (an IEFT RFC-based standard)
  • HTTP X.509 client certificate exchange (an IEFT RFC-based standard)
  • LDAP (a very common approach to cross-platform authentication needs, especially in large environments)
  • Form-based authentication (for simple user interface needs)
  • OpenID authentication
  • Authentication based on pre-established request headers (such as Computer Associates Siteminder)
  • JA-SIG Central Authentication Service (otherwise known as CAS, which is a popular open source single sign on system)
  • Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (a Spring remoting protocol)
  • Automatic "remember-me" authentication (so you can tick a box to avoid re-authentication for a predetermined period of time)
  • Anonymous authentication (allowing every call to automatically assume a particular security identity)
  • Run-as authentication (which is useful if one call should proceed with a different security identity)
  • Java Authentication and Authorization Service (JAAS)
  • JEE container autentication (so you can still use Container Managed Authentication if desired)
  • Kerberos
  • Java Open Source Single Sign On (JOSSO) *
  • OpenNMS Network Management Platform *
  • AppFuse *
  • AndroMDA *
  • Mule ESB *
  • Direct Web Request (DWR) *
  • Grails *
  • Tapestry *
  • JTrac *
  • asypt *
  • Roller *
  • Elastic Path *
  • Atlassian Crowd *

Many independent software vendors (ISVs) adopt Spring Security because of this significant choice of flexible authentication models. Doing so allows them to quickly integrate their solutions with whatever their end clients need, without undertaking a lot of engineering or requiring the client to change their environment. If none of the above authentication mechanisms suit your needs, Spring Security is an open platform and it is quite simple to write your own authentication mechanism. Many corporate users of Spring Security need to integrate with "legacy" systems that don't follow any particular security standards, and Spring Security is happy to "play nicely" with such systems.

Sometimes the mere process of authentication isn't enough. Sometimes you need to also differentiate security based on the way a principal is interacting with your application. For example, you might want to ensure requests only arrive over HTTPS, in order to protect passwords from eavesdropping or end users from man-in-the-middle attacks. This is especially helpful to protect password recovery processes from brute force attacks, or simply to make it harder for people to duplicate your application's key content. To help you achieve these goals, Spring Security fully supports automatic "channel security", together with JCaptcha integration for human user detection.

Irrespective of how authentication was undertaken, Spring Security provides a deep set of authorization capabilities. There are three main areas of interest in respect of authorization, these being authorizing web requests, authorizing whether methods can be invoked, and authorizing access to individual domain object instances. To help you understand the differences, consider the authorization capabilities found in the Servlet Specification web pattern security, EJB Container Managed Security and file system security respectively. Spring Security provides deep capabilities in all of these important areas, which we'll explore later in this reference guide.

History

Spring Security began in late 2003 as “The Acegi Security System for Spring”. A question was posed on the Spring Developers' mailing list asking whether there had been any consideration given to a Spring-based security implementation. At the time the Spring community was relatively small (especially compared with the size today!), and indeed Spring itself had only existed as a SourceForge project from early 2003. The response to the question was that it was a worthwhile area, although a lack of time currently prevented its exploration.

With that in mind, a simple security implementation was built and not released. A few weeks later another member of the Spring community inquired about security, and at the time this code was offered to them. Several other requests followed, and by January 2004 around twenty people were using the code. These pioneering users were joined by others who suggested a SourceForge project was in order, which was duly established in March 2004.

In those early days, the project didn't have any of its own authentication modules. Container Managed Security was relied upon for the authentication process, with Acegi Security instead focusing on authorization. This was suitable at first, but as more and more users requested additional container support, the fundamental limitation of container-specific authentication realm interfaces became clear. There was also a related issue of adding new JARs to the container's classpath, which was a common source of end user confusion and misconfiguration.

Acegi Security-specific authentication services were subsequently introduced. Around a year later, Acegi Security became an official Spring Framework subproject. The 1.0.0 final release was published in May 2006 - after more than two and a half years of active use in numerous production software projects and many hundreds of improvements and community contributions.

Acegi Security became an official Spring Portfolio project towards the end of 2007 and was rebranded as “Spring Security”.

Today Spring Security enjoys a strong and active open source community. There are thousands of messages about Spring Security on the support forums. There is an active core of developers who work on the code itself and an active community which also regularly share patches and support their peers.

Features

In this section, we are going to direct our attention to the features that Spring Security has and what it can provide us or its use-cases. We are also briefly mentioning the "how" while doing so.

Password Encoding

The benefits of Spring Security are not limited to helping us with Authentication and Authorization. It can also help us to apply best practices in saving users, a.k.a, building a sign-up feature.

In the process of building a sign-up feature, there are some common mistakes that could result in severe security issues.

One of those mistakes is, saving the user passwords in plaintext without any kind of hashing. This not only allows the hackers who may gain access to your server to view the passwords directly but also opens your users to the threat of getting their other accounts cracked as well since the majority of people use the same passwords for all their accounts.

Another common mistake is trying to reinvent the wheel and create your own encryption/hashing algorithm instead of using the well-known, tested, proven algorithms.

Spring Security allows us to assign a secure password encoder to our UserDetails object to prevent these mistakes. By default, it uses BCrypt to encrypt the passwords, which is considered a well-rounded algorithm for encoding passwords. It is also possible to set the number of hashing rounds (or the strength as the parameter name suggests) and the secure random algorithm implementation to be used in the process.

BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion version, int strength, java.security.SecureRandom random)

It would not be surprising to encounter code snippets like this in a configuration class that extends WebSecurityConfigurerAdapter:

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}

In-Memory Authentication

In-Memory Authentication means using a database that stays in application memory/RAM (one example is the h2 database) to save users and perform the authentication without saving them to a persistent database. Such databases can be useful when you are building a proof-of-concept app or prototyping your application and need to get going or test your authentication code without bothering yourself with a database. An in-memory database is also useful if you run your tests without mocks so that your real database will remain untouched and the changes caused by tests will be in temporary memory.

Spring Security supports authentication of users who reside in the in-memory databases.

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // Some other configuration code here...

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth.inMemoryAuthentication().withUser("temporary").password("temp123").roles("ADMIN");
    }
}

LDAP Authentication

LDAP is short for Lightweight Directory Access Protocol, and it is commonly used for authenticating the user accounts of employees in enterprises. It allows you to specify users/user-groups in a hierarchical structure and define their permissions.

dn: cn=John Doe,dc=example,dc=com
cn: John Doe
givenName: John
sn: Doe
telephoneNumber: +1 888 555 6789
telephoneNumber: +1 888 555 1232
mail: john@example.com
manager: cn=Barbara Doe,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top

Spring Security has a project called "spring-security-ldap" that allows us to use LDAP Authentication in our Spring apps. Spring Boot also provides auto-configuration for an embedded LDAP server to save us from the difficult task of setting up an LDAP authentication server. You can take a look at this official tutorial for more information.

Session Management

In the applications where backend and frontend are tightly coupled, like Spring MVC applications or any other MVC framework: Whenever a user logs in, a session is stored in the server that holds information about this user. Operations like retrieving, caching, destroying this session are called Session Management. Spring Security provides mechanisms to control this session object. It will create the session when a user logs in, destroy it when they log out and allow us to set the timeout value.

Spring Security also takes additional measures to make sure the sessions are being utilized in a secure way:

  • It is configurable to disable using URL rewriting to avoid the Session Tracking attack.
  • It automatically migrates the session when the user logs in again to avoid Session Fixation.
  • It allows us to use httpOnly and secure flags on session cookies to protect our cookies.

Remember Me Authentication

Remember Me authentication is the mechanism to recognize the user after their session times out, so the users do not need to enter their credentials every time they visit the website. Spring Security supports multiple ways to implement this type of authentication.

The typical way to implement Remember Me authentication is by hashing the user details with a secret key that is on the server and encoding it along with the username and expiration time.

base64(username + ":" + expirationTime + ":" +
             md5Hex(username + ":" + expirationTime + ":" password + ":" + key))

    username:          As identifiable to the UserDetailsService
    password:          That matches the one in the retrieved UserDetails
    expirationTime:    The date and time when the remember-me token expires,
                       expressed in milliseconds
    key:               A private key to prevent modification of the remember-me token

Though it works, this approach has some flaws. If an attacker captures the cookie somehow, it will work by anyone from any source until it expires. The only way for the users to invalidate their tokens is to change their passwords.

A better approach for implementing Remember Me authentication is storing a persistent token in the database instead of the Remember Me cookie. The token is stored in a similar way to a session object, but the difference is that it is saved to a database instead of temporary application memory.

API Security with JWT (JSON Web Tokens)

We have mentioned that server-side sessions can be used to confirm the identity of a user and to keep track of their roles (what they are allowed to do). Since the REST is a sessionless protocol, it is advised not to store a session in RESTful APIs. We can instead make use of another popular approach to check if a user is authorized to take some action.

In applications that use JWT, after a user completes a successful login, an access token is generated with a secret key on the server, which usually contains information about the user's identity and token's generation timestamp. In separated frontend-backend architectures, the frontend stores this token in cookies.

It is possible to implement JWT Authorization for your application by making use of Auth0 JWT library for encoding/decoding the tokens. In addition to this, Spring Security may be used for filtering the requests and checking for the user's roles, only allowing the authorized users to pass through the filters.

OAuth 2.0

Open Authorization 2.0 is an open standard for checking a user's permissions on service with the help of an authorization server. It is not uncommon to use OpenID Connect to confirm the user's identity, and OAuth can then provide a token that contains the list of permissions for this user. After the user receives the OAuth 2 access token, they will use it to access the protected resources on the server. OAuth is a very popular standard, and it is also used to implement features such as Facebook login or Google account login, so even if you do not know what it is consciously, you probably used it before without knowing.

Setting up an authorization server and implementing OAuth and OpenID Connect comes with its own risks and can be time-consuming. It is easy to mess up and create a vulnerability by mistake.

Instead of trying to build everything from scratch, it is a good idea to integrate Spring Security with Auth0 and spend your precious time on improving the business logic instead. You can check out this awesome tutorial on securing your RESTful API with the help of Auth0 by Tadej to secure your API rapidly.

Building Blocks of Spring Security

In this section, we will take a look at several concepts which are heavily applied in Spring Security. Basic knowledge about these topics will serve as a foundation that we can build upon since all these topics are more or less connected to each other.

Chain of Responsibility

Chain of Responsibility is a GoF behavioral design pattern that aims to decrease the tight coupling between request handlers and the sender. The "chain" refers to a list of ordered request handlers, just like a LinkedList structure, and the request handler can be a method or a class that implements some Handler interface. The responsibility is just a fancy word of answering the request, each handler on the chain can either return a response (by taking the responsibility) or pass the request to the next handler on the chain (delegating the responsibility).

Filters

Before we start talking about filters, it is helpful to familiarize ourselves with Interceptors: An Interceptor is a class that implements the HandlerInterceptor interface and intercepts the web requests before they hit the controller. Its name is very descriptive of what it actually does, and a Filter can be thought of as a more specialized version of an Interceptor.

A Filter method runs after the request hits the Tomcat (or any other) web server and before its arrival to the servlet. This allows Filters to even be able to block the request from reaching the actual servlet, explaining why they are called Filters. There are many Filter interfaces in Spring Security that can be implemented to create a customized filter class. We could then tell Spring Security to add these Filters we created to its "Filter Chain."

If you are already wondering whether this "Filter Chain" has something to do with our Chain of Responsibility pattern, congratulations to you! That is why we started by learning the Chain of Responsibility pattern. Before we even add a single custom Filter, Spring Security will usually have around six filter chains by default (source), and they will start filtering out the requests as soon as we add Spring Security as a dependency.

Here is the sample code for a JWT Authorization Filter:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req,
                                    HttpServletResponse res,
                                    FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(HEADER_STRING);

        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }
}

You do not need to understand all of this but just glance over this doFilterInternal() method. It takes a FilterChain as its parameter and what it does is: Get the header from the request, check if it has a token and if it does not have it, pass it down the filter chain by calling:

chain.doFilter(req, res);

This is a pattern you will encounter often. Notice that the last line of this method is also the same.

Matchers

"Filters are nice and all, but they apply to every request as soon as I add them to my security configuration, and what if I want to apply a filter only to a single REST resource?" you might ask. This is when URL Matchers should come to the scene. URL Matchers in Spring Security are called Ant Matchers, historically named after Apache Ant build system, and they allow us to specify a regex-like matcher to determine which endpoints should be subject to filtering.

Example configuration:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(HttpMethod.GET, "/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new CustomFilter(authenticationManager())
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
    }

This code snippet allows all GET requests to URLs that start with "/public/" to bypass the filters. For any other request, the API consumer should be authenticated, and the custom filters will also apply. Code similar to this can be found in a Configuration class.

User Roles (Role-based Authorization)

Now that we know about Ant Matchers, we are able to specify the paths that filters will be applied to, but we still lack some flexibility to define role-specific permissions. For example, we could want an endpoint to be accessible only by users who have the role ADMIN or any arbitrary set of roles. By using role-based authorization/authentication, we can achieve such behavior. I will not give the whole code or a tutorial for implementing role-based security since it would be the topic for a whole new article by itself but you should know that Spring Security allows you to define roles for your users and apply filters depending on those roles as follows:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/").permitAll
            .antMatchers("/new-blog-post").hasAnyAuthority("ADMIN", "AUTH0 EMPLOYEE", "GUEST_WRITER")
            .antMatchers("/edit/**").hasAnyAuthority("ADMIN", "EDITOR")
            .antMatchers("/delete/**").hasAuthority("ADMIN")
            .and()
            .formLogin().permitAll()
            .and()
            .logout().permitAll();
    }

This could be the configuration for Auth0 blog permissions if it was built with Spring Security.

Conclusion

n this article, we have started by defining Spring Security and tried to provide insights about what kind of things a security framework provides. I hope it is more clear after reading the features section and seeing the example use cases for Spring Security.

After learning what it is good for, we have taken a look at some important concepts that can help us understand Spring Security better.

Timeline

Further Resources

Title
Author
Link
Type
Date

Spring Framework - Wiki

Web

Spring Security | FULL COURSE

Web

December 18, 2019

Spring Security Tutorial Step By Step - Example & Advantages - DataFlair

Web

July 12, 2018

Golden logo
By using this site, you agree to our Terms & Conditions.