How to programmatically logout in acegi plugin in Grails? - grails

Is there a similar logic for logout using this login code:
// login account
def autht = new AuthToken(username, password)
def authtoken = daoAuthenticationProvider.authenticate(autht)
SecurityContextHolder.context.authentication = authtoken
I checked LogoutController and this is the only logic for logout:
redirect(uri: '/j_spring_security_logout')
Any idea? Thanks

You would need to invalidate the session:
session.invalidate()
and remove the authentication:
SecurityContextHolder.clearContext()
You also need to remove their remember-me cookie if that's supported. Add a dependency injection for rememberMeServices ("def rememberMeServices") and call
rememberMeServices.logout request, response, null

Related

Grail's Spring security: Use email instead of username to switch users in SwitchUserFilter

I have a modified User class in my spring security which use attribute email instead of username. Now I want to a functionality to switch users, so an admin can login seamlessly as a particular user without logging out. I came across this Link , which shows there is a switchUserFilter to achieve this. So I tried to get it working by passing j_username as email,but it gets redirected to a blank page and the user does not switch.
I have tried all these things but still could not figure out a way around it:
1) Added to Config.groovy:
grails.plugins.springsecurity.userLookup.usernamePropertyName='email'
2) Create a method in User class getUserName() to return email.
P.S: I looked into the source code of springSecurity switchUserFilter(link)and came across this code on line 209:
protected Authentication attemptSwitchUser(HttpServletRequest request)
throws AuthenticationException {
UsernamePasswordAuthenticationToken targetUserRequest;
String username = request.getParameter(usernameParameter);
But I am not sure if that is the issue and do not want to make changes in the plugin.
The usernameParameter property of the SwitchUserFilter is set to username by default. That does seem to be part of your problem.
The SwitchUserFilter has a method named setUsernameParameter() that allows you to change this default. It seems the filter is a bean, so you might be able to do something like this in grails-app/conf/spring/Config.groovy
import org.springframework.security.web.authentication.switchuser.SwitchUserFilter
beans = {
switchUserFilter {
usernameParameter = 'email'
}
}
Or maybe something like this in grails-app/config/BootStrap.groovy
def switchUserFilter
def init = { servletContext ->
switchUserFilter.usernameParameter = 'email'
}
Finally found the solution: Add this to the config.groovy file
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'email'
grails.plugin.springsecurity.useSwitchUserFilter = true
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
....
'/j_spring_security_switch_user': ['ROLE_SWITCH_USER', 'isFullyAuthenticated()'],
'/j_spring_security_exit_user': ['isFullyAuthenticated()'],
'/public/**': ['permitAll']
.....
]
2) Then create a Role ROLE_SWITCH_USER in bootstrap.groovy
def switchUserRole = Role.findByAuthority('ROLE_SWITCH_USER') ?: new Role(authority: 'ROLE_SWITCH_USER').save(flush: true, failOnError: true)
And assign it to a super user
3) Then follow the instruction(here) to update the view to add a switch button

How do I manually "log a user in" using WebSecurity + SimpleMembership?

I'd like to use WebSecurity+SimpleMembership, but implement the ability to (optionally) login users via a custom/alternative authentication method.
WebSecurity.Login only has one method signature, which requires both a username and a password. I'd like to skip the password check, e.g.:
if (MyCustomAuthenticationMethod.Authenticate(username, customData)) {
WebSecurity.Login(username); // Login without password check, method doesn't exist though
}
I assume custom-auth-methods are possible given OAuthWebSecurity exists, but I'm not sure how to go about implementing my own.
Well, you could simply go back to root of authentication and call directly
FormsAuthentication.SetAuthCookie
This will create cookie and authenticate your user.
See Asp.net Memebership Authorization without password
They didn't make it easy to login without a password. One method could be to make your own custom OAuth plug-in and simply call it with your own token like this:
OAuthWebSecurity.Login("google", "token", true);
You can find here how to create a custom OAuth provider:
http://www.codeguru.com/columns/experts/implementing-oauth-features-in-asp.net-mvc-4.htm
And you can browse the code here: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/Microsoft.Web.WebPages.OAuth/OAuthWebSecurity.cs
Here is a snippet from OAuthWebSecurity.cs file that shows the internals of how to user is authenticated without password:
internal static bool LoginCore(HttpContextBase context, string providerName, string providerUserId, bool createPersistentCookie)
{
var provider = GetOAuthClient(providerName);
var securityManager = new OpenAuthSecurityManager(context, provider, OAuthDataProvider);
return securityManager.Login(providerUserId, createPersistentCookie);
}
Perhaps someone out there already made this plugin.

