«
»

Rails

Persistent Cookie Authentication Gem Documentation

07.07.08 | 4 Comments

cookie-monster

What are persistent cookies? What are persistent cookies used for?

A persistent cookie is no different from other cookies. What is different is that it is used to identify users. With identification, it enables a website to remember you on subsequent visits, speeding up or enhancing your experience of services or functions offered. For example, a website may offer its contents in different languages. On your first visit, you may choose to have the content delivered in French and the site may record that preference in a persistent cookie set on your browser. When you revisit that site it will use the cookie to ensure that the content is delivered in French.

Why do I need it?

The biggest advantage is we can skip the registration step. We use persistent cookies to identify users. Users can be anonymous first time visitors or registered users. When we’re able to identify them(especially anonymous users), we can keep data like what items the user has placed on her cart. For e-commerce sites, you may not want to force the first time anonymous users to register when they try to place items in the cart. Some may be turned off and go away. By using persistent cookies to identify them, we can save which items they want without making them go through the registration process. You can make them register when its time to make payment.

How do I use them?

To use persistent cookies effectively, we’re segregating the web site into 3 levels of access.

  • Public – anyone can go in. Examples would include your index page and FAQ
  • Protected – cookie authenticated.
  • Private – user must log in.

In your controllers, place a before_filter to identify which actions is private/protected

before_filter :cookie_required, :only => [:some_actions]
before_filter :login_required, :only => [:some_actions]

Use :cookie_required for protected actions, and :login_required for private areas.

How do I identify the users?

If you have seen through the code, there’re actually 3 models controlling the authentication system: identity, login_cookies and users.

  • Identity – the unique identifier used to identify users. All users only have one identity, be it anonymous or registered users.
  • Login_cookie – the cookies used for identifying the users.
  • User – for identifying registered users.

One unique identity can have many Cookies, but only one User. So when you want to link to the user, use the Identity model instead. For example, you want to create a relationship where a user has many books:

class Identity < ActiveRecord::Base
has_one :user
has_many :login_cookies
has_many :books
end

Whenever your controllers need to link to the user, do it through the identity instead.

@identity.user

What if the user’s browser did not enable cookies?

Good question. If that happens, we will treat the protected region as private automatically. There’s no need for you to handle it. The code is created to degrade gracefully.

Implementation of persistent cookie authentication

The implementation is as suggested by Barry Jaspan and Charles Miller. In fact, Drupal‘s Persistent Login Module follows this set of implementation.

Special cases

There’s a special case you need to take note. For example, an anonymous user comes to your site, and place a few items on the cart. And then she registers as a new user. Will the data in her shopping cart be lost? The gem will ensure that her cookie entry and her newly registered user entry will be transferred to the same identity. But as I do not know how your website will be implemented, I did not implement the merging of the data from her cart. You’ll need to add your code to transfer the data to her new identity. An example of the implementation is here. You’ll need to modify the merge_identity function from user_controller.rb From app/controllers/user_controller.rb

def mergeIdentity(anonymousCookieValue, knownIdentityID)
if anonymousCookieValue == nil || knownIdentityID == nil
return false
end
 
return false if !LoginCookie.isAnonymous(anonymousCookieValue)
loginValue = LoginCookie.getCookieLogin(anonymousCookieValue)
 
#getting the both anonymous user's identity and the known identity
anonymousCookie = LoginCookie.find(:first, :conditions => ["login = ?", loginValue])
anonymousIdentity = anonymousCookie.identity
knownIdentity = Identity.find(knownIdentityID)
return false if anonymousIdentity == nil || knownIdentity == nil
 
#transferring the cookies
anonymousIdentity.login_cookies.each { |cookie|
cookie.identity_id = knownIdentity.id
cookie.save
}
 
#transferring the cards
anonymousIdentity.cards.each { |card|
card.identity_id = knownIdentity.id
card.save
}
 
#finally send the identity to its grave
anonymousIdentity.destroy
 
return true
 
end

This is about all you will need to know to implement the persistent cookie authentication system effectively. Any bugs or unclear points, feel free to contact me.

4 Comments

have your say

Add your comment below, or trackback from your own site. Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

:

:


«
»