Translate

Thursday, July 12, 2018

How to Setup AuthLogic In Rails 4

This will go over, from start to finish, how to implement session handling using AuthLogic in Ruby On Rails 4.


Run the following in your terminal:

$ rails new login_app
$ cd login_app
$ vim Gemfile
/* Add line "gem 'authlogic'" somewhere in the gem file */
$ bundle install


This will create an application called login_app add the authlogic gem, and install the gem if it is not already installed.

Next we’ll create our user model, controllers, and model classes.

rails generate scaffold User username:string subdomain:string email:string crypted_password:string password_salt:string persistence_token:string authentication_token:string

$ rake db:migrate

Crypted_password persistence_token are both expected attributes from authlogic. Now we’ll need to setup our User Model to work as the authentication class.

Now that our Model is setup, lets work on the UI. Lets add a global register link so that anybody logged out can register easily. Open your /app/views/layouts/application.html.erb file to look like this:
If you haven’t started your server yet feel free to start it now.

$ rails s


As you can see we’re using the built in rails scaffolding. Since this is a basic application we’ll have the user overview list act as our main page. Lets clean it up a bit, it currently shows encrypted passwords, salts, and tokens. Open your /app/views/users/index.html.erb and edit it to look like this:
Now fire up your browser and check your nifty site. If you goto localhost:3000 you should see the default rails homepage, navigate to localhost:3000/users. It should now look something like this

There are currently not users listed because nobody has registered. If you open up the registration page you’ll see that it doesn’t look much like anything, lets add some quick formatting there as well. Open up app/views/users/_form.html.erb and change it to look like this:

The main changes here are rather simple. We changed the field name from :crypted_password to :password. Authlogic will map the :password field to :crypted_password after hashing it. We also changed the field type from f.text_field to f.password_field, this will create your standard password input field instead of a plain text input field. We have also added a :password_confirmation field. All of the logic to support these fields is built into authlogic. Try registering with an invalid e-mail address. You should see a page like this:

Authlogic adds in auto e-mail validation on email forms, as well as some other basic settings that you can change yourself.

Now lets create our first account. As you can see it has displayed our hashed passwords and some other data that no user really needs to be bothered with. Also the flash notice isn’t exactly user friendly. To fix these open up app/controllers/user_controllers.rb and edit the create function to make it look like this.
In rails 3 the :flash has been replaced with :notice. As you can see this syntax is a little clearer. We’ll change this message to say “Registration Successful”, a little more user friendly. Also we change the redirect to the users list page instead of the view user page. If you register another account you’ll see a much cleaner UI interaction and interface.

Where’s my session?

The Model

You may be saying, “That’s neat where does the session handling come in”. We’re going to create a separate controller and model to handle our session handling logic. Since the user model contains all the information about our tracked object, we can just create an empty model called user_session, run the following command

$ rails g model user_session

You can delete the migration that was generated, it is not needed and only creates an empty table. Now lets setup our user_session model, edit your app/models/user_session.rb to look like this:
In rails 2 all that was required was changing the inherited class to AuthLogic::Session::Base, but with rails 3 there are some errors in the form handler. AuthLogic users a function called to_key which is clearly not defined. The function we have created does some ruby magic, if this is a new record it returns nil, as there is no key otherwise it calls send, basically saying self.primary_key. There is none on this object and we could most likely return nil at all times here, but this is nice to have anyways. Rails will also want to know if this object is persisted, it is not so we’ll just return false.

The Controller

Well now that we have a way to track sessions, we do authlogic. Lets create a way to login and log out. We’ll create a user_session controller to specifically handle this, once again we’ll use ruby generate with some scaffolding.

$ rails g scaffold_controller user_session username:string password:string

This command creates a controller that expects its respective object to have two attributes: a password, and a username. As you can probably tell from now our UserSession class does not have either of these, but our User model has a username as well as a crypted_password that is mapped to password by authlogic. It also has already been setup to expect authlogic with the act_as_authentic function.
If you open up your app/controllers/user_sessions_controller.rb you’ll see it has tons of generated code in there, we’re going to trim this down to a much nicer and more manageable file, that should look like this:
The biggest changes here are in the destroy function. UserSession does not have a id, so one does not need to be passed in. Other than that, we just did some cosmetic changes, redirecting the create and destroy functions to to :users and changing their :flash text.

Logging In and Logging Out

Currently the login and logout functions are stored at user_session/create and user_session/destroy, not very pretty. Lets open up config/routes.rb and set up some cleaner urls. Your file should look like this:
We added :user_sessions to the resources, this is required for the login form submission. We then wrote to name match rules to change create routes for /login and /logout, this is a little more user friendly.
Now lets create the login link. We’ll want this link available everywhere, right next to our Register link preferably. Open up app/views/layouts/application.html.erb, and change the body to look like this
Since our route defines the login link as :login we can just refer to it as such, very easy and clean.
There are couple more quick UI changes, in app/views/user_sessions/new.html.erb change the h1 tag to say “Login”. In app/views/user_sessions/_form.html.erb change the password field to f.password_field just like we did in the register form.
Feel free to login now.

I Logged In But Nothing Happened?!?

It may seem that way, but we weren’t displaying the notice. Change app/views/users/index.html.erb to look like this:
Now it will display what ever is in the notice variable. Lets also add a logout link, this should only be visible when the user is logged in.
Change app/views/layouts/application.html.erb nav div to look like this:
current_user is a helper method that will return the current views user model or nil. If there is a current user, we’ll display an edit profile and a log out links, otherwise the reigster and login link. Now lets create that helper method, edit app/controllers/application_controller.rb so it looks like this:
current_user function is pretty much as we said earlier, it returns the current user object if viewer is logged in. It has global scope because of the helper_method :current user function call. current_user_session returns the current_session if the user is logged in.