Pablo's blog

A bit of this, a bit of that and a lot about computers

Archive for the tag “authentication”

Getting the current user

I’m not using any authentication gem or plug in, I’m rolling my own. I’m actually using OpenID, so rolling my own is not hard: no passwords to encrypt, resend and send, no email address to verify. I think this is the future. But I’m also doing something that I call ghost users.

When you use one of my web apps you can start using most of it right away. At first you are a totally anonymous user but as soon as you do something that requires you to have an account on the database I create one for you. In the case of Sano, the moment you add a weight you’ll have an account.

At that moment your account is accessible thanks to the session of your browser. The moment you close the browser that account is no longer accessible. If you use the app and like it and decide to stick around, all you have to do is log in with your OpenID. For using the web app there’s no barrier of entry.

From the programming point of view this creates some challenges:

  • Maintenance of the users and related data. Over time the user database will have users that are no longer accessible with weights and other related data. That needs cleaning up. For the moment I’m going to ignore that problem because it has no impact on the system and it’s not likely to present a problem any time soon.
  • Getting a user object is no longer a query to the database. Any piece of code should be able to get a user object no matter what’s the status of the session. Sometimes the user object is only needed in memory and sometime it’s needed in the database. For example: if you create a new weight, I need a user object that’s been saved on the database; to list your weights, I need a user, I don’t care if it’s in the database or not (if it’s not, it’s not going to have any weights, which is where you start).
  • Merging users happens regularly. Look at this scenario: you go to the app, you log in, you enter your weight, you leave; you go back to the app, you don’t log in, you enter a new weight. Now you have one account with one weight and another session only account with another weight. You realize you need to log in and you do it. At that moment I have to merge the two users.

To make it as simple as possible I’ve created a method called user in my application controller that is also declared as a helper method so it’s available for all controllers and all views. This method is guaranteed to return a user, and if you call with options[:create]=true then it’s guaranteed to return a user that is also on the database. What is not guaranteed is that the user object represents a permanent account. It may be what I call a ghost user.

This is the method:

class ApplicationController < ActionController::Base
  helper_method :user
  helper_method :user!

  protected

  # Helper method to get the current user. It will always return a user but the
  # user may not be in the database. If options[:create] is true, then the user
  # will be in the database (although it may be a ghost user).
  def user(options = {:create => false})
    # If we already have a user object, return that.
    return @user if @user != nil

    # Try to find the user in the database if session[:user_id] is defined.
    @user = User.find(session[:user_id]) if session[:user_id] != nil
    return @user if @user != nil

    # Create a new user object.
    @user = User.new()
    if options[:create]
      # Save the user in the database and set the session user_id for latter.
      @user.save
      session[:user_id] = @user.id
    end
    return @user
  end

  # Helper method to get a user that for sure exists on the database.
  def user!
    return user(:create => true)
  end
end

The advantages of OpenID

forgot-passwordOpenID has many advantages. For the average user, the main one is not having to remember a thousand passwords. That’s obvious. But also consider not having to remember the username. Many web sites use the email address as username and that’s nice, but many don’t. And most people are not lucky enough to have a username that’s free everywhere. For my wife, remembering the username is sometimes as hard as remembering the password.

Not having to worry about poorly programmed web sites leaking your password because they stored it in plain text and they have phpMyAdmin open without any password is also a big plus, but not something the average user would see.

But for the developer, it has many, many advantages.

Not having to decide on what identifier to use for your users (users vs emails vs ids). Not having to implement a log in screen, which means not having to worry about SSL encryption which means not having to get a dedicated IP address, a certificate, configure the web server accordingly and ensure that the site switches to https when it must.

Not getting password for the user means you don’t have to store a password. You don’t have to figure out what is the appropriate encryption mechanism so that if your encrypted password leak, they are not readable. Not using plain text is not enough, as some encryption mechanisms are easily broken. Not having to worry about that is huge.

You don’t have to create a signup page, people just log in. You don’t have to validate the password by asking for it twice or validate its strength or any other stuff like that.

You don’t have to create a remember password page, which means one less place where you have to deal with sending emails. That’s always good. Also it means that you don’t need to store the email of the user. You may want to, but that’s your option.

I’ve always been a fan of canned authentication and authorization systems. I’ve been using them since the days of PHP 4.0 and I used them in Django and ASP.NET (MVC). But with OpenID, it seems the authentication became almost trivial. Canned solutions were always troublesome because they had to work for everybody so they implemented a lot of stuff you don’t actually need and sometimes you spend more time fighting the bureaucracy of the system than producing something.

Is it possible that without OpenID authentication and identity for the developer of a web site becomes something simple and trivial? Where rolling your own solution not only is simple enough, but also the way to go. I’m looking forward to my users being just in the user table, and not all over the place in users, profile, membership, etc. I’m giving the roll-your-own-with-OpenID a try. I hope to post positively about it soon.

Post Navigation

Follow

Get every new post delivered to your Inbox.

Join 332 other followers