Lesson 11
Adding User Authentication
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:
- Learning Rails example app code as of the end of Lesson 10
- Learning Rails example app code as of the end of Lesson 11
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:
- If there is an instance variable @pagetitle, use that
- If not, then use @page.title, if there is a @page object
- 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.


Reader Comments
42 comments
plugins now on git instead of svn
From: Michael, 08/01/10 01:43 PM
Sam, read through the other comments and you will find the answers. The plugin was moved from an SVN repository to git.
URGENT HELP PLZ! CAN NOT INSTALL!! PLZ HELP
From: Sam P, 08/01/10 05:13 AM
Hi there Thanks for this I have rails 2.3.8 On a Mac OSx 10.6 I am new to Runy on Rails Trying to install and I get an error This is what I do: >rails test >cd test >script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/ Plugin not found: ["http://svn.techno-weenie.net/projects/plugins/restful_authentication/"] Why it is not found?! Had the location changed? Please someone email me, here is my email: info@ukcivil.com its urgent± thanks! plz email me if you know how this can be fixed: info at ukcivil dot com
One possible pitfall
From: Nathan, 02/05/10 03:43 AM
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.
Pitfall from Git version install
From: Doug, 12/12/09 11:21 AM
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.
include AuthenticatedSystem
From: cecille, 09/24/09 10:17 PM
why do AuthenticatedSystem needs to be included in all controllers? Is it necessary to do that in all new plugins? (include new plugins)
Installed the Git version...not sure how to back it all out
From: Wayne Simacek, 09/16/09 04:35 PM
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
Undefined method 'logged_in?'
From: Scott Lewis, 07/20/09 10:15 PM
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?
Don't use newer version of restful_authentication
From: Charlie Magee, 03/27/09 04:46 PM
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
logim
From: shakeeb, 01/29/09 07:35 AM
great dude
So many aha moments...!
From: Kenton, 12/16/08 01:07 PM
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
Greg's "Subject: New Restful Authentication breaks link_to routes" problem.
From: DVargas, 10/31/08 11:12 AM
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.
New restful_authentication configuration
From: Rich Webster, 10/30/08 07:31 PM
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
New restful_authentication configuration
From: Rich Webster, 10/30/08 07:31 PM
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
Mailing address??
From: cherrian, 10/23/08 03:38 AM
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
session routes
From: Vitaliy Khudenko, 09/18/08 03:24 AM
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.
Fixed
From: Greg, 08/14/08 08:51 PM
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.
New Restful Authentication breaks link_to routes
From: Greg, 08/13/08 09:17 PM
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.
Lost/Forgotton Password
From: Gurvinder, 08/11/08 10:20 AM
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.
Re: I did the same thing as Gurvinder
From: Gurvinder, 08/08/08 11:20 PM
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.
I did the same thing as Gurvinder
From: rick, 08/03/08 05:29 PM
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
Redirect after session authentication throwing errors
From: Jason, 07/10/08 04:49 AM
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
Login oddity
From: Henry, 07/01/08 02:17 AM
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?
RE: getting the plugin
From: Christopher Haupt, 06/03/08 02:04 AM
Now that Rails 2.1 is out, it includes a fixed up version of
script/pluginthat 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 usingscript/plugin installagain.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.
Route Login/Logout Location
From: phil, 06/02/08 03:47 AM
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
Re: Plugin not found
From: Josh Harris, 05/29/08 01:47 AM
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.
Plugin not found
From: Josh Harris, 05/29/08 01:33 AM
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.
:login_required
From: Michael Slater, 05/20/08 02:04 AM
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.
Thanks
From: Nitilaksha.M, 05/18/08 02:58 PM
Excellent-very clear and concise tutorial.Thanks a lot for Your Team
Re: Plugin is now git-based and...
From: Scott, 05/16/08 11:48 PM
Responding to my own post to provide the correct command:
git clone git://github.com/technoweenie/restful-authentication.git
small typo
From: Tim Morgan, 05/15/08 08:25 AM
login_required should be a symbol in the before_filter declaration above.
-great lessons!
Plugin is now git-based and running script/plugin install produces infinite loop
From: Scott, 05/13/08 02:29 PM
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]While I can of course just download the tar, can you advise the correct way to handle this?
Finding methods in restful_authentication
From: Michael Slater, 05/08/08 03:15 PM
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.
Restful_authentication
From: Shilpa, 05/08/08 08:13 AM
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???
RE: Plugins and Subversion
From: John, 05/05/08 10:32 AM
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
RE: Plugins and Subversion
From: Christopher Haupt, 05/04/08 08:49 AM
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).
Plugins and Subversion
From: John, 05/02/08 09:21 AM
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
@pagetitle vs. @page.title
From: Michael Slater, 04/27/08 02:32 PM
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.
@pagetitle vs. @page.title
From: nate, 04/27/08 05:25 AM
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
One Simple question
From: Gurvinder, 07/22/08 03:06 PM
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
Well explained
From: Thando Vuzane, 07/14/08 10:34 PM
Thank you, this has been well explained.
k
From: k, 07/10/08 06:17 AM
k
Redirect after session authentication throwing errors
From: Jason, 07/10/08 05:16 AM
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