Secure REST Services with Spring Security

A guest post by Josh Long, the lead author on Apress’ Spring Recipes, 2nd Edition, O’Reilly’s Spring Roo, and a SpringSource open-source project committer and contributor. You can reach him on his personal blog, the SpringSource Blog and on Twitter (@starbuxman).

Hi! I’ve just released a new video series introducing the Spring framework for Pearson’s Livelessons series. The video series runs the gamut of Spring’s various technnologies and introduces – among other things – container basics, web application development, (big-) data processing, messaging and integration, mobile- and cloud-computing with Spring.

In the last post, we introduced Spring’s rich REST support. In this post, we’ll look at how to secure those services for both typical, browser-bound HTTP clients, and for REST API clients using Spring Security and Spring Security OAuth.

Web Application Security with Spring Security

HTTP’s flexibility and simplicity can be deceptive. Just how does one secure a REST service? The answer is as always: it depends. What do you mean by authorization? Encryption? Authentication? Most of the concerns we have are already addressed and supported by the open web and Spring Security. Let’s look at the oauth module, which introduces security to the REST service we built up in our last installment.

HTTP Secure (HTTPS) is a communications protocol for secure communication on top of the SSL/TLS protocol. It protects against man-in-the-middle attacks and attempts to ensure the integrity of the payload communicated between two parties. You can easily set this feature up on most web servers as well as most cloud platforms. It’s fairly easy to setup SSL/TLS with Apache Tomcat or with a cloud platform like AppFog or Heroku. What little there is to do at the application level, Spring Security ably supports. HTTPS is something configured at the runtime-level, however, so we won’t explore this topic any further in this post. At the time of this writing, however, it was discovered that HTTPS, particularly older versions, has been compromised.

Username and Password Based Authentication

HTTP Basic Authentication provides a very simple way to handle access control. Another approach to securing an application is to simply use a login form on the application somewhere, typically in conjunction with something like a server-side session. Neither HTTP Basic Authentication nor sign-in forms provide any guarantee of confidentiality of transmitted content. They’re both best used in conjunction with SSL/TLS.

Installing Spring Security in our Servlet Application

We’ll use the Spring Security Java Configuration support to configure our application’s security rules. Spring Security is ultimately implemented in a web application as a javax.filter.Filter object configured in the servlet container. The Spring Security filter should be the front-line of the web application, inspecting every request as it goes through. To automate the installation of all of these components, Spring Security supports a custom WebApplicationInitializer subclass called AbstractSecurityWebApplicationInitializer. You simply extend the class and fill out the abstract template methods with information that it needs. See this example of an implementation of AbstractSecurityWebApplicationInitializer to secure our Spring application:

This WebApplicationInitializer instance is additive – it will be included in addition to any other initializers present. As you might imagine, this is a very convenient way for modules to provide out-of-the-box integration with the Servlet container. CrmSecurityApplicationInitializer implements the abstract callback method, afterSpringSecurityFilterChain which gives the client a chance to insert javax.filter.Filter instances into the Filter chain after Spring Security’s filter is installed. As we’re installing the Filter instances here, we can remove the corresponding entries from our CrmWebApplicationInitializer.

Configuring A Sign-In Form with Spring Security

The Spring Security Java configuration class presented next demonstrates how to setup form-based signin and signout functionality, and how to specify which URIs should be protected by that signin form. Our sample application uses H2, the embedded Java database. The H2 database console itself uses HTML frame elements and so runs afoul of a particular type of protection that Spring Security installs by default. The configurer object returned from the headers() method allows us to override the default HeaderWriter instances to avoid this problem:

Teaching Spring Security New Tricks

The userDetailsService instance registered in registerAuthentication is an implementation of Spring Security’s UserDetailsService interface. This interface is a strategy interface with numerous other backend implementations available supporting technologies like LDAP, Active Directory, pam, SAML, etc.

Our system already has a notion of a user. It’s easy enough to adapt Spring Security to our user management logic with a custom implementation of UserDetailsService. This interface is integral to Spring Security. The code below demonstrates how we wrap and adapt our existing user-management logic to fit in the Spring Security framework. The implementation mostly delegates what it can to our underlying service, and hard codes the rest as our application isn’t all that involved at the moment. Note, particularly, the scopes and role harccoded for the resulting UserDetails instances as we’ll refer to those again later.

Putting Out the welcome.html Mat

With all of this in place, any unauthorized HTTP request will be routed to the signin view (signin.html). When authentication is successful, the client is then redirected to /crm/welcome.html. The following presents the @Controller handler for the signin and welcome views, both of which are used in the signin process:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

