Spring Security Authentication Provider

1. Overview

This tutorial will show how to set up an Authentication Provider in Spring Security to allow for additional flexibility compared to the standard scenario using a simple UserDetailsService.

2. The Authentication Provider

Spring Security provides a variety of options for performing authentication – all following a simple contract – an Authentication request is processed by an AuthenticationProvider and a fully authenticated object with full credentials is returned.

The standard and most common implementation is the DaoAuthenticationProvider – which retrieves the user details from a a simple, read only user DAO – the UserDetailsService. This User Details Service only has access to the username in order to retrieve the full user entity – and in a large number of scenarios, this is enough.

More custom scenarios will still need to access the full Authentication request to be able to perform the authentication process – for example, when authenticating against some external, third party service (such as Crowd) – both the username and the password from the authentication request will be necessary.

For these, more advanced scenarios, we’ll need to define a custom Authentication Provider:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();

        // use the credentials to try to authenticate against the third party system
        if (authenticatedAgainstThirdPartySystem()) {
            List<GrantedAuthority> grantedAuths = new ArrayList<>();
            return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
        } else {
            throw new AuthenticationException("Unable to auth against third party systems");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Notice that the granted authorities set on the returned Authentication object are empty – this is because authorities are of course application specific.

3. Register the Auth Provider

Now that the Authentication Provider is defined, we need to specify it in the XML Security Configuration, using the available namespace support:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
      http://www.springframework.org/schema/security
      http://www.springframework.org/schema/security/spring-security-3.2.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <http use-expressions="true">
        ...
        <http-basic/>
    </http>

    <authentication-manager>
        <authentication-provider ref="customAuthenticationProvider" />
    </authentication-manager>

</beans:beans>

4. Do Authentication

Requesting Authentication from the Client is basically the same with or without this custom authentication provider on the back end – we can use a simple curl command to send an authenticated request:

curl --header "Accept:application/json" -i --user user1:user1Pass 
    http://localhost:8080/spring-security-custom/api/foo/1

Note that – for the purposes of this example – we have secured the REST API with Basic Authentication.

And we get back the expected 200 OK from the Server:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=B8F0EFA81B78DE968088EBB9AFD85A60; Path=/spring-security-custom/; HttpOnly
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 02 Jun 2013 17:50:40 GMT

5. Conclusion

In this article we discussed an example of custom authentication provider for Spring Security.

The implementation of this Spring Security Authentication Provider can be downloaded as a working sample project.

This is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Security on Google+ - you can follow me there:

GET THE 3 EBOOKS >>
Download the 3 eBooks: "Rest with Spring", "Persistence with Spring" and "Learn HttpClient"
×
Build Your Web App with Spring (and quickly prototype it to 90%)

,

  • Stephane

    Nice article. I had to explicitly instantiate the CustomAuthenticationProvider bean though.

    • baeldung

      Yeah, if you don’t have claspath scanning enabled for that package – you’ll have to manually instantiate the bean. I find it easier to have scanning enabled.
      Thanks. Eugen.

  • webiyo

    Inside CustomAuthenticationProvider’s authenticate() method,

    // returning null authentication
    else {
    return null;
    }

    is this a good idea ? what is the alternative ?? !!!

    • baeldung

      Good catch – it’s better to throw AuthenticationException instead of simply returning null – I updated the example. Thanks.

      • webiyo

        I am working on a project which should build two artifacts,

        1) Spring MVC based UI [WEB-Project] secured by typical spring security
        2) RestEasy based API layer [API-Project] secured by X-Auth-Token header.

        and one common java project for sharing RestEasy service interface definitions both in WEB & API projects.

        All the data access happens in API-Project, and API is using stateless spring security configuration with LDAP authentication

        WEB-Project is also using Spring Security but the authentication happens at API-Project layer and API-Project is responsible to provide authorization details to WEB-Project, authorization happens at both the layers ( duplicated ) !!!

        To achieve so I had created the CustomAuthenticationProvider which does the following,
        1) Calls the API for login with username/password acquired in WEB Project using form.
        2) Should set the WEB Session with X-Auth-Token which could be used by RestEasy API Client in WEB-Project
        3) The GrantedAuthorities should be fetched from the API-Project and put into WEB-Project per user session.

        ___________________________________

        REQUEST :

        Basically we have a API Implemented using JAX-RS with LDAP authentication using stateless Spring Security secured by a custom X-Auth-Token ( not the remember me token )

        And a UI which is not javascript based HTML5 UI but a traditional server side UI based on Spring MVC & Spring Security , this UI is getting user authorization ( which makes the scenario very complex )

        Could you come up with a demo app which has such implementation using Spring Security, JAX-RS & Spring MVC?

        This is a challenging idea to blog about !!!! which has not been discussed much on the internet !!

        Requesting you because I am a noob in such work and may end up doing id badly , where as you seem to have mastered the minute details of Spring & Spring Secueiry & REST

        • baeldung

          That’s an interesting scenario – it sounds like it’s functional and the MVC project does authenticate (as well as retrieve the required artifacts for authorization) agains the
          API. This pattern looks similar to an older article here on baeldung.
          I have implemented something similar with a standard MVC application with standard login and Spring Security, and an API application secured separately (also with Spring Security). I choose to have the client (js) send requests to the API directly, and only use the MVC web project to serve out the HTML.
          The API part is on github (https://github.com/eugenp/REST) and I will likely move the full web project over there as well at some point (but not in the immediate future).
          Thanks. Eugen.

  • Norman

    Thanks for the tutorial. I have a question. You’ve provided the security configuration xml where authentication-provider ref=”customAuthenticationProvider” is set. Could you please point where and how bean with id=customAuthenticationProvider should be specified. Thanks in advance

  • Norman

    Figured it out. Oh I’m such a noob. That bean can be defined in the XML Security Configuration as:

  • Burak

    Can you give login.xhtml code ?

    • baeldung

      I wrote in detail about login here
      Hope it helps.
      Cheers,
      Eugen.

      • Burak

        So customauthenticationprovider uses the login.xhtml on the link you give
        Thanks

        • Burak

          I’m using custom authentication and login.jsf. Do I have to use loginbean in my login.jsf file ?

          REVİR HASTA KAYIT

          .panelGrid {
          position: relative;
          height: 100px;
          margin: 0 auto;
          padding: 10% 0;
          }

        • baeldung

          One quick note about using comments – if you need to post any large code samples – please feel free to raise an issue on github and I’ll take a look (code doesn’t render well in comments).
          Thanks. Eugen.

  • Burak

    I would like to ask a question about CustomAuthProvider, in my auth provider, I did like this

    List grantedAuths = new ArrayList();
    grantedAuths.add(new SimpleGrantedAuthority(“ROLE_ogrenci”));
    Authentication auth = new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
    return auth;

    and my security xml

    It’s working but is it true to write like this ?

  • http://www.klebermota.eti.br/ Kleber Mota

    Hi Eugen,
    Do you know how to configure this Custom AuthenticationProvider in a java-based configuration of Spring Security? I have a class SecurityConfig where I am trying configure jdbcAuthentication, and because this I try autowire my UseDetailsService implementation in this custom class and I want see if this set up works.
    Kleber Mota

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Kleber – I have followed the new(ish) Java based configuration for Spring Security, but haven’t had a chance to use it yet. When I do – I will definitely write about it.
      Cheers.

    • Andreas Hucknyswon

      @Configuration
      @EnableWebMvcSecurity
      public class SecurityConfig extends WebSecurityConfigurerAdapter {

      @Override
      protected void configure( HttpSecurity http ) throws Exception {
      http.authenticationProvider( new MyAuthenticationProvider( ) );

      }

      ….

      }

  • Umanath M

    Fine, but we need to know more in web-service (either RestFul, or WS) with authentication which it as separate layer. It will consume from Spring MVC as presentation layer. And it also supporting token based authorization.

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Umanhath – not entirely show what you’re asking – can you try to give me some additional details please. Cheers,
      Eugen.

  • Antonio

    Very useful, thanks a lot for sharing!

  • Amit Garg

    Can you please help me with OAuth and spring security? I want to make a stateless application. I will write my own authentication provider, for the first time authentication. I want the subsequent requests to be using the OAuth token which the client will send to the server.
    I am unable to find any good example which has implemented something like this. Do you have any sample application for such set up?

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Amit – no, I have not written about OAuth and Spring Security yet – I do plan to as some point, but it may not be very soon. I’m assuming you’re aware of the official guide and the samples. Cheers,
      Eugen.

  • Eduardo B

    Hello, I have a similar scenario and your guide helped me a lot to succesfuly login to an external API. Now, when I get the API response, there are a lot of values that I should store “somewhere” for that user. I need this information to make sucesive calls. My first try was to access a custom User (UserDetails) object to store the values there but there was no luck. It appears that doing (after success on external login):

    User user = (User)(authentication.getPrincipal());

    freezes the app

    Maybe you could give me some guidance on this

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Eduardo – doing your own custom User implementation is relativelly straightforward and shouldn’t have any effect on your app if it implements UserDetails. Now – without a project (github, etc) that I can look at and replicate the issue, I cannot really go into more detail that that – but if you do have that up, I’d be happy to take a look. Cheers,
      Eugen.

      • Eduardo B

        Hello Eugen, thank you very much.
        I finally took another approach and it is working very well.
        I ended extending the UsernamePasswordAuthenticationToken with the properties that I need for further communication with the API. And it has sence because these values are in fact “Tokens”.

        Then, when I need my “Tokens” on any controller, I can use:
        SecurityContext context = SecurityContextHolder.getContext();
        BizToken auth = ((BizToken)context.getAuthentication());
        String bizToken = auth.BizToken;

        Do you think of any drawback for this approach?

        Thank you again!

        • http://www.baeldung.com/ Eugen Paraschiv

          Sounds good. I wouldn’t say that the extra info can be called a “token” but the approach does work and should not be a problem. Cheers,
          Eugen.

  • Carlos R

    Hi Eugen,

    First of all, you are creating a great and useful blog about persistence and security.

    I am creating a new application for my client and I need a special login form. This form
    is currently authenticating with a database table (users) in my local database
    (user/role tables) . I configured a static datasource (root) to connect to database and then, in the login form, I authenticate with the database table. The problem is that my client needs to create a kind
    of dynamic datasource. Thus, the authentication should be obtained from the oracle
    database user not from the user stored in my database table.

    I am currently defining this user (root) in a static properties file, so I have no
    idea about how to implement this. Is it possible in Spring security?

    Thank you!!