#21 Super Simple Authentication
Apr 20, 2007 | 6 minutes | Administration, Authentication
The final piece of the administration puzzle: authentication. There are many different approaches which is why I saved this step for last. This episode will cover a few techniques including the simple solution used for this site.
Hey, man. Great work! Really helped me get going.
Is this the place to ask questions? I'm trying out acts_as_authenticated, and have hit one snag based on the helper method you wrote in the screencast. From what I can tell, current_user.name throws an error if the public tries to access the page without being logged in. I'm sure it's a simple fix, but I thought I'd point that out. And see if you had a quick solution.
!Jon
Hey, super cool casts you make ;)
Can you make a screencast about using and integrating acts_as_auth or restfulauth ?
@Jon,
Good question, I should have mentioned this in the screencast. You need to check if the user is logged in first:
def admin?
logged_in? && current_user.admin?
end
Untested.
I wished I'd seen this before I installed acts_as_authenticated! I'll certainly use this for my next simple app!
Ryan, I was wondering if you could explain to me as to how the variables you are using such as 'home_path' and 'sessions_path' are set. Furthermore, I am trying to use these past 3 videos to create a simple auth system for a program I'm working on, but I can't seem to figure out 2 problems: 1 - how did you have your 'new.rhtml' load when you browsed to '/login', and 2 - how did you decide where to put the same file (I assumed it would be 'views\login'. I can explain more in detail if I can contact you via email, as I don't really want to make such a long comment on your website. Also if you or anybody on this site feel like they can help please do.
Finally, thank you for doing such a great favor to so many people by creating these wonderful screencasts.
Please disregard my previous post, as I forgot about the routing.rb file. I modified it according to your tutorial and it now works! Thanks again for such a great service!
Hi, i followed the tutorial and its great but i also try to enter any password and not use the foobar and it can pass.. how to resolve this? =)
on sessions_controller.rb
session[:username] = params[:username]
application.rb
session[:password] == "foobar"
Thanks dude! =)
@Brian, although the message says "successfully logged in" when providing an incorrect password, the user will not have access to the administration capabilities unless the password matches. I did this for simplicity but it can be confusing so you may want to change it.
One way is to move the comparison further up. So instead of checking if the password matches in the "admin?" method, check it inside the "sessions/create" action. Then you can provide an error message when the password is incorrect.
Can i ask for your help? =) because i have here is a project called "leaveform"
i want to have simple login system. i want to connect it to my users table.
and when they login, they can see the welcome screen.
here is my syntax in app/controllers/application.rb
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
# Pick a unique cookie name to distinguish our session data from others'
session :session_key => '_leaveform_session_id'
helper_method :admin?
protected
def authorize
unless admin?
flash[:error] = "Unauthorize access"
redirect_to home_path
false
end
end
def admin?
#create if statement here...
if session [:password] == 'brian'
true
redirect_to home_path
else
false
redirect_to error_path
end
end
end
here is the syntax of my app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def create
if session[:password] = params[:password]
flash[:notice] = 'succesfully logged in'
redirect_to home_path
else
redirect_to login_path
end
end
def destroy
reset_session
flash[:notice] = 'successfully logged out'
redirect_to login_path
end
end
@ryan bates
hi, i already fix my error.. sorry i didn't see the "==" in the password for the password is equals equals.
now its working and my next step is to connect ito database when i have users table.
Thanks =)
Hi to all!,
any idea on how can i connect this one to database? Now, I have users table with username and password field in my users table. how do i connect this to the login system?
Thanks
@Brian, I recommend asking your questions over at railsforum.com. That way it will be easier to post code samples and ask more detailed questions. I visit there frequently so hopefully I can get around to answering you there. Thanks.
Hi,
I have posted it on:
* Index
* » Rails Programming
* » Super Simple Authentication
Thanks
Hi,
Really good screen casts but I am also having a problem with setting up the sessions_path and home_path variables
I have set up the the routes.rb file as specified in the video, but I get this error:
undefined method `first' for :sessions:Symbol
if i comment out the map.resources line
then I get the undefined method or variable sessions_path error.
Any help appreciated
Kev
@Kev, what version of Rails are you using? This requires Rails 1.2. If you are using an older version then it won't work.
@Ryan,
I thought that might have been the problem, so I upgraded - am now on 1.2 but the issue is still there.
Fixes to the source of routes.rb
1) should be map.logout for the logout line
2) probably should include:
map.resources :sessions
Which may be @kev's problem.
Just discovered your series recently - still working my way throught them - they are very insightful even on the basic topics.
@Ofer, thanks. Fixed.
Hey guys,
been away from the code desk for a bit :)
When I upgraded rails to 1.2, should I have done anything to the app i.e. would it need to be ported?
I had already tried including:
map.resources :sessions in the routes.rb
file, but now the WEBrick won't finish booting up with the error:
undefined method `first' for :sessions:Symbol.
I'm a bit stuck and considering starting the site again using 1.2 as the starting point unless this sounds stupid.
Cheers
@Kev, I use Rails 1.2 in these screencasts, so it should work without any problems. It's hard to tell what the issue is without seeing the code. You may want to post your question on railsforum.com along with your code.
Btw, just fixed my issue - I didn't know that the environment.rb needed to be changed after an upgrade thanks for the help anyways
Really dumb question from a total noob, I'm sure: The routing action is shown as "new," but the action is shown in the SessionsController as "create." What am I not understanding?
BTW, Ryan, you totally rock.
@Tony, the "new" action is really there, it's just not shown in the controller. There's a "new.rhtml" view which will be used for the new action. That just displays the login form. The "create" action handles the login process which is what the form goes to.
Got it. Ergo, the "create" action in the form. Thanks.
I think you should never use IP based authentication, even if you're using only trusted addresses like 127.0.0.1, because it's possible to spoof the IP address:
http://www.securityfocus.com/infocus/1674
Also, if you're storing your password in a plain text form on a shared environment, make sure that only you have a read access to the file (chmod 600). Of course, encrypting your password is always encouraged.
Is it possible to include the validation in the plugin with a dynamic validate method?
@Chris, I'm not certain what you're asking. Which plugin are you referring to? And by validation do you mean the checking of the password?
I'm sorry, I meant to post this on episode 33 making a plugin. In that episode, you ended with a validate method in the task.rb file and I was wondering if it were possible to include that in the plugin?
Excellent 3-part series. I'm coming from a PHP background where I usually had a separate /admin folder, but I was stumped on the best way to do this RESTfully in Rails. This makes a lot of sense. I get it now, thanks to you!
The naming confuses me. The session gets created automatically somehow by rails when a browser accepts a cookie or something? If you navigate to "new" I guess you get given a form text field that will call the create action that doesnt create a new session but sets the session[:password] . Is "create" a misnomer or am I missing something? Shouldn't it be called something like "set_password". The destroy seems to actually destroy all session information, not just the password so the naming seems appropriate.
hi,
can somebody tell me how the create action is called? in the screencast i just see a:
<% form_tag sessions_path do -%>
no mention of a create anywhere. I know how to fix this myself but i am just wondering how this works in the screencast without any mention of 'create' anywhere.
BTW i am a big fan of the railscasts, thanks!
@Mieg
He's using a REST way...
In the routes.rb he set map.resources :sessions
With this he can do a post request on sessions_path (or sessions_url) to do a create. With a delete request on an id session_url(id), :method => :delete call for a destroy and session_url(id), :method => :put is a call for update.
For more info have a look here http://api.rubyonrails.com/classes/ActionController/Resources.html
Hi Ryan, excellent tutorial series. I was looking for a simple way to do an admin kit while keeping the code DRY. This method seems right up my alley, especially since I'm very new to Ruby and Rails. Thanks!
I'm a little on the new side but I thought you were never supposed to store a password in the session? Isn't that a big security no-no?
@PJ, good point. Honestly I haven't looked into the security risks. It's probably not the safest thing if the sessions are stored in the cookie as is the default with Rails 2. Alternatively you can do this:
session[:admin] = true
Which I believe will work okay.
great tutorials man. I wanted to note quickly that when using restful_authentication you can add a simple administrator check by using your boolean in the user table method
and calling:
def admin?
if logged in?
current_user.admin?
else
false
end
end
then create a new before filter
def admin_required
admin? || access_denied
end
Thats a simple way to do it, but it allows you to filted certain actions by wether a user is an admin and other by just if they are loggedin or not.
I've hacked mine up a lot more but for simple sites I somethimes use this method.
Great screencasts man.
Great episode -- this was really helpful.
RE PJ's security comment and Ryan's response: I was wondering exactly how that security risk would be fixed. What does the session[:admin] = true replace?
Hi Ryan,
First of all, thanks for all your railscasts: wonderful job, helped me a lot !
I'm struggling on an authentication through LDAP, more specifically authenticating as Apple's Open Directory users...
any idea on how to do this ?
Hi Ryan, I`m your big fan
Thanks for the screencast.
But I have a question. I think including password in session is danger isn`t it?
A follow up question on your @Ryan Bates answer to @Tony #28.
"... The "new" action is really there, it's just not shown in the controller. ..."
# The SessionsController has
def create
...
end
def destroy
...
end
# But does not have a 'new' action
# def new
# ...
# end
# The routes.rb has
map.login 'login', :controlller => 'sessions', :action => 'new'
Yet the /login causes the partial views/sessions/new.html.erb to be displayed. I think it is because of the map.connect(s), but both have /:id, which makes me think there may be another mechanism
Hey there. I'm following this tutorial (I thought) to the T, but when I try to log in to my app, I get redirected to /sessions/ with the following error:
Unknown action
No action responded to index
Maybe a problem with my routes? I have set up the routes as described here.
Can anyone help me out?
Hey Ryan,
Question for you. On the create action of the sessions controller, the password field you have on there, how are you going about that?
I am trying to use <% form_for ...
but can't think of an object to reference it to, since we have no User model in this scenario. Can you paste your create.erb and destroy.erb file code? That part just doesn't make sense to me...
is there any reason why this wouldn't work in 2.x? i've tried doing this on one of my new apps, and it just doesn't seem to work. i don't get errors, or exceptions, but it's not functioning like the screencast.
I can login but when i do it doesn't show me the administration links (edit, destroy).
I'm going to look at the code again and compare it to what's posted.
Thanks,
John
Found the problem. Ryan, you're the man!!!
http://railsforum.com/viewtopic.php?pid=111950#p111950
would live some help on this man
redirecting problems
in sessions controller
if wrong password, what do I do here?
tried this :
else
class SessionsController < ApplicationController
def create
session[:password] = params[:password]
flash[:notice] = 'Successfully logged in'
redirect_to :controller => 'home', :action => 'index'
else
authorise
redirect_to login_path
end
def destroy
reset_session
flash[:notice] = 'Successfully logged out'
redirect_to login_path
end
end
Hey Ryan,
Nice screencast.
1 question:
I noticed your routes.db has
login path set to:"sessions" controller and "new" action
But your session controller does not have "new" action. It has a "create" action. Is it that rails matches "new"action to "create" action?
Am I missing anything here? Thanks Abhi
Great screencast as usual, really well made.
I would point out only one thing:
In the video it is shown session :session_key => '_railcasts_session_id' in the ApplicationController. In Rails 2.3 or later it will give a warning:
DEPRECATION WARNING: Disabling sessions for a single controller has been deprecated. Sessions are now lazy loaded. So if you don't access them, consider them off. You can still modify the session cookie options with request.session_options.. (called from /app/controllers/application_controller.rb:11)
It's safe to remove that line. Nowadays it is not necessary to explicitly load the session. If you really want to, you can do it with request.session_options.
But that cast was made way back in 2007, so it is not an error. Great job.
is there any examples of how to test this authentication using functional tests?
@Nic - I know your question is very old, but if you want to integrate Rails with Open Directory Apple has some example code. Unfortunately you need to own OS X Server to view it. Apple uses Ruby on Rails to implement their wiki server and profile manager applications. Dig in to the Server.app bundler and look for a folder called webauthd. The ruby code for md5 authentication with Open Directory is in that folder.
I enjoyed over read your blog post. This was actually what i was looking for, and i am glad to came here!
• Your sharing of this content is very interesting. I like it very much. Hopefully I will be able to read more post from you.