packagecom.jl.crm.web;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

publicclassPageControllers{

@RequestMapping("/crm/welcome.html")

publicStringwelcome(){

return"welcome";

}

@RequestMapping("/crm/signin.html")

publicStringsignin(){

return"signin";

}

}

The markup for each view is simple, fairly typical HTML (again in the interest of conciseness and transparency). You could easily use Spring Mobile to conditionally render experiences tailored to mobile, desktop, or tablet clients. In this case, the markup is so simple that it looks equally boring on all platforms, so we didn’t need Spring Mobile. Here is the signin.jsp page:

Accessing the Currently Authenticated User from REST

First things first: we don’t want users reading other users’ information. We can deny access to the /users/ endpoint simply by adding another restriction in Spring Security:

1

2

3

4

5

6

...

http.authorizeRequests()

.antMatchers(filesToLetThroughUnAuthorized).permitAll()

.antMatchers("/users/*").denyAll()

.anyRequest().authenticated();

...

We still need a way to access the currently authenticated user. As a convenience, it’s useful to implement an endpoint to return the currently authenticated user, which we know we can get at from the Spring Security context. This code demonstrates one possible implementation for a REST endpoint situated at /user:

The controller injects the current User as a @ModelAttribute into the controller method argument. As you might imagine, having the current authenticated user available can be a handy thing in any complicated system. We could already simply inject the current Spring Security Authentication object then de-reference the principal, but this involves an ugly cast that would end up littered throughout the code. Instead, it’s easy enough to put that code in a Spring MVC @ControllerAdvice component. A @ControllerAdvice instance looks and feels very much like a controller in that it may register exception handlers (with the @ExceptionHandler annotation), and model attributes (with the @ModelAttribute annotation), etc., in a central place and is involved in every request. Here’s an implementation – SecurityControllerAdvice – that sets up a @ModelAttribute for the currently authenticated users:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

packagecom.jl.crm.web;

import com.jl.crm.services.*;

import com.jl.crm.services.security.CrmUserDetailsService;

import org.springframework.security.core.Authentication;

import org.springframework.web.bind.annotation.*;

import javax.inject.Inject;

@ControllerAdvice

publicclassSecurityControllerAdvice{

@Inject privateCrmService service;

@ModelAttribute

publicUser currentUser(Authentication authentication){

if(null==authentication){

returnnull;

}

CrmUserDetailsService.CrmUserDetails crmUserDetails=(CrmUserDetails

Service.CrmUserDetails)authentication.getPrincipal();

longuserId=crmUserDetails.getUser().getId();

returnthis.service.findById(userId);

}

}

With all of this in place, launch the application and then authenticate yourself using any of the users and passwords in the user_account table in our schema. By default, the application preloads data from crm-schema-h2.sql.

Scaling Web Security with Spring Security OAuth

Username and password-based access control works well enough for trusted clients. If you are the only person who knows your (hopefully randomized) password, then the chances that a malicious client might afflict your account are far lower. A password authentication scheme is a simple way to identify that a client is who it says it is. However, this scheme starts to fall apart in a world where multiple clients may interact with a service provider on your behalf. This is typical, for example, when using service-provider clients for Netflix, Facebook, Twitter, and Google+ clients across phones, desktop browsers, tablets, and TVs.

For a specific example, let’s look at the Facebook application ecosystem. Facebook opened up the Facebook object graph through its REST APIs and opened the door to a slew of application developers that wanted to deliver applications (“Sign In with Facebook”) and games integrated with your Facebook experience and data. Some of these API clients were better than others. Some were downright abusive! However, no matter how abusive a client got, it could never lock you out of your own account because it never had access to your password. Instead, clients authenticate with Facebook and other service providers using a system called OAuth.

You’ll recognize the telltale signs of OAuth when you use a “Sign In with Facebook” or “Sign In with Twitter” button on any number of web properties. Invariably, these buttons launch Facebook.com, prompt the user to sign in (if not already signed in) (as shown in Figure-1) and then prompt the user to authorize the permissions required by the application (shown in Figure-2). Once permission is granted, you’ll end up back where you started, but the application will have what it needs to authenticate you and sign you in. Convenient, eh?

Figure 1. The Facebook signin page.

Figure 2. The Facebook approval page.

Figure 3. The Facebook applications console.

