Skip to content

Instantly share code, notes, and snippets.

@smola
Created February 6, 2013 16:01
Show Gist options
  • Save smola/4723534 to your computer and use it in GitHub Desktop.
Save smola/4723534 to your computer and use it in GitHub Desktop.
public class MyUsernamePasswordAuthProvider
extends /* ........ */ {
/* ... MORE ... */
/**
* XXX: Ugly hack for Remember Me feature.
*/
public static Result handleLogin(final Context ctx, final boolean rememberMe) {
final Result result = UsernamePasswordAuthProvider.handleLogin(ctx);
if (rememberMe) {
//XXX: Is this secure? (SECURITY)
// We are logged in, remember.
RememberMe.remember(ctx);
}
return result;
}
/* ... MORE ... */
}
package providers;
import java.util.List;
import java.util.UUID;
import models.TokenAction;
import models.User;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.mvc.Http.Context;
import play.mvc.Http.Cookie;
import play.mvc.Http.Cookies;
import com.feth.play.module.pa.PlayAuthenticate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
public class RememberMe {
private static final Logger log = LoggerFactory.getLogger(RememberMe.class);
private static int getTimeout() {
return 30;
}
private static String getCookieName() {
return "REMEMBERME";
}
public static TokenAction getTokenAction(final Context ctx) {
final Cookies cookies = ctx.request().cookies();
final Cookie cookie = cookies.get(getCookieName());
if (cookie == null) {
return null;
}
final List<String> fields = ImmutableList.copyOf(Splitter.on('|').split(cookie.value()));
if (fields.size() != 2) {
log.warn("Discarding marlformed cookie: " + cookie.value());
ctx.response().discardCookies(getCookieName());
return null;
}
Long userId = null;
try {
userId = Long.valueOf(fields.get(0));
} catch (NumberFormatException ex) {
log.warn("Discarding marlformed cookie: " + cookie.value());
ctx.response().discardCookies(getCookieName());
return null;
}
final User user = User.find.byId(userId);
if (user == null || !user.active) {
log.warn("Discarding cookie for invalid user: " + cookie.value());
ctx.response().discardCookies(getCookieName());
return null;
}
final String randKey = fields.get(1);
final TokenAction tokenAction = TokenAction.find
.fetch("targetUser").where()
.eq("target_user_id", userId)
.eq("type", TokenAction.Type.REMEMBER_ME)
.eq("token", randKey)
.findUnique();
if (tokenAction == null) {
log.debug("Discarding cookie inexistent tokenAction: " + cookie.value());
ctx.response().discardCookies(getCookieName());
return null;
}
if (tokenAction.targetUser == null) {
log.debug("Discarding cookie inexistent tokenAction.targetUser: " + cookie.value());
tokenAction.delete();
ctx.response().discardCookies(getCookieName());
return null;
}
if (new DateTime().isAfter(new DateTime(tokenAction.expires))) {
tokenAction.delete();
return null;
}
return tokenAction;
}
public static boolean authenticate(final Context ctx) {
final TokenAction tokenAction = getTokenAction(ctx);
if (tokenAction == null) {
return false;
}
PlayAuthenticate.storeUser(ctx.session(), new MyLoginUsernamePasswordAuthUser(tokenAction.targetUser.email));
return true;
}
public static void remember(final Context ctx) {
remember(ctx, User.getLocalUser(ctx.session()));
}
public static void remember(final Context ctx, final User user) {
if (user == null) {
return;
}
final String token = UUID.randomUUID().toString();
final TokenAction tokenAction = TokenAction.create(
TokenAction.Type.REMEMBER_ME,
token,
user);
tokenAction.expires = new DateTime().plus(Duration.standardDays(getTimeout())).toDate();
tokenAction.save();
ctx.response().setCookie(
getCookieName(),
user.id + "|" + token,
getTimeout()*24*60*60, // MaxAge in seconds
"/", // Path
null,
false,
true);
for (final Cookie cookie : ctx.response().cookies()) {
log.error("FOO - " + cookie.toString());
}
}
public static void forget(final Context ctx) {
final TokenAction tokenAction = getTokenAction(ctx);
if (tokenAction != null) {
ctx.response().discardCookies(getCookieName());
tokenAction.delete();
}
}
}
package controllers;
import com.feth.play.module.pa.PlayAuthenticate;
import play.mvc.Action.Simple;
import play.mvc.Http.Context;
import play.mvc.Result;
import providers.RememberMe;
public class RememberMeAction extends Simple {
@Override
public Result call(Context ctx) throws Throwable {
if (!PlayAuthenticate.isLoggedIn(ctx.session())) {
RememberMe.authenticate(ctx);
}
return delegate.call(ctx);
}
}
@smola
Copy link
Author

smola commented Feb 14, 2013

This implementation is currently semi-broken since there is a conflict between the Set-Cookie for PLAY_SESSION and REMEMBER_ME. As it is, it does not work with recent Netty versions (AFAIK).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment