#82 HTTP Basic Authentication
Rails 2.0 offers an extremely easy way to do HTTP basic authentication. See how in this episode.
- Download:
- mp4Full Size H.264 Video (7.95 MB)
- m4vSmaller H.264 Video (4.88 MB)
- webmFull Size VP8 Video (13.1 MB)
- ogvFull Size Theora Video (10.1 MB)
Oh, hey, that's neat. Was just googling for this. Should make REST-authentication super easy, and then using the usernames and passwords in the database to authenticate.
<pre>
authenticate_or_request_with_httpt_basic do |username, password|
User.authenticate(username, password)
end
</pre>
Wohoo!
Hi. Sorry my stupid question, but how can I do logout using http_basic? :-)
Bye
Hi,
You can watch previous episode which is about Sorcery.
Cheers.
@August, right! Since the authentication is handled in a block there's a lot of flexibility. Moving it to the user model (if you have one) is a good idea.
@nelson, that's a good question. The authentication is kept in the browser (client side), so there's really no way to log out the user on the server side AFAIK. The user will have to close the browser to end the session. I think there are hacks around this issue, but I haven't looked into them.
I have a really stupid question. What is that Growl type notification that pops up whenever you are executing keyboard shortcuts in Textmate? That could be handy for me if I could figure out what it is and how to get it.
@Joel: Yeah, that was a stupid question =P It's listed on the "about" page, and is called KeyCastr.
@nelson: As Ryan says, http based authentication doesn't support logout. But as we're rails developers, we should be used to using systems that's opinionated and that makes choices for us - which is exactly what http does. This kind of authentication is rarely used to authenticate users through browsers, but it's ideal for authenticating in API's and so on, as most API reading systems supports the HTTP standards.
@August, @Ryan: then using Model inside the 'authenticate_or_request_with_http_basic' as used on the example, I have support to logout? The authenticate don't will stay registered on client-side?
(srry my english guys)
[]s :)
@nelson jr: As opposed to the "normal" way of authenticating, where you set session[:user] to something (which is what e.g. the restful_authentication does), this particular method authenticates you if the stuff inside the block returns true. So, doing this would authenticate you:
authenticate_or_request_with_http_basic { true }
This is what a User.authenticate action could look like:
def self.authenticate(username, password)
user = self.find_by_username(username)
user && user.valid_password?(password)
end
This method returns true if a user was found and the password was valid. Otherwise, it returns false (if the password wasn't valid) or nil (if no user was found with the specified username).
@August Lilleaas
You are absolutely right. To elaborate a bit more for nelson jr, with HTTP Basic Authentication and REST you won't need to use a server-side session at all. The server authenticates you and services your request. You then cease to exist to the server, as you are not actually "logged in".
This makes running a service/site across a cluster or servers simple because your session state (logged in, not logged in etc) isn't of any concern. A subsequent request could go to any server in a cluster and it wouldn't be a problem because you provide your authentication details again.
I would imagine you could still create a session for the user, right?
Also, how would this work for HTTP Digest Authentication? Could you do this with OpenID instead of a Username/Password combination?
Hello,
I just want to say "thank you". I'm new to rails and I like it. Your screencasts are great. I don't understand each of them fully, but from day to day I understand more.
Bye,
Patrick
@Ryan, I don't see what benefit storing it in a session would give because the browser will usually store the login credentials on its own. If you store it in a session it will be in two different places which could get messy.
As for HTTP Digest Authentication, I don't think Rails 2.0 offers an easy way to do this. But I haven't looked into it.
Also, I don't see any way to incorporate OpenID authentication into this.
I'm currently using restful_authentication. So, in the move to Rails 2.0, should I stick with that and "enhance" it with this? Based on August's comments, that is what is implied. Where might the code August posted be put? Sorry, my newby-ness is apparent.
Do you know if its possible to use http to request information from the user other than login credentials?
Keep up the great work guys! As I continue my education with rails (and ruby) into the 2.0 transition, your railscasts are a breath of fresh air in the often dark tunnel I call rails newbieness of which I suffer greatly.
@ryan
How would one do the call to such an authenticated controller from activeresource. How does one pass the request authentification at the reqest time. does that go into the model or is that a step done during the find?
I mean like so:
*model*
class Event < ActiveResource::Base
self.site ="http://localhost:3000/"
end
*irb*
s=Event.find 989
I haven't seen it asked yet and I've done some google-ing and haven't come up with a result either...
I want a authenticated? / logged_in? method. Because in my views I want the edit | delete links visible for the authenticated user but obviously not the general public...
Does anyone have any ideas? Thanks in advance.
I set up the auth model you described and it worked great. I switched my site to using it in development no problem. Then I went live, which is mongrel w/apache cgi. I can't seem to get the username and password through to rails. Has anyone found a good way to do this. I've gone through a lot of tutorials and guessing with no luck.
http_basic only works when running through curl with http://user@pass:localhost:3000/etc, not when running in Safari or Camino--I never get a window to enter the credentials, it just passes through, and then obviously creates the dreaded "nil" error when the @user can't be authenticated and found.
@Coop, no idea how to but I'm wondering the same thing.
@Eilert Islaksen, I don't think that it's possible otherwise someone would have said something...
@Oskar Lissheim-Boethius, I use Safari and always get the HTTP box to input my details
@Coop, Eilert Islaksen: I too was wondering how to combine authenticate_or_request_with_http_basic with the show/hide edit/delete links explained in Railscast 20.
The way I achieved this was to set an is_authenticated instance variable:
# products_controller.rb
def authenticate
@is_authenticated = authenticate_or_request_with_http_basic do |username, password|
username == "foo" && password == "bar"
end
end
Then you can show/hide in the view by:
# index.haml
- if @is_authenticated
= link_to …
You could add a helper method:
# application.rb
helper_method :admin?
def admin?
@is_authenticated
end
and go:
# index.haml
- if admin?
= link_to …
If you're having troubles with getting HTTP Basic Authentication working with Apache fcgi try adding this to your htaccess file.
RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
@nelson et al.
A way (hack) to logout of HTTP-Basic-auth is to let the user follow a link to a special 'logout' resource which will always return "401 Unauthorized", after which the browser will reset the user's credentials and therefore stop sending them as such.
@Joshua - Just what I needed, thanks!
In finding out how to password the exception_logger interface, I came across this neat stuff:
http://errtheblog.com/posts/67-evil-twin-plugin
Here's my code:
http://gist.github.com/9771
and that's that.
Hope it helps someone.
@QQ
Yeah, sorry, my code example didn’t work. I ended up using the session object to get it working: http://pastie.org/280240
How would I add this to my demo and test environments?
I want basic authentication based on environemt
Great screencast, really great!!! The comments also are very useful.
Thanks guys.
when I use this method on localhost, everything works fine.. but, when I host it online, the application root directory is in domain.com/local ..
in this, the authentication window comes, but it doesn't authenticate me actually.. I type the login, password, still, the window appears again and again, and if I cancel, I get:
HTTP Basic: Access denied.
The rewrite rule pointed out by Joshua even didn't work!
I tried a lot to write a Rewrite rule, but it didn't turn out for me.. probably the hosting provider has disabled fast cgi scripts..
Instead, I installed this plugin which has even got login/logout features.. :)
http://ariejan.net/2007/08/24/super-simple-authentication-plugin-and-generator/
Thanks again for this great work.
It appears the link to the http_authentication.rb source shown above is no longer valid since the code moved to github.
I assume you might want something like: http://github.com/rails/rails/tree/v2.0.0/actionpack/lib/action_controller/http_authentication.rb
There are a couple of comments here asking about digest encoding of username:password so I just wanted to say that the Rails HTTP authentication library also handles a form of digest encoding - though i am not sure if it conforms to HTTP spec.
To use it, encode 'username:password' in Base64 and put it in the 'authorization' header of the request (which is where basic auth is anyway)
In curl, the line looks like this:
http://gist.github.com/50638
This is really really handy for JavaScript (and iPhone) apps accessing a resource server - especially if you do not have an SSL connection setup and do not want to send login info over the internets in the clear.
It's a pitty that this function do not protect the public-folder. Do you know a possibility, sans .htaccess?
Nice Tut! I think I may use this concept for my site. (currently implementing a new RoR tutorial system).
Had some random not working at some point with it, but I just changed the username and password and for some strange reason that fixed it.
Thanks Again,
Joe
Hola a todos estoy iniciando con el mundo ruby on rails y necesito hacer una aplicacion web con autentificacion y con base de datos prostgres alguien me podria guiar por favor es urgente gracias mi correo cyber_daemon_one@hotmail.com
Hi,
I am trying to run a curl url from my terminal and I am getting permission denied error.
curl -H "Accept: application/xml" http://localhost:3000/readings?current_user=1
I tried this as well:
curl -H "Accept: application/xml" http://localhost:3000/readings?user_id=1
in my readings controller I have before_filter method set.
Kindly suggest me how would I fix that.
Thanks
Puneet
Hello Ryan, first time posting - big fan...
This is killing me! I think the answer to this will help solve a lot of your commenters woes.
Im trying to do a remote authentication via json from within a JS based accelerator iphone app seen here http://pastie.org/789924 but i keep coming up with the famous ActionController::InvalidAuthenticityToken. I've been searching all night and I find myself more confused than when I started. How does one go about construct this JSON call in order to circumvent the protect_from_forgery method!
Thanks in advance and keep doing the awesome job youre doin...
NICE AUTHENTICATION HACKING PROGRAM
I just want to say "thank you". I'm new to rails and I like it. Your screencasts are great. I don't understand each of them fully, but from day to day I understand more.
Great screencast, really great!!! The comments also are very useful.
Thanks guys.
otherwise someone would have said something...
@Oskar Lissheim-Boethius, I use Safari and always get the HTTP box to input my details
when I use this method on localhost, everything works fine.. but, when I host it online, the application root directory is in domain.com/local
Thanks again for this great work.
It appears the link to the http_authentication.rb source shown above is no longer valid since the code moved to github.
on logout call this in java script function
document.execCommand("ClearAuthenticationCache");
to clear the cache of the browser
I can't get this to work, it always gives 401 unauthorized and never asks for a username/password. If I use curl and give it a username and password though it works, can anybody help me out?
Thanks
Does anybody know how the authentication problem can be solved when using Phusion Passenger?
Every couple of weeks, I face this bug that doesn't let me to login when using IE! Strangely enought, it works fine other times!
Thank you very much in advance!
> Joshua Jul 16, 2008 at 01:08
> If you're having troubles with
> getting HTTP Basic
> Authentication working with
> Apache fcgi try adding this to
> your htaccess file.
>
> RewriteRule ^(.*)$ dispatch.fcgi > [E=X-HTTP_AUTHORIZATION:%
> {HTTP:Authorization},QSA,L]
How do you handle exception here ? Don't want to have this ugly "HTTP Basic: Access denied." sign.
nice video. Can you add some details if incorrect username or password is entered, instead of persisting, can it
1) show a page with Unauthorized: incorrect username or password
2) or somehow indicate wrong username or password and let the user try again
3) either (1) or (2) above after 3 attempts to log in but fail.