When a user authorizes the application and requested permissions, Facebook ultimately redirects the client to the requesting application and conveys in that request an accessToken. The accessToken is like a session cookie, and tells the server which client is connecting on behalf of the authenticated user. Additionally, Facebook has the ability to track which applications are installed in an application console (shown in Figure 3). The console is powerful: here, a user may centrally control (including revoke) access to any and all clients, selectively.

A full discussion of OAuth is out of scope here, but you might check out Dr. David Syer’s many amazing posts on the subject from the Cloud Foundry blog in 2012. OAuth provides a few things we’ll desire as part of our system.

So: a username and password scheme certifies that a request is being made by a user. OAuth certifies that the request being made has the permission to do so from the user. That’s close enough to certifying the user for most applications that OAuth works with.

Introducing Spring Security OAuth

Integrating OAuth into our application is a snap thanks to Spring Security OAuth. Spring Security OAuth introduces the concept of a client – a logical notion composed of the authenticated user, a unique identifier, certain permissions (or scopes) that the client is permitted, and the type of OAuth connectivity supported by that client. OAuth supports varying levels of security, and can force the client to go through more hoops to increase the confidence in the security provided. We’re going to assume the common, but not exclusive, case of working with an Android mobile client. Spring Security OAuth needs information about which clients will connect.

The first thing you’ll notice here is that the class extends OAuth2ServerConfigurerAdapter instead of WebSecurityConfigurerAdapter. The two beans – passwordEncoder and textEncryptor – below are just no-op implementations of two APIs that Spring Security requires.

In Spring Security OAuth, the ClientDetailsService manages the information about which clients might connect, and how. To simplify setup, register an InMemoryClientDetailsServiceConfigurer in the registerAuthentication method. You could as easily plugin an implementation backed by a database.

Here, we have only one client in mind, so we’ll configure a client (android-crm) that requests two scope’s, read and write. Scopes are arbitrary strings. In the Facebook world, they correspond to things an API client might want to do, like post to your wall, access your email address, etc. In the Spring Security world, they line up with the grantedAuthorities returned from the CRM-specific UserDetails instances vended by our CrmUserDetailsService instance. In our application, these roles are arbitrary, hard-coded Strings. You can, of course, be as granular as you like in using this facility to limit access to certain parts of your application.

Once the user has successfully authenticated, an OAuth service sends back a token to be transmitted on all subsequent API requests. The service needs to remember that token. Spring Security OAuth delegates this chore to a TokenStore-implementation, in this case a JdbcTokenStore.

When users run through the OAuth dance with our application, on the other hand, they’ll be presented with a page to confirm what scopes the user authorizes to the client. We must provide this page ourselves. The code shown next is an implementation that prepares information and then renders access_confirmation:

Summary

This concludes the second of three posts. Here we covered how to secure our services for both typical, browser-bound HTTP clients, and for REST API clients using Spring Security and Spring Security OAuth. In the next and final post in this series we will cover the Java client-side with Spring core’s RestTemplate, Spring Social, and Spring for Android.

Be sure to look at the Spring resources below that you can find in Safari Books Online.

Safari Books Online has the content you need

Spring Framework LiveLessons (Video Training) provides a walking tour of all of the Spring projects, including: Spring, Spring MVC, Spring Data, Spring Batch, Spring Integration, Spring Security, Spring Social, and more. Josh introduces how to get started building modern day Spring applications while introducing the concepts behind them. In the lessons, Josh guides viewers through a look at the Spring stack and the features designed to support relational data access, NoSQL and big-data access, batch processing, integration and messaging, REST services, mobile clients, OAuth-secured, connected web applications, service provider APIs, and more!

Spring Recipes
continues upon the bestselling success of the previous edition but focuses on the latest Spring 3 features for building enterprise Java applications. This book provides elementary to advanced code recipes to account for the following, found in the new Spring 3.

Spring in Action, Third Edition is totally revised for Spring 3.0, and covers the latest features, tools, and practices including Spring MVC, REST, Security, Web Flow, and more. Following short code snippets and an ongoing example developed throughout the book, you’ll learn how to build simple and efficient J2EE applications.

About the author

Josh Long is the Spring developer advocate at SpringSource, by Pivotal. Josh is the lead author on Apress’ Spring Recipes, 2nd Edition, O’Reilly’s Spring Roo, and a SpringSource open-source project committer and contributor. When he’s not hacking on code, he can be found at the local Java User Group or at the local coffee shop. Josh likes solutions that push the boundaries of the technologies that enable them. Continue the discussion on his personal blog, the SpringSource Blog and on Twitter (@starbuxman).