Search code examples
securitysession-cookiesgoogle-fusion-tables

Cookie Security


I had a quick question about cookie security that I wanted to run by the stackoverflow community before I got too far into implementing it. This will be my first time implementing user sign-in on a site and I wanted to be extremely cautious about security so-as not to have to worry about accounts being compromised down the line.

Here's my hypothetical security solution:

  • User signs up for site (through either email registration, login with Facebook, etc.) and is assigned a User ID number. This number is public and can be used to access the profile of the user, refer to them in posts, and so on.
  • At registration, the user is also assigned a randomly generated ROWID as their information is stored in a database (hosted on Google Fusion Tables). This ROWID number is kept hidden from the user and is never revealed.
  • The User ID is encrypted against the ROWID number and this number is stored in a cookie on the user's computer. It isn't ever visible to other users and, in theory, this could only be viewed by the user.

This solution would allow for a "secret" key (the ROWID number), a "consumer" key (saved in the cookie), and a public reference ID (the User ID). All of these are, of course, rolled up into a database where the site can quickly access them. Does this sound like a plan that would provide the proper level of security or is there something else that I should consider?


Solution

  • For additional protection against cookie theft through something like XSS, you might want to consider issuing unique cookies per IP address, and then making sure that the cookies are only useable from that IP address. If you're storing your cookies in the database, things can get complicated, as you now have multiple cookies mapping to the same user.

    Here's how to avoid those problems:

    Set-Cookie: userName=Alice; authCode=eeba95a4...
    

    Where: authCode=HMAC(ROWID, userName + ipAddr)

    When you receive this cookie, look up the user in the database, recompute/verify the authCode in the cookie, using ROWID and ip address of the request. No need to store cookies in the database.

    For extra crypto points, throw a salt parameter into the mix:

    Set-Cookie: userName=Alice; salt=59843...; authCode=eeba9...
    

    Where: authCode=HMAC(ROWID, userName + ipAddr + salt)

    Salt value is generated randomly for every cookie you produce. There's no need to keep it a secret.