Security Top

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE

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. These follow 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 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. This is enough for most scenarios.

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();
        
        if (shouldAuthenticateAgainstThirdPartySystem()) {
 
            // use the credentials
            // and authenticate against the third-party system
            return new UsernamePasswordAuthenticationToken(
              name, password, new ArrayList<>());
        } else {
            return null;
        }
    }

    @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 we've defined the Authentication Provider, we need to specify it in the XML Security Configuration, using the available namespace support:

<http use-expressions="true">
    <intercept-url pattern="/**" access="isAuthenticated()"/>
    <http-basic/>
</http>

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

4. Java Configuration

Next, let's take a look at the corresponding Java configuration:

@Configuration
@EnableWebSecurity
@ComponentScan("com.baeldung.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private CustomAuthenticationProvider authProvider;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
            .and().httpBasic();
    }
}

5. Performing Authentication

Requesting Authentication from the Client is basically the same with or without this custom authentication provider on the back end.

Let's 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

For the purposes of this example, we've 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

6. Conclusion

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

The full implementation of this tutorial can be found in the GitHub project.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE
37 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Kleber Mota
6 years ago

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

Eugen Paraschiv
6 years ago
Reply to  Kleber Mota

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
Andreas Hucknyswon
6 years ago
Reply to  Kleber Mota

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

}

….

}

Umanath M
Umanath M
6 years ago

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.

Eugen Paraschiv
6 years ago
Reply to  Umanath M

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

Amit Garg
Amit Garg
6 years ago

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?

Eugen Paraschiv
6 years ago
Reply to  Amit Garg

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
Eduardo B
6 years ago

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

Eugen Paraschiv
6 years ago
Reply to  Eduardo B

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
Eduardo B
6 years ago

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!

Eugen Paraschiv
6 years ago
Reply to  Eduardo B

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
Carlos R
6 years ago

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… Read more »

Comments are closed on this article!