I'm looking for an implementation of a password retrieval procedure using the Acegi plugin for Grails...Google is failing me...
IMHO this is currently not part of the Acegi plugin. I've added a forgotPassword action to the LoginController:
def forgotPassword = {
if (params.username) {
User user = User.findByUsername(params.username)
if (user) {
def password = randomService.generateRandomString(8)
user.passwd = authenticateService.encodePassword(password)
if (!user.save(flush:true)) {
user.errors.each {
log.error "err $it"
}
flash.message = message(code: "LoginController.msg.forgot.error")
} else {
sendMail {
to user.username
subject message(code:"LoginController.mail.forgot.subject" )
body(view:"forgotPasswordEmail", model: [person:user, password:password])
}
flash.message = message(code:"LoginController.msg.forgot", args:[user.username] )
}
} else {
flash.message = message(code:"LoginController.msg.forgot.unknown", args:[params.username])
}
}
}
The code above uses the Grails mail plugin.
Google is failing you because there isn't one. It's really not possible to reverse the hashed password (without brute force cracking and rainbow tables), and if it were, that'd mean that your system was not secure.
The common pattern is to e-mail the user that forgot their password with a one time use token that they can then use to reset the password to whatever they want to. This isn't built into the framework, but it's not too hard to do manually (I'd suggest using the grails mail plugin).
The Acegi plugin doesn't support this out of the box, but if you add the email-confirmation plugin, it's pretty easy to roll your own.
Here are the steps:
Create a password reset form that asks the user to enter their email address and new password.
The controller action that handles the password reset form should validate the data and use the email-confirmation plugin to send an email to the user with a link for them to click on to confirm their change of password. You can do this by calling the following method on the EmailConfirmationService service added by the plugin.
def sendConfirmation(String emailAddress, String theSubject, Map model = null,
String userToken = null)
where:
emailAddress = address of user changing password
theSubject = subject of e-mail sent
model = any data passed to GSP that creates e-mail body
userToken = hashed user's password
when the user clicks on the link in the e-mail (refer to the plugin docs for info about how to customise this e-mail), the onConfirmation
closure of the service will be invoked.
This closure should be assigned in Bootstrap.groovy
like this:
def emailConfirmationService
def init = { servletContext ->
emailConfirmationService.onConfirmation = { email, hashedPassword ->
User user = User.findByEmail(email)
user.passwd = hashedPassword
if (!user.save()) {
// Handle this error, somehow....
}
// Then return a map which will redirect the user to the login screen (for example)
[controller:'userProfile', action:'login']
}
}
Notice that the user's email and hashed password are passed into this closure, enabling you to reset and save the user's password.