One more approach for diagnosing spring-security-core login errors
I wrote up a few techniques to help determine what is happening when you are unable to authenticate with use the Grails spring-security-core plugin here
and since then I’ve had to use them myself a couple of times. I have everything configured to easily debug the issues and often that ends up being the best approach, but not everyone is comfortable with a debugger, or not excited about the prospect of configuring their IDE with JAR sources and the other steps needed to properly debug. This and this Stack Overflow question
prompted me to document another approach.
This one is a rather dangerous and should be removed as soon as the issue is resolved because it prints cleartext passwords to the console, which is a huge security risk.
There are a handful of places where the cleartext password is available, but I think the most convenient is in the additionalAuthenticationChecks
method of DaoAuthenticationProvider
. The arguments to the method are the UserDetails
instance, which will have the hashed password from the database, and the UsernamePasswordAuthenticationToken
which will have the cleartext password.
To access this, create a subclass of DaoAuthenticationProvider
:
package deletethisasap import org.springframework.security.authentication.UsernamePasswordAuthenticationToken as UPAT import org.springframework.security.authentication.dao.DaoAuthenticationProvider import org.springframework.security.core.Authentication import org.springframework.security.core.AuthenticationException import org.springframework.security.core.userdetails.UserDetails class MyDaoAuthenticationProvider extends DaoAuthenticationProvider { protected void additionalAuthenticationChecks(UserDetails ud, UPAT auth) throws AuthenticationException { String hashedPassword = passwordEncoder.encodePassword( auth.credentials, null) boolean ok = passwordEncoder.isPasswordValid( ud.password, auth.credentials, null) println "Cleartext: '$auth.credentials' from DB: '$ud.password' hashed '$hashedPassword' Valid: $ok" super.additionalAuthenticationChecks ud, auth } }
and register it with the same bean name in grails-app/conf/spring/resources.groovy
:
import deletethisasap.MyDaoAuthenticationProvider beans = { daoAuthenticationProvider(MyDaoAuthenticationProvider) { userDetailsService = ref('userDetailsService') passwordEncoder = ref('passwordEncoder') userCache = ref('userCache') saltSource = ref('saltSource') preAuthenticationChecks = ref('preAuthenticationChecks') postAuthenticationChecks = ref('postAuthenticationChecks') authoritiesMapper = ref('authoritiesMapper') hideUserNotFoundExceptions = true } }
It prints the hashed password and the cleartext password, and the cleartext password hashed for comparison. This won’t necessarily be the same as the value from the database, for example when using bcrypt, but the encoder has an isPasswordValid
method to verify that they’re equivalent, so that is also printed.
This code assumes that you’re using standard form-based authentication (i.e. DaoAuthenticationProvider
) and that you’re not using a salt. If you are using salted passwords, dependency-inject the saltSource
bean and use it in the encodePassword
and isPasswordValid
methods.
Bert,
When are you planning to update the Security Plugin to use the released Spring Security? I see that you checked in changes but the site with the plugin details still shows the October release?
http://grails.org/plugin/spring-security-core
Thanks,
Joe
Dear Burt Beckwith,
I was trying to find your e-mail on Harvard Extension School website but ended up here, on your blog page (and I glad I did it!). I am very interested in taking a class you are offering this Fall but am a bit concern about prerequisite requirements. I have some educational experience with Java (including classes, objects, and design patterns). In addition, I am familiar with PHP and mySQL. Will it be enough to follow the course?