Skip to content

OpenID user registration on Grails

July 1, 2008

Now that I’ve got OpenID working on noisyheads via the Acegi Security Plugin, time to create a user registration mechanism. Of course this is not your ordinary capture of user name, password, email address, your favorite Chuck Norris movie, stalked celeb address sort of thing. You have to authenticate the url submitted (done!), and get the response coming from the OpenID server that authenticates it. This response is then what you store as identifier for the user who would like to make use of your site. Of course, what’s sweet about this is that you have none of the password hashing and salting (you do hash passwords do you?), email confirmation kung fu. You can always, of course save an authentication response if it’s not yet registered in the db. But you would need some more details from that user rather than displaying “Welcome http://rockstaruser.openidproviderthatrocks.com.” Although OpenID do have some attribute exchange going on. I’d rather show my users a simple form for the first time just to be sure.

Basic scaffolds from the plugin didn’t really offer much (anything) for OpenID registration, so need to go dirty on this one. First, I need to ensure that a session is established as long as a valid OpenID authentication is made. So I need to change my UserDetailsService implementation again. It has to always return a valid user whenever a successful authentication is made. I overridden loadDomainUser method as so:

protected def loadDomainUser(username, session) throws UsernameNotFoundException, DataAccessException
{

        def query = session.createQuery(
                "from $loginUserDomainClass where 
                    $usernameFieldName=:username")
        query.setProperties([username: username])

        def users = query.list()

        if (users.empty)
        {
            String queryString = "from $loginUserDomainClass where
              $usernameFieldName='$DEFAULT_IDENTIFIER'"
            query = session.createQuery(
                    queryString)
            users = query.list()
        }

        if (!users[0])
        {
            logger.error("Cannot authenticate user.")
            throw new UsernameNotFoundException("User not found.", username)
        }

        return users[0]
    }

Where a DEFAULT_IDENTIFIER (to be declared later) is returned when identifier is not yet in the db. So let’s say I declared this to be “ROLE_NOT_QUITE_THERE.” I added this default role then to my boot strap utility. Gave it a shot. Then what do you know, any one with an OpenID account can now login with a role of “ROLE_NOT_QUITE_THERE.”

Now that I’ve got that out of the way, time for capture of additional details. Let’s say all i need is a display name. So in my spaghetti controller flow (I fucked it up bad), a user with a role defined above would always get redirected to the registration form. After which, if the value validates, the identifier now gets saved, assigned a new role (typically “ROLE_USER”), and the session updated to accommodated that. To do the session massaging, I needed to talk to SecurityContextHolder. Created a new Authentication (implemented by OpenIDAuthenticationToken), and shoved it in there. Here’s my whacked attempt:

private void updateSpringSecuritySession(accountIdentifier, role)
{
        def currentAuthentication = SCH.context.authentication

        def status = currentAuthentication.status
        def identityUrl = currentAuthentication.identityUrl

        def grantedAuthorities = new GrantedAuthorityImpl(role.authority) as GrantedAuthority[]

        Authentication newAuthentication = new OpenIDAuthenticationToken(grantedAuthorities, status, identityUrl)
        newAuthentication.details = accountIdentifier

        SCH.context.authentication = newAuthentication
   }

A little adjustment to my request mapping, and voila. Things seems an ounce more hopeful.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: