4

I would like to ask for your help regarding my problem in Spring Security. I have a requirement wherein I have to validate a login credential based on the option selected by the user. Option 1 would be validating the logged in user via third party service. Option 2 would be the normal validation using database authentication level. How can I implement this?

1 Answer 1

14

General Strategy

  1. Provide a custom implementation of org.springframework.security.authentication.AuthenticationProvider that delegates authentication to the appropriate backend (third-party service, another AuthenticationProvider, etc.).
  2. Pass the user-selected option to the custom AuthenticationProvider, enabling it to choose the correct authentication backend.
  3. Configure the custom AuthenticationProvider as the default authentication provider.

Step 1: Implement AuthenticationProvider

AuthenticationProvider is an interface with a single method. Therefore, a custom implementation may look like:

class DelegatingAuthenticationProvider implements AuthenticationProvider {
  @Autowired
  private ThirdPartyAuthenticationService service;

  @Autowired
  @Qualifier("anotherAuthenticationProvider")
  private AuthenticationProvider provider;

  @Override
  public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
    // Get the user selection.
    String selection = (String) authentication.getDetails();

    // Take action depending on the selection.
    Authentication result;
    if("ThirdParty".equals(selection)) {
      // Authenticate using "service" and generate a new
      // Authentication "result" appropriately.
    }
    else {
      // Authenticate using "provider" and generate a new
      // Authentication "result" appropriately.
    }

    return result;
  }
}

Step 2: Pass the user selection to the AuthenticationProvider

The AuthenticationProvider implementation above picks up the user selection from the details property of the Authentication object. Presumably, the user selection would have to be picked up from the HttpServletRequest and added to the Authentication object before the AuthenticationProvider is invoked. This means, another component that has access to both the Authentication and HttpServletRequest objects needs to be invoked before the AuthenticationProvider is called.

The Authentication object is created by an implementation of AbstractAuthenticationProcessingFilter. This class has a method named attemptAuthentication that accepts an HttpServletRequest object and returns an Authentication object. So it seems this would be a good candidate for implementing what is needed. For username-password based authentication, the implementation class is UsernamePasswordAuthenticationFilter. This class returns a new instance of UsernamePasswordAuthenticationToken, which is an implementation of Authentication. So, a class extending UsernamePasswordAuthenticationFilter should be sufficient.

class ExtendedUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
    ...
    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
    authentication.setDetails(obtainUserSelection(request));

    ...

    return authentication;
  }
}

obtainUserSelection is a private method that gets the user selection out of the request.

Step 3: Configuration

Configure the AuthenticationProvider and filter implementations in the Spring Security configuration. The exact steps will vary depending on whether XML or Java configuration is used.

Sign up to request clarification or add additional context in comments.

2 Comments

wow..thanks manish! this is one heck of a ride learning spring security. This is my first implementation by the way. can you point me to a tutorial site on implementing the ExtendedUsernamePasswordAuthenticationFilter? please :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.