1. Overview

This is the eighth of a series of articles about setting up a secure RESTful Web Service using Spring 3.1 and Spring Security 3.1 with Java based configuration. This article will focus on how to authenticate against a secure RESTful User Account and Authentication Service.

The REST with Spring series:

2. The Goal

First, let’s go over the actors – the typical Spring Security enabled application needs to authenticate against something – that something can be a database, LDAP or it can be a REST service. The database is the most common scenario; however, a RESTful UAA (User Account and Authentication) Service can work just as well.

For the purpose of this article, the REST UAA Service will expose a single GET operation on /authentication, which will return the Principal information required by Spring Security to perform the full authentication process.

3. The Client

Typically, a simple Spring Security enabled application would use a simple user service as the authentication source:

<authentication-manager alias="authenticationManager">

   <authentication-provider user-service-ref="customUserDetailsService" />

</authentication-manager>

This would implement the org.springframework.security.core.userdetails.UserDetailsService and would return the Principal based on a provided username:

@Component

public class CustomUserDetailsService implements UserDetailsService {    

   @Override

   public UserDetails loadUserByUsername(String username) {    ...    }

}

When a Client authenticates against the RESTful UAA Service, working only with the username will no longer be enough – the client now needs the full credentials – both username and password – when it’s sending the authentication request to the service. This makes perfect sense, as the service itself is secured, so the request itself needs to contain the authentication credentials in order to be handled properly.

From the point of view or Spring Security, this cannot be done from within loadUserByUsername because the password is no longer available at that point – we need to take control of the authentication process sooner.

We can do this by providing the full authentication provider to Spring Security:

<authentication-manager alias="authenticationManager">

   <authentication-provider ref="restAuthenticationProvider" />

</authentication-manager>

Overriding the entire authentication provider gives us a lot more freedom to perform custom retrieval of the Principal from the Service, but it does come with a fair bit of complexity. The standard authentication provider – DaoAuthenticationProvider – has most of what we need, so a good approach would be to simply extend it and modify only what is necessary.

Unfortunately this is not possible, as retrieveUser – the method we would be interested in extending – is final. This is somewhat unintuitive (there is a JIRA discussing the issue) – it looks like the design intention here is simply to provide an alternative implementation which is not ideal, but not a major problem either – our RestAuthenticationProvider copy-pastes most of the implementation of DaoAuthenticationProvider and rewrites what it needs to – the retrieval of the principal from the service

Read the rest of the article