login automatically with Grails & Acegi - security

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

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.

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 :).

This is Burt Beckwith's answer (not mine)
(It was left as a comment by Burt, but I think it deserves to be more prominent)
If you don't have the password, 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)

Related

Password type field in gmail card service

Right now, in gmail appscript we don't have any option to add a password type field.
Gmail Card Service for add-on has a very good ability to show any thing in it. We can integrate with any app which has basic REST api. We need authentication for that which commonly need password type field.
Any work around to show password type field?
As of now, there is no support for password field in Gmail add-on.
But we can build a hack for it. I hope password is needed only in registration forms. So, we can build a registration form using HTML and that can be served through authorization action.
CardService.newAuthorizationAction().setAuthorizationUrl(loginUrl)
Here, host registration HTML in a web server and pass this URL as "loginUrl" in the above snippet. We have to supply AuthorizationAction for the signup/register button. So, when the user clicks on this button, a new popup page is launched, the user will give the username, password, etc... onsubmit, we can encode all the form data and pass it to the parent Gmail add-on by redirecting it to a script redirection URL which you can generate an add-on. Once the redirection to the script URL comes, there will be a callback in our add-on code from there you can get the form fields which were encoded from registration HTML page.
function generateNewStateToken(callbackName, payload) {
return ScriptApp.newStateToken()
.withMethod(callbackName)
.withArgument("payload", JSON.stringify(payload))
.withTimeout(3600)
.createToken();
}
function getRedirectURI() {
return "https://script.google.com/macros/d/" + ScriptApp.getScriptId() + "/usercallback";
}
var state = generateNewStateToken("registerCallback", {"signup": true});
var reg_url = <reg_url> + "?redirect_uri=" + getRedirectURI() + "&state=" + state;
function registerCallback(cbResp) {
// to access payload which passed in state token: cbResp.parameter.payload;
// in the html serialize all the form fields or data which you want to pass to plugin as query params like: <redirect_uri>?form_data=<encoded_data>&state=<state>
//Note: here the registration HTML page should parse the URL to get the state & redirect_uri from URL.
// to access form_data: cbResp.parameter.form_data
}
I hope this will help you. This is how we are doing the signup/signin flow now.
Looks like you are authorizing a non google service . Please refer to Authorizing custom google services .

Logout on ServiceStack v4

I have ServiceStack v4 service but when I call the auth/logout route (using either POST or GET) to logout the currently logged-in user, I get an error:
400 Not Empty
User Name cannot be empty
Password Cannot be empty
As I wouldn't expect users to enter credentials when logging out, I am surely missing something?
I have the AuthFeature registered during host initialisation, and I am using CredentialsAuthProvider. I have taken the code from Github so I can see how it works.
My Client Code:
var rest = Restangular.one('auth/logout').get();
//var result = rest.post({userName: userName});
this.requestTracker.addPromise(rest);
return rest;
After a lot of digging, this happens when you are using CredentialsAuthProvider. Within this class, a validator is defined that validates all instances of the Authenticate request. As the logout route uses the Authenticate request, this validator is fired.
I got round it by modifying the validator to:
RuleFor(x => x.UserName).NotEmpty().When(d => d.provider != "logout");
RuleFor(x => x.Password).NotEmpty().When(d => d.provider != "logout");
This is probably not the most elegant way of fixing long term, but got me up and running.
I know this question is old, but I recently have been struggling with the same thing. What occurs is that before the Authenticate.Post function is called, the validation cache is checked and the CredentialsAuthProvider which has the mentioned validator fails unless username and password are not empty.
Now, i'm not sure if it makes a difference if you only have that provider enabled or not - I've not tested. I actually have my own custom provider that subclasses CredentialsAuthProvider and it's the only one I register.
The only way currently is to either pass a non-empty (but useless) password and username, or modify your own custom provider, overriding the Authenticate function and using a modified version of the validator as mentioned above.

How do I create an authenticated session in ServiceStack?

