
This post is somewhat of a 2 part announcement:
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.
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.
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:
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:
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.
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:
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.
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:
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.
Pleasem can somebody paste how to convert this:
acts_as_authentic :login_field_validation_options => { :if => :openid_identifier_blank? }, :password_field_validation_options => { :if => :openid_identifier_blank? }
Thanks!
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.
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.
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?
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.
Hi,
my question may seems stupid but how do you convert this :
acts_as_authentic :login_field_validation_options => { :if => :openid_identifier_blank? }, :password_field_validation_options => { :if => :openid_identifier_blank? }
to Authlogic 2 ? I don’t see any kind of example with "if" statements anymore.
Thanks.
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.
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.
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.
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.
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.
@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 = {
:on => :update,
:if => :has_no_credentials?,
:minimum => 8
}
end
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?
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.
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!
Thanks Daniel, this has been fixed.
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?
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
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!
@karim, this is done with brute force protection.
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
Thanks melvin, didn’t know that. That did the trick though.