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. 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:

[prismatic_encoded class=%%language-xml%%]Jmx0O2h0dHAgdXNlLWV4cHJlc3Npb25zPSJ0cnVlIiZndDsNCiAgICAmbHQ7aW50ZXJjZXB0LXVybCBwYXR0ZXJuPSIvKioiIGFjY2Vzcz0iaXNBdXRoZW50aWNhdGVkKCkiLyZndDsNCiAgICAmbHQ7aHR0cC1iYXNpYy8mZ3Q7DQombHQ7L2h0dHAmZ3Q7DQoNCiZsdDthdXRoZW50aWNhdGlvbi1tYW5hZ2VyJmd0Ow0KICAgICZsdDthdXRoZW50aWNhdGlvbi1wcm92aWRlcg0KICAgICAgcmVmPSJjdXN0b21BdXRoZW50aWNhdGlvblByb3ZpZGVyIiAvJmd0Ow0KJmx0Oy9hdXRoZW50aWNhdGlvbi1tYW5hZ2VyJmd0Ow==[/prismatic_encoded]

4. Java Configuration

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

@Configuration
@EnableWebSecurity
@ComponentScan("com.maixuanviet.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:

[prismatic_encoded class=%%language-bash%%]Y3VybCAtLWhlYWRlciAiQWNjZXB0OmFwcGxpY2F0aW9uL2pzb24iIC1pIC0tdXNlciB1c2VyMTp1c2VyMVBhc3MgDQogICAgaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NwcmluZy1zZWN1cml0eS1jdXN0b20vYXBpL2Zvby8x[/prismatic_encoded]

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.

Related posts:

Java Perform to a 2D FFT Inplace Given a Complex 2D Array
Jackson – Unmarshall to Collection/Array
Spring Boot - Apache Kafka
Java Program to Implement Sorted Array
A Guide to TreeSet in Java
Disable Spring Data Auto Configuration
Spring Boot - Building RESTful Web Services
Java Program to Implement Hash Tables chaining with Singly Linked Lists
Reversing a Linked List in Java
Spring @RequestMapping New Shortcut Annotations
Java Program to Perform integer Partition for a Specific Case
SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS
Java Program to Implement Quick Sort with Given Complexity Constraint
Java Program to Perform Arithmetic Operations on Numbers of Size
Java Program to Delete a Particular Node in a Tree Without Using Recursion
Một số từ khóa trong Java
Notify User of Login From New Device or Location
Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java
Custom Cascading in Spring Data MongoDB
How To Serialize and Deserialize Enums with Jackson
Convert a Map to an Array, List or Set in Java
Receive email using IMAP
Lập trình đa luồng với Callable và Future trong Java
Spring Data Java 8 Support
Removing all Nulls from a List in Java
Tránh lỗi NullPointerException trong Java như thế nào?
Hướng dẫn Java Design Pattern – Observer
Checked and Unchecked Exceptions in Java
Java Program to Implement a Binary Search Algorithm for a Specific Search Sequence
Split a String in Java
Hướng dẫn Java Design Pattern – Interpreter
The Spring @Controller and @RestController Annotations