Index of All Lessons

View Screencast (Quicktime)

Right-click on the button above and choose Save As to save file to your computer


Support the Course

There’s no charge for the course, but we greatly appreciate any donations.

Suggested donations:

  • One or two lessons: $5
  • Several lessons $10
  • Entire course: $25 – $50

We hope you’ve found the course to be valuable, and we appreciate any support you care to provide.


Sign Up Now!

If you aren’t already receiving our course lessons via email, sign up now to be sure you don’t miss anything.

Every few days, we’ll send you an email with a link to the next episode, plus a list of additional resources for advancing your knowledge.

There’s no cost and no obligation. And we’ll never share your email address with any third party.


We’ll send you the first lesson right away.


Want to help spread the word? We’d be grateful if you would include a link to the course in your blog, web site, or emails.

Looking for a Powerful Hosted CMS?

The authors of the Learning Rails course also offer a very powerful hosted content management system for web designers, which enables you to build sophisticated, database-driven sites without programming. This is a great alternative to building a custom Ruby on Rails site for those applications for which you just can't justify the cost of a custom solution.

To learn more, sign up for the free Learning Webvanta course on building database-driven web sites without programming.

Adding User Authentication

comments

Goals

In this lesson, we add user authentication so only logged-in users can access the page controller and modify the contents of the site.

Setup

We begin with the code with which we ended Lesson 10. These zip files contain the beginning and ending states of the code:

Page title cleanup

First, we need to take care of a little problem we created for ourselves with the way we handled the page title metadata in the previous lesson.

We’re going to add a couple more admin controllers in this lesson, and with the approach used in the previous lesson, we’d need to specifically set the @pagetitle instance variable in each of those controllers. For now, we’re going to replace the existing setting of the title tag in the application layout with the following:

<title><%= @pagetitle || (@page && @page.title) || "Learning Rails Sample Application" %></title>

This line sets the pagetitle in one of three ways:

  1. If there is an instance variable @pagetitle, use that
  2. If not, then use @page.title, if there is a @page object
  3. If there’s neither a @pagetitle nor a @page object, use the fixed string

This is a little messy, and in a later lesson we’ll fix it in a more elegant way.

Install plugin

The plugin we’re going to use is called restful_authentication. You can find plugins by searching on Google or on various Rails plugin directory sites. One good site is AgileWebDevelopment. From this site, you can get the URL for the repository where the plugin code is located.

To install restful_authentication, enter the following line in a terminal at the root of your application:

script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/

You can view the readme in vendor/plugins/restful_authentication to learn more about it.

Set up the plugin

This plugin provides a generator of its own to help us set things up, so let’s run it:

script/generate authenticated user sessions

In this command, “authenticated” is the name of the generator; “user” is the name of the model that will store user names and passwords; and “sessions” is the name of the controller that will manage user sessions.

This generator creates a migration for us, but we need to run the migration:

rake db:migrate

Finally, to make the methods provided by this plugin available in your controllers, you need to add the following line to the file controllers/application.rb:

include AuthenticatedSystem

The application controller is “mixed in” to all other controllers, so any code you put here is available to all controllers. So by putting the “include” statement for the authenticated system here, you’re effectively adding that code to every controller.

Creating a user

Before we can have log-in, we need to have users, so let’s add some user management.

The authenticated generator we ran in the previous section gave us a users controller and a view for creating users, so browse to //localhost:3000/users/new and create a login for yourself.

The generator also created a sessions controller, which is what handles the actual log in and log out operations. Logging in is creating a new session, and logging out is destroying a session. It’s convenient to have shortcuts we can use to refer to these, so let’s add some named routes. Add the following lines to the top of the config/routes.rb file:

map.logout '/logout', :controller => 'sessions', :action => 'destroy'
map.login '/login', :controller => 'sessions', :action => 'new'

This gives us two things. The text ‘/logout’ and ‘/login’ makes those simple URLs work. And the words after the “map.” provide shortcuts we can refer to anywhere in our code when we want to generate that URL, using either login_path, for example, to generate a relative URL, or login_url, to generate a full, absolute URL.

Let’s add a log-in button to the navigation bar. Open views/layouts/application.html.erb, and add this code to the end of the list of links that creates the nav bar:

<li>
   <% if logged_in? %>
      <%= link_to "Log Out", logout_path %>
   <% else %>
      <%= link_to "Log In", login_path %>
   <% end %>
