login automatically with Grails Spring Security
The reauthenticate()
method has two limitations:
- It don't check password
- It don't fire events. That's why a lot of plugins that listen events may not work. For example the brute force defender plugin.
If the user exists in the database use springSecurityService.reauthenticate()
- see this link for Grails 2 or this link for Grails 3.
This method is designed to update the authentication when a user change has made it out of sync with the database, but it's also useful for this scenario where you want to force a valid authentication for an existing user but don't know the password.
Maybe this code snippit from a webapp I wrote will help. We had to auth users using a RESTful API and they provided a username and an API key..The key piece in this code is setting the authorities and the authenticated boolean.
class CustomAppTokenAuthenticationProvider implements AuthenticationProvider {
def userDetailsService
Authentication authenticate(Authentication customAuth) {
def userDetails = userDetailsService.loadUserByUsername(customAuth.principal)
def user = User.get(userDetails.id)
if (user?.apiKey.equals(customAuth.credentials)) {
customAuth.authorities = userDetails.authorities
customAuth.authenticated = true
return customAuth
} else {
return customAuth
}
}
boolean supports(Class authentication) {
return CustomAppTokenAuthentication.class.isAssignableFrom(authentication)
}
}
And here is code from the filter that intercepts the API calls to handle the authentication
def userId = request.getHeader("x-user-external-id")
def apiKey = request.getHeader("x-user-api-key")
if (userId && apiKey) {
def user = User.findByExternalId(userId)
def myAuth = new CustomAppTokenAuthentication(
name: userId,
credentials: apiKey,
principal: user.username,
authenticated: false
)
def auth = authenticationManager.authenticate(myAuth);
if (auth?.authorities?.size() >= 0) {
log.info "Successfully Authenticated ${userId} in object ${auth}"
// Store to SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(myAuth);
} else {
SecurityContextHolder.getContext().setAuthentication(null)
}