Plugins - Restful Authentication
Add to favoritesThis is a basic restful authentication generator for rails, taken from acts as authenticated. Currently it requires Rails 1.2 (or edge).
To use:
./script/generate authenticated user sessions
The first parameter specifies the model that gets created in signup (typically a user or account model). A model with migration is created, as well as a basic controller with the create method.
The second parameter specifies the sessions controller name. This is the controller that handles the actual login/logout function on the site.
You can pass —skip_migration to skip the user migration.
From here, you will need to add the resource routes in config/routes.rb.
map.resources :users map.resource :session
Generate your mailer:
./script/generate authenticated user --include-activation
Tags
REST
Restful
Restful
aasas
activation
acts
as
auth
authenticated
authentication
jeah
seperated
space
tabnav


I'm having a problem with this. I've developed an application with restful_authentication and it's running fine locally under mongrel but when I deploy it to my host running fast-cgi the routes act differently.
so the line <% formfor sessionpath do -%> should direct to the create action in the sessions controller (as it does locally) but instead it calls the show action.
In my routes.rb I have: map.resource :session, :controller => 'sessions'
which should create the default routes to actions create and show (plus others) the difference being show is GET and create is POST. I've tried specifying the form_for as POST with :method => "POST" but it still directs to show (via GET) in fast-cgi. Any ideas how to debug this?
An exception occurs if I delete cookies (clean personal info in firefox) just before submit in the login: ActionController::InvalidAuthenticityToken in SessionsController#create
Any idea? Thanks.
If you're visiting this plugin for the first time, you might consider writing your own from scratch. At least you'll learn something, and it might even save you some time.
Eventually, I also had to skip the verifyauthenticitytoken in both controllers to avoid ActionController::InvalidAuthenticityToken exceptions flying low:
class SessionsController < ApplicationController skipbeforefilter :verifyauthenticitytoken
class UsersController < ApplicationController skipbeforefilter :verifyauthenticitytoken
Hm, with the latest security patch for restful_authentication installed, this spec fails for me:
it 'does not activate user without key' do get :activate flash[:notice].should be_nil end
My route for :activate looks like this: map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate' so the spec won't hit it. I get
$ rake ActionController::RoutingError in 'UsersController does not activate user without key' No route matches {:action=>"activate", :controller=>"users"} ./spec/controllers/userscontrollerspec.rb:68:
Probably what I want in production, but I'd feel better if ALL tests would succeed. I changed the test to this:
it 'does not activate user without key' do get :activate, :activation_code => "" flash[:notice].should be_nil end
and am a happy customer. Well, kinda. Took way too long to make this plugin work. Anyway, glad you did the hard part, Rick.
Hi,
maybe a really stupid question, but is there somewhere a documentation for the plugin "restful_authentication". I searched the web but could not find more than some small tutorials or the well known README from the plugin itself.
Thanks!
Hello, im having some problem here to get it to work. Ive just created a new rails project to test it. When i try: ./script/generate authenticated account sessions i get this error message: Couldn't find 'account' generator
what did i do wrong?
this plugin installation errors out after copying the several files into the plugin folder. Error msg states: "plugin not found...". Anyone else getting this?
Documentation for this plugin states that it will work for rails 1.2.6 and above. However, it only works for rails 2.0 and above. Directions below provide work around solutions. Also, this plugin uses observers which can be a pain because it sends out the wrong email notification at the wrong time when used with actas_statefulmachine. Follow instructions to modify the plugin to get rid of observers. Hope this helps!
Directions
1) Install Plugin (enter following command in terminal) ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
2) Then enter this command: ./script/generate authenticated user sessions \ --include-activation \ --stateful
3) Create the user table by running this command: rake db:migrate
4) The above will create the following: Controller sessions_controller users_controller
Model user_mailer user_observer user
Views for Session and User_mailer and Users
It also creates authenticated_system.rb in the lib folder (this is the one the doesn't work in rails 1.x)
5) In a brand new folder outside of your apps folder, e.g. temp, install a older version of this plugin.
svn export -r 2563 http://svn.techno-weenie.net/projects/plugins/restful_authentication
Copy the lib/authenticated_system.rb file from this temp folder into our apps/lib. It will overwrite the version you downloaded previously.
6) How to get rid of Observers Follow instructions from here written by Emil Tin Comment #6 :
http://harrylove.org/2007/12/17/activation-emails-with-restful-authentication-and-actsas_statemachine
The UserObserver seems incorrect for activation. I believe instead of aftersave, beforesave should be used, and the existing record and new record must be checked to see if it's being activate at that time in order to trigger the mailer.
def before_save(user) if user && user.id old_user = User.find(user.id) if olduser && !olduser.active? && user.active? UserMailer.deliver_activation(user) end end end
Anyone else getting:
ArgumentError in UsersController#create
A copy of UserObserver has been removed from the module tree but is still active!
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:237:in
load_missing_constant' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:469:inconst_missing' app/models/user_observer.rb:3:inafter_create' app/controllers/users_controller.rb:21:increate'I was experiencing the same issue as Emil Tin, which he describes this way:
"Also the 'activation succeeded' email is send out at the same time (somewhere in UsersController#create), even though the state of the user is still pending."
It's actually sent out by the UserObserver class. The UserObserver.aftersave method sends the "deliveractivation" email if the user is "pending". Since the default state of the user is "pending", it will send the second email right away. The UserObserver.after_save method should check if the user is "active" instead.
Got a tarball of the trunk.
It just does not work. This plugin might be useful to generate some files (the tests for example) and quickly see how to do some authentication in rails, but it is not working out of the box.
First error during the generation of the skeleton (in fixtures), second with this Session(s)Controller oddness, then I see in the code that some presumably important line could be "uncommented at your own risk" for some obscure reason (no link in the comment)... is this a "plug in"?
Really poor quality software.
Where is the tarball or the pure http access (git anyone)?
I'm behind a http proxy and svn does not work over it...
rails 2.0.2, latest version of plugin.
routes.rb map.resource :session
no change to any files.
am getting this error when trying to view login form.
No route matches "/session/new" with {:method=>:get}
My last post lost a line-break. Try this:
map.resources :sessions
map.resource :session, :controller => 'sessions'
@euro: I had the same problem as you outline in (2) - session or sessions? I solved it by having a sessions controller and this in my routes file:
map.resources :sessions map.resource :session, :controller => 'sessions'
hi, I have restful auth and act as state machine working as per Bparanj screencast BUT
Validation is not now working - wonder is it because register is used rather than the core save method in create new user.
Session or sessions?. I have to use both session (singular) and sessions (plural) controlllers. Rails 2 seems to require session (singular) for new and destroy actions BUT sessions (plural) for create action - real mystery for me - I have both controllers in the app at present - must try to solve this.
Just for info! Rgs Ray
@bruz -
Just change the 'record' expression on the referenced line to '@user.valid?'. I'm working through getting the stateful setup working with the behavior I want too -- you'll probably find that more changes are needed, but that'll get you going.
The solution I found is to simply add this to user.rb
beforecreate :makeactivation_code
It work great.
The problem is that at the creation of a new user, we never using
state :pending, :enter => :makeactivationcode
So activation_code stay always at nil.
Any idea ?
Hi,
I still have the problem with the empty activation code in the email. Have some one a good solution ? Is any update of restful auth coming soon ?
Thanks in advance.
I am confused by logout route, why it is a HTTP GET? Shouldn't it be an HTTP DELETE
i found the problem. a solution is to send out emails directly from the state change methods, and discard the observer all together. for more, see my post at http://harrylove.org/2007/12/17/activation-emails-with-restful-authentication-and-actsas_statemachine#comment-208
I should note that I'm using rails 2.0.1.
Hi, I'm having a problem with the otherwise great restful authentication plugin.
The 'signup, please activate' email that's send out contain an empty activation code. Also the 'activation succeeded' email is send out at the same time (somewhere in UsersController#create), even though the state of the user is still pending.
It seems that User#makeactivationcode is called after UserMailer has send out the signup notification email.
@Gabrielle
I'm using Rails 1.2.6 but here's what worked for me. In the lib>authenticatedsystem.rb there's an action called loginfrombasicauth that contains the 'authenticatewithhttp_basic' Rails 2.0 method. I changed this to:
and had to add the getauthdata method at the end of authenticated_system:
private
hi,
in response to my own post below, I found a more detailed screencast which i found useful in getting me started.
http://www.rubyplus.org/episodes/20-Extended-RESTful-Authentication-Rails-2-App.html
so now i' up and running with it my next question is where is best to post questions about the code itself. I would like to modify it so that a child model is created at the same time as user during signup but i don;t fully understand the create method in users controller.
cheers Nathan
hi can anyone tell me where to find some documentation for this that i might understand. i have checked Ryans screencast although they usually make complete sense to me this one passes me by completely. I need to see an example of it in action. all i have is a company model and a product model company has many products product belong to company. i would like company has many users user belongs to company. then a logged in user can edit company and products.. any similar permutation would suffice as an example, i just need to see the code in action. spent numerous hours now trying to find examples but not found anything.
@raj: add this to your routes.rb
map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'
Railscasts has an excellent screencast about using restful_authentication. I highly recommend: http://www.railscasts.com/episodes/67
This plugin looks good. I am not able to activate the account after the installation. I tried to debug the code using netbeans and It is not able to retrieve the instance of the User.
self.currentuser = params[:activationcode].blank? ? :false : User.findby_activationcode(params[:activation_code])
self.current_user sounds to be nil (Note:- this is a single line in my code.) Please let me know any ideas.
Thank you for all the comments. I have a little problem (may be because i am new to RoR). Everything is OK with the logging and athentication, etc...
but what i want is to put an observer onto a table and write the login of the current user, which made the change, into an audit table. i try to put "include authenticatedSystem" into my observer but i got en error.
Anyone as already got that kind of problem before? thank you
FAILURE IN TESTS 1) Failure: testshouldfailexpiredcookielogin(SessionsControllerTest) [./test/functional/sessionscontroller_test.rb:67]: <false> is not true.
15 tests, 31 assertions, 1 failures, 0 errors
def testshouldfailexpiredcookie_login users(:quentin).remember_me users(:quentin).updateattribute :remembertokenexpiresat, 5.minutes.ago @request.cookies["authtoken"] = cookiefor(:quentin) get :new assert !@controller.send(:logged_in?) end
Don't know if this is the right place for this type of question or not. Please delete if not.
I use this plugin for most projects, so thank you for it. I'm been trying to get my hands around when to create a RESTful resource. Restful Authentication is a good example of this decision. Specifically, would anyone like to share their thoughts on why, for example, this plugin has the activate method for Users instead of an Activation resource (where to activate a user you would post a :create to Activation)? I'm not proposing this plug-in be any different - it works just fine. Just thought it might be a good and very well known example to use on discussion of when to use the constrained set of actions and when not to. Are there any guidelines or is it mostly a judgment call from experience?
Rails2.0 requires you to replace redirectto_url with redirectto.
In the plugin: restfulauthentication/generators/authenticated/templates/authenticatedsystem.rb
In existing apps: RAILSROOT/lib/authenticatedsystem.rb
I wanted user records in my app to have various statuses. Here's how I modified restfulauthentication with actsasstatemachine to accomplish this. I'll call it stateful_authentication http://www.vaporbase.com/postings/stateful_authentication
Using this plugin successfully except . . . it doesn't seem to be persisting sessions to the db. It appears that when I log out, it attempts to destroy the session record in the db, but when I log in I see no attempt to create the session in the db.
No matter what, the sessions table never gets written to.
@durant
Previous message obsolete, I finally found the reason (I had the same bug).
you must put the "map.resources" part in the BEGINNING of the routes.rb!
(The comments say: # The priority is based upon order of creation: first created -> highest priority.)
I'm feeling dumb :)
durant, maybe this note will help:
If you're on rails 1.2.3 you may need to specify the controller name for the session singular resource:
map.resource :session, :controller => 'sessions'
Also, add an observer to config/environment.rb if you chose the --include-activation option config.activerecord.observers = :userobserver # or whatever you named your model
I tried moving the UsersController to Admin::UsersController, and I can get to the /admin/users/new screen, but I get an
undefined constant UsersControlleron the create action. I've hunted around in the code but can't figure out why create is still looking for UsersController instead of Admin::UsersController. Any ideas?Also, has anyone tried using RestfulAuthentication with RoleRequirement?
Here's my take on a 'smart login' (this is a RESTful approach)... I used a partial navlogin.rhtml in my 'shared' folder and call it in my application.rhtml layout: http://pastie.caboo.se/89494
Hello Everyone, I am really new to Rails and when trying to run this plugin after installing it it gives me this error:
ou have a nil object when you didn't expect it! You might have expected an instance of ActiveRecord::Base. The error occurred while evaluating nil.errors
Extracted source (around line #1):
1: <%= errormessagesfor :user %> 2: <% formfor :user, :url => userspath do |f| -%> 3: <p><label for="login">Login</label><br/> 4: <%= f.text_field :login %></p>
Anyone have an idea on how to fix this
Thanks for this plugins, I make some change in authenticated_system.rb to prevent
Session Hijacking :
and :
To add to my previous comment. Immediately after calling
reset_session
you'll need to either have copied the session data to put in to the new session, or issue this call again :
self.current_user = User.authenticate(params[:login], params[:password])
Here is an answer to which version works with rails 1.2.3 (from Jacob Atzen http://www.ruby-forum.com/topic/117043#536293)
I tried this, ran "rake test" and all tests succeeded.
cd [into/rails-root]
svn export -r 2563 http://svn.techno-weenie.net/projects/plugins/restful_authentication/ vendor/plugins/restful_authentication
This version of the plugin should work with Rails 1.2.3.
===
unfortunately, when I try logging in, I still get an error about index not being found.
To strengthen the ramparts against session fixation and hijacking vulnerabilities call reset_session right after the line :
if LoggedIn? reset_session blah blah.....
in the method
'LoginsessionsController.create'
It doesn't solve the problem, but it is simple and the hacker will need to be much more motivated: most hackers are lazy crims who want something for nothing.
Suggestion: Newbies, remember to run "rake db:migrate" (or if that's supposed to be automatic, it didn't happen for me)
Fix: (I'm a newbie, myself, but maybe this fix will earn me some help with my problem below)
in app/views/users/new.rhtml the label tags: label for="login" label for="email" should be: label for="user_login" label for="user_email" etc. so that when you click on the name, the corresponding textfield is selected. At least, this is how input id's area being named for me when I view the page source.
Problem: When I go to "http://localhost:3000/users/new" and fill out the form, I get directed to a page:
Unknown action
No action responded to index
I've tried modifying config/routes.rb with the suggestions below to no avail. It looks like the submit form is generating an "index" action and the UsersController doesn't know what to do with it. What's supposed to happen? Is email supposed to be sent and I'm somehow missing an emailer program?
thanks
note: I'm using Rails version 1.2.3
Which revision of the plugin is suitable for Rails 1.2.3? Trunk has failing tests which are apparently due to an update for edge.
A full working sample application with restfulauthentication + openid_authenication is available at http://www.bencurtis.com/archives/2007/05/openid-sample-application/
I have written a small tutorial showing how to build a basic system using restfulauthentication and openid_authentication. The tutorial is written in spanish, but the code should be pretty understandable. Maybe can be useful for you. The url is http://blog.leugim.com.mx/index.php/2007/04/27/usando-ruby-on-rails-parte-1/
¿Is there a download-able version?. I can't get the plugin because I'm behind a firewall. Thanks!
Can someone point me to a tutorial that explains in a little bit more detail on how to use this? I see so many folks down in the comments section offering suggestions to this plugin that I don't understand the heads or tail of it. Can someone atleast aggregate the changes that are required to make this plugin work?
Thanks
The plugin has been modified since this post (thx to BillSays below) the new syntax for generating the mailer is -
./script/generate authenticated user --include-activation
It seems if you want to use the default activation code and templates you will need to add this to config/routes.rb
map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'
in authenticated.rb there is one instance of redirect_to_url
I had to change to to redirect_to
I guess they took that method out of rails?
Can't generate the mailer either. Here's what I get:
./script/generate authenticated_mailer user Couldn't find 'authenticated_mailer' generator
If you like acts_as_authenicated you'll love restful auth.
I think the --include-activation parameter replaces the separate mailer generator. Though I could be wildly incorrect.
If you are using singular resources, don't forget to change sessionspath to sessionpath wherever it is needed (ie in app/views/session/new.rhtml).
Answering my own questions... :)
Rails 1.2.2 added a concept of "singular resources: http://weblog.rubyonrails.org/2007/2/6/rails-1-2-2-sqlite3-gems-singular-resources
In a nutshell, SessionsController needs to be renamed to SessionController (note singular form), and map.resource(:session) needs tobe used instead of map.resources(:session) (again, note singular form). That should take care of it.
Fyodor 1.2.2 introduced singular resources, if you modify the generated files to match the new convention then it should old work.
eg routes.rb
map.resource :session
sessionscontroller to sessioncontroller
etc...
Looks like Rails 1.2.2 is not happy about this in view: <%= linkto("Log out", sessionpath, :method => :delete) %>
It gives the following error: sessionurl failed to generate from {:controller=>"sessions", :action=>"show"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. contenturl has the following required parameters: ["sessions", :id] - are they all satisifed?
Any suggestions as to how this should be addressed? I obviously do not want to expose current_user id in the URL. I will if I have to, but I would rather not.
Another request for clarification on the authenticated_mailer.
The usercontrollertest functional test fails.
1) Failure: testshouldactivate_user:64 <nil> expected to not be nil.
The relevant code is:
def testshouldactivate_user assert_nil User.authenticate('aaron', 'test') get :activate, :activationcode => users(:aaron).activationcode assertredirectedto '/' assertnotnil flash[:notice] assert_equal users(:aaron), User.authenticate('aaron', 'test') end
Does anyone know why?
Another newbie tip (from a newbie), look in your project's 'lib' folder and open and read the relevant files, ie. authenticated_system.rb. Much of the plugin's callable/useful methods are here.
Couldn't find 'authenticated_mailer' generator. What is wrong here ??
Was attempting to generate the authenticatedmailer, yet the error I recieve is, "Couldn't find 'authenticatedmailer' generator. I checked in my vendor/plugins/restful_authentication/authenticated/templates directory, and obviously the mailer isn't present. Wondering if this file was removed from the svn site? if so, where can I get it?
This is just a comment for newbies out there (like me) that might be trying to use restful authentication in an existing app. When starting your application server (script/server) and you get this kind of error during server startup:
action_controller/routing.rb:406:in
initialize_components': undefined methodfirst' for :users:Symbol (NoMethodError)It means that your environment is set to use an older version of Rails. If you're running Rails 1.2, then open environment.rb in your project and change the RAILSGEMVERSION line to say " RAILSGEMVERSION = '1.2' "
<i>What is "restful" about using cookies for authentication?</i>
In practice, you don't have much choice. The important thing is to treat it as a binary decision - the service either permits or rejects a user based on their cookie, and that's the only effect it has ... what you don't do is change how the service behaves, because that should be determined purely by the action and (optionally) the message.
I really like you plugin, and I am amazed how clean it is implemented.
But I'm quite new to this rails thing, and I have one question: If you provide a bug fix/update for your plugin, how are the users able to implement these changes?
For example, Rudy Lu mentions a bug here in the comments. You could release a new version that fixes the bug, but maybe I have already changed some of the generated files? What is the best practice to import the new code into my app?
Thanks for the tip Rudy Lu!
I found that in loginrequired of authenticatedsystem.rb, the following line: self.current_user ||= User.authenticate(username,passwd) || :false if username && passwd
should be changed to
self.current_user = User.authenticate(username,passwd) || :false if username && passwd
otherwise, http authorization can't work.
In both Rails 1.2RC1 and Edge Rails, I get the following:
No such file or directory - script/../config/../vendor/plugins/restfulauthentication/generators/authenticatedmailer/templates/notifier.rb
Suggestions?
Erik: Looks to me like the auth is done via HTTP headers. Cookies are only (optionally) used for 'remember me' functionality.
What is "restful" about using cookies for authentication?
Just wanted to say that this is a really well thought out and implemented piece of code.
Good job.