I have a situation where I'm using Credentials auth successfully, but I sometimes need to be able to simply create an authenticated session from inside a service using nothing but the user's email address. How can I do that? I suppose I'm looking for something similar in intent to FormsAuthentication.SetAuthCookie(), but I haven't found it.
Here's my thinking so far. Assuming I have to construct this myself, I see this inside CredentialsAuthProvider.TryAuthenticate:
if (authRepo.TryAuthenticate(userName, password, out userAuth))
{
session.PopulateWith(userAuth);
session.IsAuthenticated = true;
session.UserAuthId = userAuth.Id.ToString(CultureInfo.InvariantCulture);
session.ProviderOAuthAccess = authRepo.GetUserOAuthProviders(session.UserAuthId)
.ConvertAll(x => (IOAuthTokens)x);
return true;
}
That seems to imply that I can do what's inside the block myself via a UserAuth object from IUserAuthRepository.GetUserAuthByUserName(). I don't think this is enough though, since the session isn't saved here. Working backwards, I found that TryAuthenticate is called by Authenticate which then goes on to call OnAuthenticated where other things happen including saving the session. Can I resolve an instance of CredentialsAuthProvider and call OnAuthenticated myself?
Am I on the right track, or is this the completely wrong way of going about this?
sometimes need to be able to simply create an authenticated session from inside a service using nothing but the user's email address. How can I do that? I suppose I'm looking for something similar in intent to FormsAuthentication.SetAuthCookie()
I think the simplest, most FormsAuthentication.SetAuthCookie() way I can think of is to modify the AuthUserSession within in your service. The code below will get the Session, set IsAuthenticated to true, set the email and save the Session.
public class SomeService : Service
{
public String Any(SomeRequest request)
{
//not sure you need it, but you could put some code here to verify the email is allowed to authenticate
//and if true run the code below
var sess = this.SessionAs<AuthUserSession>();
sess.IsAuthenticated = true;
sess.Email = "test#email.com";
this.SaveSession(sess);
return "success";
}
}

Grails - Spring Security Account Creation

I am using the Spring Security Core plugin and can successfully log users in and out of my application. However, when the user successfully signs up, I don't understand how to set that user's security context on the signup postback so that they can be redirected to a secure page without having to log in again. Any help is welcome. Thanks.
The other link you reference is 2 years old. Since then I've added a reauthenticate method to SpringSecurityService. See section "6.2 SpringSecurityService" in the docs:
http://grails-plugins.github.com/grails-spring-security-core/docs/
I eventually came upon this link, which does the trick: https://stackoverflow.com/a/7112838/469106
Here are the contents of that link:
If you don't have the password, 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)

How to Prevent CSRF in Play [2.0] Using Scala?

A lot of web frameworks have a standard setup for generating forms with auth tokens.
Do I have to create such measures manually, or does Play come with a build in means of prevening CSRF?
The documentation on the Play website doesn't seem to address this.
I use the play2-authenticitytoken module:
The authenticity token is a way around one of the most serious internet security threats: CRSF attacks. It ensures that the client submitting a form is the one who received the page (and not a hacker who stole your session data).
How it works:
In a nutshell:
on every form post, we add a hidden parameter containing a uuid
the uuid is signed and its signature is stored in the session (which translated into a cookie)
When the user submits the form, we get: the uuid, the signature and the other form inputs.
We sign the incoming uuid again
Validation passes if the signatures match (session.sign=uuid.sign)
Should an attacker inject a different id, he will never figure how to generate the correct signature.
For completeness sake, I have an example here in Scala for Play 2.0
https://github.com/jacobgroundwater/Scala-Play-CSRF
This method also uses the cookie + hidden-field approach.
Example Usage
Use the SessionKey action to help sign a form:
object Application extends Controller {
def login = SessionKey{ (key,signature) =>
Action { implicit request =>
Ok( views.html.login(signature) ).withSession( key->signature )
}
}
}
When parsing forms use the following to check for the signature:
object Authenticator extends Controller {
def login = ValidateForm{
Action { implicit request =>
Ok( views.html.index("You're Loggd In") )
}
}
}
Since Play 2.1 there's support for this in the framework. Nick Carroll wrote a nice little article on how to use it:
http://nickcarroll.me/2013/02/11/protect-your-play-application-with-the-csrf-filter/

Resources