Michael
Michael

Reputation: 2510

Grails Spring Security Plugin Authentication Fails

I am trying to configure the spring-security 2.0-RC2 plugin to work with my Grails application. I am able to get it to insert my default admin user with a hashed password into mongodb. I have also configured spring security to use emailAddress instead of username as the username field for authentication.

When I attempt to login (with the correct credentials) I am getting an authentication failed error. I'm a bit stumped as to what I am doing wrong. I probably am missing something small that causes this not to work. My configuration is included below.

In Config.groovy I have the standard configuration and specify usernamePropertyName to point to the email address field instead of username.

grails.plugin.springsecurity.userLookup.userDomainClassName = 'model.Person'
grails.plugin.springsecurity.userLookup.usernamePropertyName='email'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'model.PersonRole'
grails.plugin.springsecurity.authority.className = 'model.Role'
grails.plugin.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap

//Configure URL Restrictions
grails.plugin.springsecurity.interceptUrlMap = [
  '/login/**':         [
    'IS_AUTHENTICATED_ANONYMOUSLY'
  ],
  '/static/**':        [
    'IS_AUTHENTICATED_ANONYMOUSLY'
  ],
  '/**':               [
    'IS_AUTHENTICATED_REMEMBERED']
]

grails.plugin.springsecurity.password.algorithm = 'SHA-256'

I then have a Person.groovy file that was generated by spring security then modified to change username to email address. The generated PersonRole.groovy and Role.groovy haven't been modified.

package model

class Person {
  transient springSecurityService

  String id
  String firstName
  String lastName
  String emailAddress
  String password

  boolean enabled = true
  boolean accountExpired
  boolean accountLocked
  boolean passwordExpired

  static transients = ['springSecurityService']

  static constraints = {
    emailAddress blank: false, unique: true
    password blank: false
  }

  static mapping = { password column: '`password`' }

  Set<Role> getAuthorities() {
    PersonRole.findAllByPerson(this).collect { it.role } as Set
  }

  def beforeInsert() {
    encodePassword()
  }

  def beforeUpdate() {
    if (isDirty('password')) {
      encodePassword()
    }
  }

  protected void encodePassword() {
    password = springSecurityService.encodePassword(password)
  }
}

In my BootStrap.groovy I create a default admin user unless one already exists:

def adminUser = Person.findByEmailAddress('[email protected]') ?: new Person(
    firstName: 'Admin',
    lastName: 'User',
    emailAddress: '[email protected]',
    password: springSecurityService.encodePassword('admin'),
    enabled: true).save(failOnError: true)

I also created a custom auth.gsp file as follows, but I have also tried using the default one with the same result.

<form action="${postUrl}" method="POST" autocomplete="off">
   <h4>Sign in</h4>
   <g:if test="${flash.message}">
      <div class="alert alert-danger" style="padding: 10px">${flash.message}</div>
   </g:if>
   <p>
     <input type="email" class="form-control" placeholder="Email address" name="j_username" autofocus />
   </p>
   <p>
     <input type="password" class="form-control" placeholder="Password" name="j_password" />
   </p>
   <input type="submit" class="btn btn-lg btn-primary btn-block" value="${message(code: 'springSecurity.login.button')}" />
 </form>

So, does anyone see anything I am missing that would stop authentication from working?

Upvotes: 0

Views: 2592

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75681

You're double-encoding the password. It's done in the Person class in beforeInsert, and you do it again in the BootStrap code. Change

password: springSecurityService.encodePassword('admin'),

to

password: 'admin',

Upvotes: 3

Related Questions