Authlogic 2.0 with some OpenID goodness

Signing mouse pads

This post is somewhat of a 2 part announcement:

  1. The release of Authlogic 2.0
  2. The release of Authlogic OpenId 1.0 with a live example

I apologize for this post being a little delayed, this week was unusually busy for me and I wanted to wait until I had time to write an article giving these 2 things their due diligence. So let’s get right to it.

Authlogic 2.0

I won’t bore you with ALL of the changes I made to v2.0, almost all of them are internal and a result of me being OCD, so I’ll try to fill you in quickly. The only change you might have to make when migrating is how acts_as_authentic accepts configuration. Instead of accept a hash, it now accepts a block. Ex:

acts_as_authentic do |c|
  c.my_value = my_option
end

If you want a more detailed list of changes you can check out the github commit history or the CHANGELOG.

That being said, I basically rewrote the entire library. I literally created a new folder for Authlogic 2.0 and went from there; pulled over any reusable code, etc. Why would I do this? Because the focus of v2.0 was around the public API. So much that I rewrote the library to use its own API. If you are curious, take a look at the Authlogic::Session and Authlogic::ActsAsAuthentic submodules. Any of those files could be easily pulled out into their library and be plugged into Authlogic. So if you are wanting some examples of how to extend Authlogic just glance at those sub modules. If you are super geek, I would love to hear your thoughts on the internal design of Authlogic. I feel very good about it and if you can punch some holes in the design I would be pretty impressed, more importantly I think its a good opportunity for both of us to learn something.

OpenID so easy you might think its from New Jersey

Now here is why Authlogic 2.0 is great. Because of 2.0 I was able to write a really nice OpenID “add on” for Authlogic. Check it out on github or see the live example. I’m not going to go into the set up and installation, because its all in the docs. Instead I’ll tell you the basic design behind it and how it works.

To really authenticate with OpenID you need to do 2 things:

  1. Verify their OpenID when the user registering or updating their profile.
  2. Verify their OpenID when they are logging in.

As you probably saw in my older OpenID tutorial, one of the downfalls what that it didn’t accomplish #1. It just authenticated when the user tried to log in. With Authlogic 2.0 this is no longer the case. I feel like it’s a very solid OpenID solution.

The best part is that its dead simple, it really doesn’t get any easier than this. Just to prove my point, here is the basic setup process:

  1. Add a field to your database to store the user’s openid_identifier
  2. Install the authlogic-oid gem
  3. Install and setup the openid_authentication plugin by the rails team.
  4. Save your Authlogic::Session::Base and ActiveRecord::Base objects with a block whenever you want to verify their OpenID.

So instead of this:

if @user_session.save
  redirect_back_or_default account_url
else
  render :action => :new
end

Do this:

@user_session.save do |result|
  if result
    redirect_back_or_default account_url
  else
    render :action => :new
  end
end

Why? Because the AuthlogicOpenid add on takes care of redirecting the user to their OpenID provider. When it redirects it needs to skip that entire block of code to avoid a DoubleRender error.

The Authlogic challenge

Now there there is an established and well defined public API I encourage you to write your own add ons. There are 3 that I am going to need in the near future, and I feel would be extremely beneficial to other authlogic users:

  1. AuthlogicImap – authentication via IMAP. Meaning users could provide an email address and password and Authlogic would try to authenticate with their IMAP server. This is a GREAT solution for intranet authentication. In fact, I plan to implement this in my company as soon as I can. This way they will have one password for everything: email, intranet apps, etc.
  2. AuthlogicFacebook – I don’t think this requires a lot of explanation, but the goal of this would be to authenticate with Facebook’s authentication solution: Facebook Connect. I really think if a single sign on solution becomes popular, this is the one, because of the sheer volume of users on Facebook it’s impossible to ignore.
  3. AuthlogicLdap – Allow users to authenticate via LDAP.

So if you are wanting to write an add on for Authlogic, I encourage you to do one of the above, because I feel those would be the most widely used. But if you want to write something else, go for it.

What do you get?

To get this moving along, I am offering incentives. I know it kind of goes against the basic principles of open source, but what the hell, I figured I would try to spice it up a little bit.

If you write an Authlogic add-on that is approved by me I will personally sign a mouse pad and send it right to your house, or work if you want to show it off to your colleagues. Even better, have it “accidentally” sent to your girlfriend’s house and guarantee yourself some action that night.

Alright, enough of that, here is what you really get:

  1. Officially announce it on my blog and link to it wherever relevant (Authlogic docs, wiki, etc.).
  2. Authlogic commit rights, if you want them.
  3. Employee discount at neco.com (one of my companies).
  4. $25 itunes gift card. (only if you write one of the above 3)

I know #3 is kind of lame, but hey, if you like going to events I can get you tickets to just about anything at a steal.

So that’s my speech, let me know what you think.

  • Share/Save/Bookmark