Does Spring Security gives any such API where I can pass username & password and get the Authentication Object?

Does Spring Security gives any such API where I can pass username & password and it will return either Authentication Object for successful authentication or AuthenticationCredentialsNotFoundException for unsuccessful authentication?
Let me elaborate my requirements:
Our application has a HTTP API(say, /createXXX.do) and the client is hitting this with username, password & other parameters.
Now I want to authenticate + authorize this access (coming from HTTP Hits to my application).
My planned design is like below:
a) I will not restrict access of my HTTP API context(i.e. /createXXX.do)
b) Once the request reached my doGet()/doPost(), I will retrieve the username & password from request and want to use some spring security API like below:
Authentication validateXXXXX(String username, String password)
throws AuthenticationCredentialsNotFoundException;
c) so that this above API internally push these username/password to the existing spring security chain and return me the Authentication Object for successful authentication or AuthenticationCredentialsNotFoundException for unsuccessful authentication.
d) For unsuccessful authentication, I will catch AuthenticationCredentialsNotFoundException and return the HttpServletResponse with AUTHENTICATION_ERROR code.
e) and for successful authetication, based on authiories from Authentication Object, I will allow or return the HttpServletResponse with AUTHORIZATION_ERROR code.
Can anyone know about such spring security API?
Any pointers/suggestion will be highly appreciated.
Thanks.
If you have just one authentication source (only LDAP or only DB) you can configure some implementation of org.springframework.security.authentication.AuthenticationProvider in your security context. Then you can use it:
User user = new User(login, password, true, true, true, true, new ArrayList<GrantedAuthority>());
Authentication auth = new UsernamePasswordAuthenticationToken(user, password,new ArrayList<GrantedAuthority>());
try {
auth = authenticationProvider.authenticate(auth);
} catch (BadCredentialsException e) {
throw new CustomBadCredentialsException(e.getMessage(), e);
}
// but your need to push authorization object manually
SecurityContext sc = new SecurityContextImpl();
sc.setAuthentication(auth);
SecurityContextHolder.setContext(sc);
It is "low level" manipulation. You can use element from Spring Security namespace. It can provide login controller, even login form for you (and it can handle this situation automatically).

How to force a programmatic logout using Grails / Spring Security Core?

How can i force a programmatic logout for a logged in user using Spring Security Core? I do not want to redirect to the logout page etc.. but need to do it in a service.
This is another approach. I get the logout handlers from bean "logoutHandlers" and do logout in each one of then:
def logoutHandlers
def logout(request,response) {
Authentication auth = SecurityContextHolder.context.authentication
if (auth) {
logoutHandlers.each { handler->
handler.logout(request,response,auth)
}
}
}
I used the following code to achieve my goal:
Authentication auth = SecurityContextHolder.context.authentication
new SecurityContextLogoutHandler().logout(request, response, auth);
new PersistentTokenBasedRememberMeServices().logout(request, response, auth);

How to access the URL that Acegi has stored for after the login form in Grails

I'm integrating Gigya with a web app running Acegi.
I have it working that the client side Gigya can authenticate an existing user and then skip the login form post and hit a controller method to inform the server securly that the user authentication has been performed by Gigya.
Using the following code in my controller I'm able to tell Acegi that the user has authenticated.
def user = com.playhardsports.football.web.admin.auth.User.find("from User where username=?", [UID])
def authorities = [new GrantedAuthorityImpl('ROLE_USER')] as GrantedAuthority[]
def userDetails = new org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserImpl(UID, fakePassword, true, true, true, true, authorities, user)
def authentication = new UsernamePasswordAuthenticationToken(userDetails, fakePassword, authorities)
SecurityContextHolder.context.authentication = authentication
The problem I'm having now is that I don't know where to redirect the user after the authentication.
A common scenario is that the user visits a protected page and Acegi redirects them to the login form. On my login form I also have the controls for Gigya to validate the user. Of course, meanwhile, the normal Acegi flow would be after login to redirect back to the original protected page.
So I'm looking for how to access that url, and if there was no url, because the person went straight to login, then how to find the default url that Acegi has configured.
Thanks.
You can access the SavedRequest from the session:
import org.springframework.security.ui.savedrequest.SavedRequest
import org.springframework.security.ui.AbstractProcessingFilter as APF
def savedRequest = session[APF.SPRING_SECURITY_SAVED_REQUEST_KEY]
String originalUrl = savedRequest?.fullRequestUrl ?: '/'

Resources