</li>

The restful_authentication plugin provides us with a “logged_in?” method that we can use to determine if any user is logged in. If someone is logged in, then we display a log out link; if not, we display a log in link.

Using authentication to protect the admin pages

Now we have our entire authentication system in place, but we haven’t actually used it to require login for any pages. We need to invoke the authentication feature for the pages for which we want to require log-in.

Open the file controllers/pages_controller.rb, and add the following line:

before_filter :login_required

“login_required” is another method provided for us by the restful_authentication plugin. The before_filter causes this method to be executed before any action in the controller.

Now do the same for users_controller.

Take care of page titles

Just as in the previous lesson, we need to set the @pagetitle instance variable in the user and session controllers, since these pages aren’t generated from page objects.

Wrapping up

Try accessing localhost:3000/pages, and you should be presented with a login screen. Log in with the credentials created in the previous step, and you should see the Log In button in the nav bar change to Log Out.

Try creating a new user by accessing localhost:3000/users/new. You shouldn’t be able to create a new user without being logged in. (If you didn’t create a user before adding the login requirement to the users controller, you can comment that line out temporarily.)

Coming up

In our next lesson, we’ll make a variety of small enhancements to add some polish and additional capabilities to our content management system.


Add a Comment

Have a comment or question about this lesson? Add it here.






Comments on This Lesson

From: Nathan       Date: 02/05/10 03:43 AM

Subject: One possible pitfall

This may be a stupid mistake, but it got me stuck for a while. I am a Rails newbie working on an app (not the one from your previous examples) and came to this page to read about authentication. I followed the instructions, but couldn’t create new users. No errors, but nothing was saved to the database. I looked in development.log and saw empty parameters from the form submission.

I couldn’t find anything about this error, and finally guessed that it was a routing problem. I added a restful route for users (map.resources :users) and that solved it.

Maybe someone else will find this comment helpful if they have the same problem.

From: Doug       Date: 12/12/09 11:21 AM

Subject: Pitfall from Git version install

Wayne comments about the label-tag error. You can change the url name from git:// to http:// and it will download and install. However, the script/server will produce an error.

I found that the fix (don’t do it) to this error (again, don’t do it) is to upgrade rails to 2.3.5 by doing gem install -v=2.3.5 rails.

That has sent me down a rabbit hole I’ve spent days trying to find my way out. DON’T UPGRADE!! eventually, you will try to start using ruby 1.9.1, but none of it will work properly. save yourself from the head ache and download the backwards compatible version.

I am now starting the tutorial again after learning the hard way.

From: cecille       Date: 09/24/09 10:17 PM

Subject: include AuthenticatedSystem

why do AuthenticatedSystem needs to be included in all controllers? Is it necessary to do that in all new plugins? (include new plugins)

From: Wayne Simacek       Date: 09/16/09 04:35 PM

Subject: Installed the Git version...not sure how to back it all out

Before reading all the problems in the comments, I went ahead and figured out how to install the Git version and ran the ’script/generate user sessions. it updated my routes.rb with 4 new entries at the top map.logout, map.login, map.register and map.signup.

My question now is I’m getting the undefined method ’label-tag from new.html.erb.

I don’t know how to go backward or forward???

I suppose I can just start over from Lesson 10 and work forward the “recommended” way?

Thanks in advance, Wayne

From: Scott Lewis       Date: 07/20/09 10:15 PM

Subject: Undefined method 'logged_in?'

I get the following exception when I run the application after I try add the logged_in? method.

