play-authenticate
play-authenticate copied to clipboard
Customize where users are redirected to with each provider
In my Play! Authenticate, I need to redirect users who login with Facebook (or other social network) for the first time to be redirected to a custom URL. That way, I can get users to import their friends on their first Facebook login (i.e. account creation).
Is that possible currently? Maybe it would have to be a new setting or group of settings for each provider?
You might be able to do that by using a temporary variable in the session, but it definitely isn't the best solution. I actually understand and agree with the use case, so we should look into it on how to implement this. Off the top of my head I could think of defining a method in the Router class that gets called before jumping back to the initial URL for example. If you have already implemented something like that in your application that you can refactor and provide as a pull request (preferably as a non-breaking change, that should be possible) I would be more than happy to look into merging that.
Ok. Thank you. At the moment I juse use a custom auth action with an alternative to PlayAuthenticate.handleAuthentication
. My approach is storing in context.args
the action that is being performed (login, signup, link, merge) and my loginAndRedirect
goes like this:
private static Result loginAndRedirect(final Context context, final AuthUser loginUser) {
storeUser(context.session(), loginUser);
final String action = (String)context.args.get("pa-action");
if (action != null && action.equals("link")) {
final String provider = loginUser.getProvider();
if (provider.equals("facebook")) {
return Controller.redirect("/facebook/import");
}
}
return Controller.redirect(getJumpUrl(context));
So, do you think that providing a hook in Resolver
for use in loginAndRedirect
is the way to go? I think it could look like this:
private static Result loginAndRedirect(final Context context, final AuthUser loginUser) {
storeUser(context.session(), loginUser);
final String redirectUrl = getResolver().getRedirect(
(String)context.args.get("pa-action"),
loginUser.getProvider()
);
if (redirectUrl != null) {
return Controller.redirect(redirectUrl);
}
return Controller.redirect(getJumpUrl(context));
Or maybe the hook should be for getJumlUrl
. I can't make my mind with a good API for this...
Ideally there would be method in the Router
that gets both the provider name as a String
and the return value of getJumpUrl
(from within loginAndRedirect) and returns a Call
- by default it would always return the value from getJumpUrl()
(to stay backwards compatible) but in your case you could basically override it and return a Call
object pointing virtually anywhere - how does that sound?
At the moment I just reworked my code so I can just redirect to Facebook auth and use PlayAuthenticate.storeOriginalUrl
to go back to the page I want. This works for me at the moment (no explicit Facebook login for the user, I just log in the user into Facebook as needed for certain capabilities such as importing friends). I'm not sure if I'll implement explicit Facebook login in my app any time soon, so I do not need this cutomization at the moment.
I've come across this again when implementing a welcome page where users are redirected on their first login. At the moment I'm using a new PlayAuthenticate.storeUrl
, but let's see what are the different possibilies:
Store redirect URL in session
My current approach:
In PlayAuthenticate.java
:
public static void storeRedirectUrl(final Http.Context context, final String url) {
context.session.put(ORIGINAL_URL, url);
}
Then I call it when needed. For example, if I want to redirect any new user to this page, I modify my MyUserServicePlugin.java
with this:
@Override
public Object save(final AuthUser authUser) {
final boolean isLinked = User.existsByAuthUserIdentity(authUser);
if (!isLinked) {
// Redirect to the Welcome page
PlayAuthenticate.storeUrl(Context.current(), "/welcome");
return User.create(authUser).id;
} else {
// we have this user already, so return null
return null;
}
}
I could also put this in MyUsernamePasswordAuthProvider.java
if I wanted to do a specific redirect for this provider with finer-grained control.
Or I could add a custom action for /authenticate/facebook
route to do this in a specific way of Facebook.
This API might not be very beautiful, although it seems very versatile for the use cases I considered.
Add a method to the Resolver API
Something like you described:
public abstract Call redirectAfterLogin();
For this to work flexibly enough, it should be possible to have enough information to do the decision here. For example, which provider are we using and if this is a signup, link, merge o login.
Do everything behind the scenes and conf-driven
Eventually, I guess it could be possible to just make PlayAuthenticate.java
and all core providers support enough setting options to support all these use cases just setting some keys in the conf. Maybe this would be more sensible once more people have spoken up about their use cases?
What do you think? Whatever you think is better API-wise, I'm up for implementing it.
This is quite similar to issue #63
@smola I agree with the usecase - this is actually something more users want - not only for signup but also on an error case (like a user exists already). How about a resolver driven solution with conf fallbacks like for the other pages. As long as it will work for all providers and is versatile enough this should be the easiest solution, as the resolver is there already and could come with a default (that can be overwritten by a subclass) out of the box. What do you think?
That works for me. So that resolver method would need easy access to:
- Current action (signup/login/link/merge)
- Redirect reason (success/error/...). I don't need this in my use case, but it might be needed for issue #63?
-
AuthUser
Would those be arguments for the resolver method or should they be fetched with Context.current().session()
, PlayAuthenticate.getUser()
, etc?
I would really love to see the resolver driven solution. I try to login with an ajax request and just want to write out the new user as json after successfully signup and currently I have to redirect the user. With the resolver driven solution I could just print out the json file and go :)
Since its 19 days ago since something happend here is there any kind of eta?
@ssachtleben as this is an Open Source project, there's no fix release cycle or anything. Unfortunately I am quite busy these days, so I won't be able to implement this, but I am happy to look at any pull request
+1