views:

691

answers:

4

Hi,

I'm using the Acegi plugin in my Grails app. After a user registers, he is redirected to an action that is protected. Therefore, he is shown the login form.

However, I would prefer if the user was automatically logged in as soon as he completes registration. It seems like I could achieve this by redirecting to the action that the login form uses

redirect(uri:"/j_acegi_security_check?j_username=${username}&j_password=${passed}")

But this would send a HTTP request to the client (and back to the server) which shows the user's password. Is there a way I can login automatically in a secure fashion?

Thanks, Don

A: 

I haven't tried this with non-test code, but this is the method that I created to log a user in within my integration tests (after building/saving the appropriate users/roles in my test setup):

import org.codehaus.groovy.grails.plugins.springsecurity.GrailsDaoAuthenticationProvider
import org.springframework.security.providers.UsernamePasswordAuthenticationToken
import org.springframework.security.context.SecurityContextHolder

...

def logInAsUser(username, password) {
    daoAuthenticationProvider.getUserCache().removeUserFromCache(username) 
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password)
    SecurityContextHolder.context.authentication = daoAuthenticationProvider.authenticate(token)
}

I construct and inject the authentication token in the security context. There might be a little more that you need to do to get your user logged in and past security, but this would be the start of whatever that is.

I'll actually need to do exactly what you're asking in a week or two for my current app, post back if you figure it out fully before I do :).

Ted Naleid
This works if you have the password. If you don't, you can load the user via 'def user = User.findByUsername(username)' and setting the authority array in the 3-parameter constructor. Create the auths via 'GrantedAuthority[] auths = user.authorities.collect { new GrantedAuthorityImpl(it.authority) }'. Then you can omit the call to authenticate() and use 'SecurityContextHolder.context.authentication = new UsernamePasswordAuthenticationToken(username, 'unknown', auths)'
Burt Beckwith
does this really work? I have tried it unsuccessfully, only works if the password is provided
Aaron Saunders
+2  A: 

If you generate the controller classes for the spring security plugin (grails generate-registration) you'll see the following lines in RegisterController which does just what you want:

class RegisterController {

def daoAuthenticationProvider

    ...

    def save = {
        ...
        def auth = new AuthToken(person.username, params.passwd)
        def authtoken = daoAuthenticationProvider.authenticate(auth)
        SecurityContextHolder.context.authentication = authtoken
        redirect uri: '/'
    }

Be sure that params.passwd is the plain-text password (i.e. not hashed) and it works like a charm.

Dave
What is the package of AuthToken class?
tuler
Got it from http://stackoverflow.com/questions/2268266/grails-acegi-manual-login
tuler
A: 

Aaron - Burt's post does indeed work. Although the strange part while it is possible to bypass logging into protected pages, the unprotected pages now throw an exception

I added this my custom filter:

void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {

def roles = [new GrantedAuthorityImpl('ROLE_ADMIN')]

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken('admin', 'admin', roles as GrantedAuthorityImpl[])

SecurityContextHolder.context.authentication = token

chain.doFilter(request, response)

}

the exception thrown on unsecured pages: Caused by: groovy.lang.MissingPropertyException: No such property: domainClass for class: java.lang.String at AcegiGrailsPlugin$_addControllerMethods_closure23.doCall(AcegiGrailsPlugin.groovy:926) at AcegiGrailsPlugin$_addControllerMethods_closure23.doCall(AcegiGrailsPlugin.groovy) at UserController$_closure1.doCall(UserController.groovy:5) at UserController$_closure1.doCall(UserController.groovy)

Anonymous.e
A: 

I like Burt Beckwith's solution to auto-login without a password.

Being that my app does not have a user self-registration function. Can someone explain where in the app to add this code to support auto-login? Will it go in the LoginController or maybe the SecurityConfig file? Thank you for any help given.

Phil

higgledy