Archive for January, 2014

One more approach for diagnosing spring-security-core login errors

Thursday, January 30th, 2014

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 as UPAT

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.

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.