undefined method `logged_in?’ for #

Any thoughts what I am doing wrong?

From: Charlie Magee       Date: 03/27/09 04:46 PM

Subject: Don't use newer version of restful_authentication

Hi All,

Restful_authentication has been updated and creates problems with Lesson 11. Instead of going to agilewebdevelopment.com and using the repository url on the plug-in page, scroll up this Lesson 11 page here at buildingwebapps.com and copy the repository url for the plugin and use that.

Charlie Magee

From: shakeeb       Date: 01/29/09 07:35 AM

Subject: logim

great dude

From: Kenton       Date: 12/16/08 01:07 PM

Subject: So many aha moments...!

Guys, thanks so much for putting this course together. I’m learning a lot. For example, in going through this lesson, I kept getting an error when testing the login/logout functionality. I did the lesson earlier but wanted to go through again using an app that might go live.

While troubleshooting I found out that the order in which things are placed in the routes.rb file matters. I guess rails goes through them one by one or something. My /login and /logout routes were AFTER the :name route and threw an error. OOPS!

Maybe my mistake will help someone else out.

Thanks again,

Kenton

From: DVargas       Date: 10/31/08 11:12 AM

Subject: Greg's "Subject: New Restful Authentication breaks link_to routes" problem.

Hi Greg,

I am also new to Ruby on Rails and had a similar situation before of not displaying something back to the page. Need to remember when displaying something back to a page, you must include the “=” symbol after the <% (i.e. <%=).

The following is the specific area that you had trouble with. Notice the link_to lines.

  • <% if logged_in? > <= link_to “Log Out”, logout_path > < else > <= link_to “Log In”, login_path > < end %> Hope this helps you.

  • From: Rich Webster       Date: 10/30/08 07:31 PM

    Subject: New restful_authentication configuration

    Hey guys… this course is awesome, but is there any chance you could update it to accommodate the changes in restful_authentication?

    I’d probably just have read a book, but there are so many new ideas to get used to (git, gems, etc.) that make me a total noobhead… hold my hand and lead me… be gentle. ;-D

    From: Rich Webster       Date: 10/30/08 07:31 PM

    Subject: New restful_authentication configuration

    Hey guys… this course is awesome, but is there any chance you could update it to accommodate the changes in restful_authentication?

    I’d probably just have read a book, but there are so many new ideas to get used to (git, gems, etc.) that make me a total noobhead… hold my hand and lead me… be gentle. ;-D

    From: cherrian       Date: 10/23/08 03:38 AM

    Subject: Mailing address??

    Hi! I am very stuck on lesson #9 can’t see to get past here,but that is O.K.! I must resolve this on my own. Anyway I would like to sent personal check to cover the cost of this course could please send me a mailing address please? Would very much appreciate your response on this matter. Thanks

    From: Vitaliy Khudenko       Date: 09/18/08 03:24 AM

    Subject: session routes

    Looks like session routes need some fix. For example, try to login with wrong pass. The expected URL after this is ‘http://your_site/login’, but it differs.

    From: Greg       Date: 08/14/08 08:51 PM

    Subject: Fixed

    Never figure out what made my link_to links disappear but I swapped out my application.html.erb with the class example and everything is back to normal again. Thanks.

    From: Greg       Date: 08/13/08 09:17 PM

    Subject: New Restful Authentication breaks link_to routes

    I tried using the newest restful authentication on github and it doesn’t seem to work with the routes set up in the screencast. The “link_to” will not display on page, they are hidden and I’m not sure why… if I use regular html links they it works (displays links on page) and I could use the older version of restful i.e. the screencast version (works well) but I guess I would like to know why it isn’t working. I know its user error because I am still learning all this. Does anyone have a clue? hint maybe? Thanks.

    From: Gurvinder       Date: 08/11/08 10:20 AM

    Subject: Lost/Forgotton Password

    Hi Michael & Christopher
    I was just wondering, is it possible to have the lost/forgot password button in restful authentication and if so, How?
    I have been looking at couple of sites for this, but dint find any nice blog. It will be appreciated if you can advice on it.
    Thanks in Advance.

    From: Gurvinder       Date: 08/08/08 11:20 PM

    Subject: Re: I did the same thing as Gurvinder

    Thank you so much rick for your comment. I think this should be solved in rails as we have to keep track of which route goes first and which NOT. And in a big app. it can become cumbersome.

    From: rick       Date: 08/03/08 05:29 PM

    Subject: I did the same thing as Gurvinder

    Funny, I did the same thing as Gurvinder. For those curious, the api has a good explanation http://api.rubyonrails.org/classes/ActionController/Routing.html

    “Not all routes are created equally. Routes have priority defined by the order of appearance of the routes in the config/routes.rb file. The priority goes from top to bottom. The last route in that file is at the lowest priority and will be applied last. If no route matches, 404 is returned. "

    So in this case Gurvinder, if you had the :name route first and you tried to go to http://localhost:3000/logout it will try to map “logout” to the :name param and processing would try to take place in the viewer controller (which is obviously not what we want.) hth

    From: Gurvinder       Date: 07/22/08 03:06 PM

    Subject: One Simple question

    Hi Michael & Christopher
    I have yet another question for you guys regarding this podcast.
    In this podcast when you configured the route.rb file you added login and logout routes before the view page route….why?
    I am asking this coz when i entered those routes after the view_page route the application started giving me errors and when i put those two routes before the Page Route as explained in the screencast it started working fine.
    Please comment

    From: Thando Vuzane       Date: 07/14/08 10:34 PM

    Subject: Well explained

    Thank you, this has been well explained.

    From: k       Date: 07/10/08 06:17 AM

    Subject: k

    k

    From: Jason       Date: 07/10/08 05:16 AM

    Subject: Redirect after session authentication throwing errors

    I am resolving my own issue. I just needed to restart the mongrel server in order for the new controllers to take effect.

    Thanks J

    From: Jason       Date: 07/10/08 04:49 AM

    Subject: Redirect after session authentication throwing errors

    I love the tutorials that you all have created. One of the issues I am running into is after the session has been authenticated and the framework tries to do a redirect. It looks like that are a lot of changes with the new restful_authentication plugin. (I used the git install and have the lasted code for the plugin)

    It seems that when the session authenticates the framework is getting confused with the url of /session; it thinks this is a page name and throws an error on the show.html.erb page with the error message of the “nil.body”.

    Any suggestions would be much appreciated.

    Thanks J

    From: Henry       Date: 07/01/08 02:17 AM

    Subject: Login oddity

    After completing the code about and attempting to access “pages”, I now get an IE “web login” dialog, which is not unexpected (??). However, the oddity is that if you cancel the login dialog, I now get prompted to open/save/cancel a Shockwave file named “new.” If I try to either open or save, I get an error. Is this expected behaviour at this point in the tutorials?

    From: Christopher Haupt       Date: 06/03/08 02:04 AM

    Subject: RE: getting the plugin

    Now that Rails 2.1 is out, it includes a fixed up version of script/plugin that can install from either Subversion or git. If you are able, update your Rails gem to 2.1 (Mac: sudo gem update rails, Win: gem update rails) and you can start using script/plugin install again.

    Of course, you’ll need to have git installed too. On Mac, if you don’t have it already, you can use the MacPorts version. (My articles on installing Rails on Mac details MacPorts setup itself.) On Windows get the full msysgit package from the download area.

    The other ideas here work (e.g. clone the plugin repository, download a tar, etc), but what you have to be careful of is that many plugins require that you run their “install” script to properly get set up. This process can vary depending on the plugin.

    From: phil       Date: 06/02/08 03:47 AM

    Subject: Route Login/Logout Location

    Ah ha! After some time debugging – I figured out that the location of map.login/map.logout matters in routes.rb These must be above map.view_page

    thanks from a noob

    From: Josh Harris       Date: 05/29/08 01:47 AM

    Subject: Re: Plugin not found

    Answering my own post.

    Instead of using the git-based link provided at agilwebdevelopment.com… stick with the link provided in the screencast:

    http://svn.techno-weenie.net/projects/plugins/restful_authentication/

    and be sure to use an underscore between “restful_authentication” at the end of the URL.

    From: Josh Harris       Date: 05/29/08 01:33 AM

    Subject: Plugin not found

    I am getting a ‘plugin not found’ with

    git://github.com/technoweenie/restful-authentication.git

    which is what is listed as the Repository at agilewebdevelopment.com. Any help with getting this plugin to work or a work around.

    From: Michael Slater       Date: 05/20/08 02:04 AM

    Subject: :login_required

    Tim, thanks for pointing that out. I’ve corrected the text. In “before_filter :login_required”, the colon is required because we’re providing the name of the method, not invoking the method.

    From: Nitilaksha.M       Date: 05/18/08 02:58 PM

    Subject: Thanks

    Excellent-very clear and concise tutorial.Thanks a lot for Your Team

    From: Scott       Date: 05/16/08 11:48 PM

    Subject: Re: Plugin is now git-based and...

    Responding to my own post to provide the correct command:

    git clone git://github.com/technoweenie/restful-authentication.git

    From: Tim Morgan       Date: 05/15/08 08:25 AM

    Subject: small typo

    login_required should be a symbol in the before_filter declaration above.

    -great lessons!

    From: Scott       Date: 05/13/08 02:29 PM

    Subject: Plugin is now git-based and running script/plugin install produces infinite loop

    This course is fantastic. Many thanks! I’ll be sure to digg it, 5-star it on iTunes, etc. as soon as I finish it.

    I ran in to one slight problem outside of your purview: the restful authentication plugin repository is now at http://github.com/technoweenie/restful-authentication/tree/master

    Running script/plugin install produces this recursion: ./opensearch.xml ./bundle.css?[alnum string] ./master/opensearch.xml ./master/bundle.css?[alnum string] ./master/master/opensearch.xml ./master/master/bundle.css?[alnum string]

    1. etc.

    While I can of course just download the tar, can you advise the correct way to handle this?

    From: Michael Slater       Date: 05/08/08 03:15 PM

    Subject: Finding methods in restful_authentication

    Shilpa, unfortunately, for the most part you just need to read the code, in particular the file authenticated_system.rb in your lib directory. There’s also examples scattered around the web in various tutorials and blog posts, and in a couple books. This is one of the hazards of open-source software.

    From: Shilpa       Date: 05/08/08 08:13 AM

    Subject: Restful_authentication

    Hi Guys, This is an awesome screencast. I did learn how to use plugin.Also the restful_authentication is the most required i feel. Thanks a lot. One quaetion i have in this regard ..How do we know what methods are available and the usage of the methods in the plugins ,as i didn’t find any explanation in ReadMe also. For example login_required?Logout,Login when i installed plugin i got a message like don’t forget to use Signup it’s syntax,similalrly Login Logout what you have explained in the screencast.

    Or am i missing to notice something???

    From: John       Date: 05/05/08 10:32 AM

    Subject: RE: Plugins and Subversion

    Chris, Thank you for your response. I did install Subversion on the machine (Fedora 8 distro) and still had problems installing the plugins, but once I put it under version control, the problem went away. The error btw was “Plugin Not Found” even though typing “script/plugin list—source=X” (where X is repository URL) actually did report several available plugins, including of course Restful Authentication. Anyhow, not sure exactly what happened, but putting the project under SVN control did the trick. It was the first time I used Subversion after installing it, so perhaps something somewhere got initialized in setting up just ANY project under version control. Cheers…and thank you for the new screencast. -John

    From: Christopher Haupt       Date: 05/04/08 08:49 AM

    Subject: RE: Plugins and Subversion

    John: What kind of problems did you run in to? On what platform? Rails plugins are independent of source-code control, so using plugins shouldn’t be a problem regardless if your own project is under Subversion, git, or nothing at all. What may be a problem, though, is if you try to install a plugin and you don’t have the Subversion client program on your machine. Some plugins are stored in source code repositories and the script/plugin install script will utilitize Subversion to pull down the code if required (it will try http when possible). Best thing to do is to install a Subversion client on your machine (see our Installation Articles), but if you don’t want to, you can usually download the plugin code manually, unpack it, and place it in your vendor/plugins area of your project (no source code control required).

    From: John       Date: 05/02/08 09:21 AM

    Subject: Plugins and Subversion

    First off I want to thank you guys for really awesome work! I am brand new to Rails and Ruby, having used PHP with some frameworks that were, well let’s say, lacking :-) I love how easy it has been to get into Rails following your screencasts.

    As a newbie, I ran into quite a bit of difficulty installing the plugin, and it took me a good hour of googling around to realize that Rails plugins work only on code that is under Subversion control. If you didn’t mention it in the screencast, it might be worth putting a comment on your site somewhere.

    Thanks again. I look forward to Cinqo de Mayo now for more reasons than one.

    John

    From: Michael Slater       Date: 04/27/08 02:32 PM

    Subject: @pagetitle vs. @page.title

    Nate, you raise an excellent point. We were trying to keep things simple, but it ended up making it more complex. To be honest, it was a decision that we regret, and we’ll be changing it (more than once, as the design evolves) in future lessons.

    From: nate       Date: 04/27/08 05:25 AM

    Subject: @pagetitle vs. @page.title

    I’m curious about the choice of accessing @page.title directly in the application template, rather than assigning it to @pagetitle in the pages controller “show” action, thereby eliminating the need for the || comparison in the view.

    Thanks for the tip on the restful_authentication plug-in. I’m eager to dive into the code it provides to see how it compares with the RailsSpace book’s implementation of user authentication.

    Nate

     

    Sponsored By

    New Relic Rails Performance Monitoring