views:

67

answers:

1

Hi,

I'm trying to add a "remember me" feature to my web app to let a user stay logged in between browser restarts. I think I got the bulk of it. I'm using google app engine for the backend which lets me use java servlets. Here is some pseudo-code to demo:

public class MyServlet {
    public void handleRequest() {
        if (getThreadLocalRequest().getSession().getAttribute("user") != null) {
            // User already has session running for them.
        }
        else {
            // No session, but check if they chose 'remember me' during 
            // their initial login, if so we can have them 'auto log in' 
            // now.
            Cookie[] cookies = getThreadLocalRequest().getCookies();
            if (cookies.find("rememberMePlz").exists()) {
                // The value of this cookie is the cookie id, which is a 
                // unique string that is in no way based upon the user's 
                // name/email/id, and is hard to randomly generate.
                String cookieid = cookies.find("rememberMePlz").value();

                // Get the user object associated with this cookie id from 
                // the data store, would probably be a two-step process like:
                //
                // select * from cookies where cookieid = 'cookieid';
                // select * from users where userid = 'userid fetched from above select';
                User user = DataStore.getUserByCookieId(cookieid);
                if (user != null) {
                    // Start session for them.
                    getThreadLocalRequest().getSession()
                        .setAttribute("user", user);
                }
                else {
                    // Either couldn't find a matching cookie with the 
                    // supplied id, or maybe we expired the cookie on 
                    // our side or blocked it.
                }
            }
        }
    }
}

// On first login, if user wanted us to remember them, we'd generate 
// an instance of this object for them in the data store. We send the 
// cookieid value down to the client and they persist it on their side 
// in the "rememberMePlz" cookie.
public class CookieLong {
    private String mCookieId;
    private String mUserId; 
    private long mExpirationDate;
}

Alright, this all makes sense. The only frightening thing is what happens if someone finds out the value of the cookie? A malicious individual could set that cookie in their browser and access my site, and essentially be logged in as the user associated with it!

On the same note, I guess this is why the cookie ids must be difficult to randomly generate, because a malicious user doesn't have to steal someone's cookie - they could just randomly assign cookie values and start logging in as whichever user happens to be associated with that cookie, if any, right?

Scary stuff, I feel like I should at least include the username in the client cookie such that when it presents itself to the server, I won't auto-login unless the username+cookieid match in the DataStore.

Any comments would be great, I'm new to this and trying to figure out a best practice. I'm not writing a site which contains any sensitive personal information, but I'd like to minimize any potential for abuse all the same,

Thanks

A: 

The only frightening thing is what happens if someone finds out the value of the cookie? A malicious individual could set that cookie in their browser and access my site, and essentially be logged in as the user associated with it!

That's correct. This also applies to all "standard" session cookies such as jsessionid in JSP/Servlet webapps and PHPSESSID in PHP webapps and so on. They however have such a short lifetime that it doesn't harm. For long-living cookies, just ensure that the cookie value is unique (use DB's PK/UK for it), long (go up to 255 chars), hard-to-guess (no patterns, no MD5 hashes) and can contain all printable ASCII characters (in 0x20-0x7E range).

You also see often an option "Remember me on this IP address only" so that it's basically locked to an unique IP address. You can obtain it by HttpServletRequest#getRemoteAddr().

BalusC
All sounds good, just what is "DB's PK/UK"? Is this a utility library or something to generate the quality random cookie ids?
PK = Primary Key (which is implicitly unique), UK = Unique Key. The DB will error when you attempt to insert a duplicate. Make use of it :)
BalusC