22 Responses to “Authlogic 2.0 with some OpenID goodness”

  1. John says:

    Pleasem can somebody paste how to convert this:

    acts_as_authentic :login_field_validation_options => { :if => :o penid_identifier_blank? }, :password_field_validation_options => { :if => :o penid_identifier_blank? }

    Thanks!

  2. Simon Harris says:

    OAuth plugin would be cool too. Looks like I’ll need to update. Is there a quick "moving from 1 to 2.0" somewhere? I noticed things such as configuration have changed.

  3. Ben Johnson says:

    Nothing else has changed from the public aspect, except the configuration for acts_as_authentic. It now accepts a block instead of a hash: acts_as_authentic { |c| c.my_option = my_value }. The hash was getting really messy in my opinion, and it was a lot less flexible.

  4. bes island says:

    As for OpenID: I think it is wrong each OpenID being a separate user. OpenID is not user entity, but authentification method (as well as login & password pair, LDAP etc.). A user is somebody who uses the site, and they can have plenty of authentification methods: login & password, several OpenIDs and so on. Whatever method and, in particular, whatever OpenID they use to log in, they must be treated as the same user. Must they not?

  5. Ben Johnson says:

    Hi Bes,

    You are right and that is really application specific. Authlogic will not get in your way if this is what you want to do. Setting up authlogic to use a relationship to get credentials takes one line of configuration.

  6. Hi,
    my question may seems stupid but how do you convert this :

    acts_as_authentic :login_field_validation_options => { :if => :o penid_identifier_blank? }, :password_field_validation_options => { :if => :o penid_identifier_blank? }

    to Authlogic 2 ? I don’t see any kind of example with "if" statements anymore.

    Thanks.

  7. To follow-up on the comment above. How hard would it be to support shared authentication? If 5 user accounts shared an authentication? For example I have 2 github accounts for different companies, but it is a hassle having to log out and back in to see assets from different accounts. I would like to authenticate once for all accounts.

  8. Ben Johnson says:

    Nicolas, the first paragraph under the authlogic 2.0 section covers this.

    Michael, that is an application specific issue. To do that is very easy, check out the find_by_login_method configuration.

  9. Loren says:

    What a coincidence, I just started working through the tutorial this morning and wondered why
    acts_as_authentic :crypto_provider => Authlogic::CryptoProviders::BCrypt
    was choking. Don’t forget to update your excellent tutorials. It will give us all something to read while we wait for EngineYard to regain consciousness.

    I appreciate the thought you have put into *logic. Good stuff.

  10. Hunter Nield says:

    Sounds like it is time to dust off my RPX code for Authlogic 1 and make an AuthlogicRpx addon. It could actually reduce the need for the FB or OpenID addons since it provides those along with Google, Yahoo, MySpace, etc.

    I saw the landing of the initial Authlogic 2 work and thought immediately of writing of a plugin with the public API. Now… I just need to find the time.

  11. Ben,

    > Nicolas, the first paragraph under the authlogic 2.0 section covers this.

    actually, no, it doesn’t. And if it does, it’s not clear enough. For example, I have no idea on how to access `User#openid_identifier_blank?` or the value of the `login` or `openid_identifier` from inside the block. Another pointer would be most welcome.

    Thanks for Authlogic, appreciate your work. :)
    C.

  12. grimen says:

    @Carlo & Nicolas

    Examle I use (too lazy to apply on your case, but same principle – this took me 5 min to figure out from RDoc, look it up!):

    acts_as_authentic do |options|
    options.login_field = :email
    options.validates_length_of_password_confirmation_field_options = {
    :o n => :update,
    :if => :has_no_credentials?,
    :minimum => 8
    }
    end

  13. Ben Johnson says:

    Carlo, you access those just like you would anywhere else in your application. Call them off of your object. Also openid_identifier_blank? is a private method used internalls. You can accomplish the same thing by doing openid_identifier.blank?

  14. Ben Johnson says:

    Also Nicholas, the authlogic_openid addon takes care of all this for you, you don’t even need to do that anymore. Just install the plugin, remove that entire line and you are good to go. You can also check out the "with-openid" branch in the authlogic_example on github.

  15. Daniel says:

    When verifying an OpenID during account creation, or when updating an account with a new OpenID, the identifier returned by the OpenID server should replace the identifier entered by the user.

    For example, Yahoo! tells its users to simply enter http://yahoo.com. This is obviously not the real OpenID identifier. The real one is returned by Yahoo! upon successful authentication.

    Thanks for your good work on AuthLogic!

  16. Ben Johnson says:

    Thanks Daniel, this has been fixed.

  17. David Park says:

    Hi Ben,

    Thanks a lot for the great gem/plugin. I need to add access control to my app as well. Is there an access control plugin/gem that you’d recommend?

  18. David says:

    Hi Ben,
    thanks for great plugin.

    I have one question – I usually set-up attr_accessible in my models. When I modify new_user form (as malicious user can), I can assign any value (I tried login_count). So I’ve set attr accessible (login and email) and I get errors about mass-assigning protected attributes on password and password_confirmation. I ended with login, email, password and password_confirmation as a attr_accessible. It it ok? (assuming that there are no other columns than you have specified in the tutorials).

    Sorry if I have missed something clear.

    Thanks,
    David

  19. Karim says:

    Hi Ben,

    Thanks for providing us with a clean and extremely well designed lib. We’ve actually switched over half of our app from Restful Auth to this because we needed to provide 2 separate logins (users and employees). Now there is something I might need your help with. We need to provide a facility where a user account is disabled if he fails to properly enter his account 3 times in a row…. How could that be done with authlogic? Can you provide something like that built-in in the lib?

    Thanks!

  20. benjohnson says:

    @karim, this is done with brute force protection.

  21. Melvin Ram says:

    Hey Ben, I’m looking forward to using Authlogic and this OpenID extension. Thanks for making that.

    Anywho, I noticed that the numbers in your list at the top is running into the picture. I had that a similar problem and I found a simple fix for it: http://railsnotes.com/88-ul-css-trick/

    ~ mel

  22. benjohnson says:

    Thanks melvin, didn’t know that. That did the trick though.