This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

Custom AuthenticationProvider and UserDetailsService

Sep 17th, 2010, 02:33 AM

hi,

I have few newbie questions about authentication.

First of all I'm using Spring Security 3.0.3, Spring 3.0.3 and Flex on the client side.

In my application I need to authenticate user with not only login and password but also certificate, so it's more complicated. I need to check these things in database (I'm using Hibernate), so the scenario looks like this: I concatenate password wth certificate to send them as one parameter and I am sending login and password+certificate to the server. Then I need to process this data (split these two, query all needed user data, check if the cartificate is correct).

What would be the best solution in this case? I thought I can implement my own UserDetailsService (to query data from the database with Hibernate) and AuthenticatonProvider (to check if user can be authenticated; besides I need to perform some other tasks like logging and so on). I discovered, that something like this is not possible:

So maybe I should just implement AuthenticationProvider and perform all I need in authenticate method? I mean querying user info from the database, checking if user can be authenticated, putting my UserDetails implementation into Authenticate object and so on. Is this correct? It doesn't feel elegant. Is there any better solution?

Comment

It's a custom authentication process. The username and a credential submitted would be used to authenticate the user against a COTS document management application using it's own specific Java API (not based on a user table comparing hashed passwords). I can not retrieve user details until the the user is authenticated first by this specific Java API.

I was planning on extending the AbstractUserDetailsAuthenticationProvider and overriding the authenticate and retrieveUser methods, the Authentication method to perform the validation of credentials using the Java API and the retrieveUser to return the UserDetails object that will be populated from the COTS document management tool. I noticed as soon as I override the authenticate method, the retrieveUser method is not called.

Comment

Great feedback from the forum, I really appreciate it. I did download the source code and refer to the api docs which were very helpful.

Let me layout my intentions and hopefully you can validate I'm on the right path of using Spring Security correctly.

I have a Flex client that will be integrated with Spring BlazeDS and Spring Security. I have to perform the authentication BEFORE retrieving my UserDetails, as this is a binding-based strategy (user credentials are needed to authenticate and gain access to the underlying data repository).

Approach will be to create a custom authenticationProvider by extending the AbstractUserDetailsAuthenticationProvider. Since authentication needs to take place to retrieve UserDetails, the validation and population of the UserDetails will occur within the retrieveUser method. I will not be utilizing the additionalAuthenticationChecks method, as it is called after the retrieveUser method.

Is this the correct approach for a binding-based strategy? Should I have any concerns around having the authentication take place within the retrieveUser method? The api docs state that '...it is important that subclasses either disable caching...', how do I do this and will this be a problem for a stateful application?

Comment

I have taken your suggestion and have implemented the AuthenticationProvider interface directly, overode the supports method returning the appropriate AuthenticationToken and overode the authenticate menthod, where I perform my validation of credentials using the specfic Java API for the COTS product.

To answer your questions, authentication is performed by trying to log the user into the COTS product using their specific Java API, I'm basically returning a boolean if it is successful or not, if not successful then throw a BadCredentialsException. Access to data within the COTS repository is determined by ACLs within the COTS product. Again, I can only retrieve data or user data from the COTS repository by first authenticating the user. This is because it's a binding-based strategy, where the the user credientials are used to access the data and needs to be first authenticated.

I now have both the AbstractUserDetailsAuthenticationProvider and the custom AuthenticationProvider working successfully in my test environment. What is the benefit of using AuthenticationProvider over AbstractUserDetailsAuthenticationProvider or the other way around? If I use AuthenticationProvider, I lose out in populating the UserDetails, where as the AbstractUserDetailsAuthenticationProvider, I am able to return the UserDetails from within the retrieveUser method (I would authenticate the user within the retrieveUser method and then populate and return the UserDetails).

Comment

Curious if there is any feedback of the benefit of using AuthenticationProvider over AbstractUserDetailsAuthenticationProvider or the other way around? If I use AuthenticationProvider, I lose out in populating the UserDetails, where as the AbstractUserDetailsAuthenticationProvider, I am able to return the UserDetails from within the retrieveUser method (I would authenticate the user within the retrieveUser method and then populate and return the UserDetails).

Comment

Hi Luke, What are the pros and cons between implementing AuthenticationProvider and extending AbstractUserDetailsAuthenticationProvider ?
How to avoid losing out populating UserDetails by implementing AuthenticationProvider ?
What are the key points for a sufficient "externally-defined concept of authentication" ?