Screencast - RestfulAuthentication - 1

Restful Authentication: With an empty project

(Screencasts at the bottom of the page!!)

  1. Try out the plugin in a plain “Hello, World!” app before you adapt your own code. So . . .
    
    rails _2.1.1_ ra
    

    (the “_2.1.1_” is to force the use of Rails 2.1.1, since I now have Rails 2.2.2 on my system.)

  2. Create a test “welcome” controller and edit the index template so we can see something; also remove public/index.html
    
    cd ra
    script/generate controller welcome index
    rm public/index.html
    

    (and edit app/views/welcome/index.html.erb)

  3. Try out your app: script/server, and then browse to http://localhost:3000/welcome — If you like, change the routing so that the default route points to this controller/action.
  4. Now you need to install the plugin. Two ways:

    1. Use script/plugin:
      
      script/plugin install git://github.com/technoweenie/restful-authentication.git
      

      If you get the error message “Plugin not found” AFTER some obvious status messages suggesting that stuff is getting installed, and if you do get files created in vendor/plugins/restful-authentication, ignore that error message! If figure out out to avoid the error message, let me know!

    2. Download the plugin as a ZIP from here:
      
      http://github.com/technoweenie/restful-authentication/tree/master
      

      Now unzip the ZIP download and put a copy in vendor/plugins in your app.

  5. Ensure that the plugin name is restful_authentication

    
         mv vendor/plugins/restful-authentication vendor/plugins/restful_authentication
    

    Once you have done this, there should be a directory restful_authentication in vendor/plugins, and that directory should have files such as CHANGELOG, TODO, and directories such as lib/, generators/, etc.

  6. So that we can set members into “states” (e.g., “suspended”), we are also going to use a new gem called aasm. To get this:

    
    gem sources -a http://gems.github.com
    gem install rubyist-aasm
    
  7. Additionally, we will need a plugin so that we can use GMail has our outgoing mail server. The plugin we are going to use tweaks SMTP to support TLS (HTTPS security). Here’s the command:

    
    script/plugin install http://code.openrain.com/rails/action_mailer_tls/
    
  8. From here on out, the “last word” is the installation instructions on the restful_authentication page. Note that many of the details here are taken directly from that page (for instance, the directive to make sure that the plugin directory is called restful_authentication with an underscore).
  9. Make sure you are in the root of your directory, and do:

    
    script/generate authenticated User Session --aasm
    
  10. Review the output carefully! You will see some instructions for adding lines to your config/routes.rb file. Some of these lines will be added for you. In my cases, after adding the appropriate lines, the start of config/routes.rb looks like this:

    
    map.logout '/logout', :controller => 'sessions', :action => 'destroy'
    map.login '/login', :controller => 'sessions', :action => 'new'
    map.register '/register', :controller => 'users', :action => 'create'
    map.signup '/signup', :controller => 'users', :action => 'new'
    map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate', :activation_code => nil
    map.resources :users, :member => { :suspend => :put, :unsuspend => :put, :purge => :delete }
    map.resource :session
    
  11. Inside the “Rails::Initializer.run do |config|” block in config/environment.rb add

    
    config.active_record.observers = :user_observer
    config.gem 'rubyist-aasm', :lib => 'aasm', :source => 'http://gems.github.com'
    
  12. Also, we will use GMail for our outgoing e-mail. Add this in the same place:

    
        config.action_mailer.smtp_settings = {
          :address        => 'smtp.gmail.com',
          :port           => 587,
          :authentication => :plain,
          :user_name      => 'john.g.norman',
          :password       => 'PASSWORD'
        }
    
  13. In config/environments/development.rb, make sure the e-mail setting are like so:

    
    config.action_mailer.raise_delivery_errors = true
    config.action_mailer.delivery_method = :smtp
    
  14. You should now be able to do

    
    rake db:migrate
    
  15. Review the code that has been created for you - in particular, study the controllers/ and models/ directory. When it comes time to adapt an existing application, we will be refactoring our code so that it will play nice with the generated controller and model for users.

    It is hard to underestimate how important it is to go through these files. For example, if you review controllers/session_controller.rb, you will see this comment and line:

    
    # Be sure to include AuthenticationSystem in Application Controller instead
    include AuthenticatedSystem
    

    (Yes, for the sharp-eyed, it is true that the comment says one thing and the include statement says something else; the include is correct)

  16. Indeed. The authentication system will not be triggered unless you do this! So comment-out the “include” line in SessionController and move the line to ApplicationController (so all of your controllers will get the plugin).
  17. Now, since it says “include AuthenticationSystem” — where does that come from? Look in lib/authenticated_system.rb

    This provides many useful methods to your controllers and views. Review them! They are incredibly useful!

    Notice the comments before login_required — this tells you how to force a login before actions. So we want to add:

    
    before_filter :login_required
    

    to our welcome controller:

    
        class WelcomeController < ApplicationController
          before_filter :login_required
          def index
          end
        end
    
  18. Now look at models/user_mailer.rb

    Where you see YOURSITE replace with localhost:3000

    Replace ADMINEMAIL with your address, e.g., john@7fff.com

  19. Restart your server, and browse to http://localhost:3000/welcome

    Now we are redirected to login! Great. But we need a link to the registration page. Let’s add that. To views/session/new.html.erb add at the bottom:

    
    <%= link_to 'Sign up', :signup %>
    
  20. Try it again . . . you should be able to go through the whole
    signup/login process
    1. Screencast, Part I



      Screencast, Part II





      Viewing 27 Comments

        • ^
        • v
        This page looks like something I remember when I learned visual basics a few years ago but now sadly I don't remember nothing from what I've read above. Maybe this is the reason I applied to Dallas security company. Cause it have nothing to do with this kind of things.
        • ^
        • v
        Great work. I love this Screen Cast. Thank you Soooooo Much.
        • ^
        • v
        I love this screencast and instruction sheet. It's so clear and easy to use, and it worked for me until I changed database types. I had started my project using mysql so that I could make an easy chart of my models using dbvisualizer. I had been happily rolling along until today when I finally switched to sqlite3. Suddenly the authentication system is broken, and user.new silently fails. Any thoughts? Thanks.
        • ^
        • v
        I fixed the problem. thanks
        • ^
        • v
        One thing I should mention is that i hadn't tested user.new for a while, and may not have anything to do with the db switch except for the fact that I lost my user data from the old db.
        • ^
        • v
        Hi all, I'm trying to get this working and running into a Net::SMTPSyntaxError whenever I try to create a new user. I'm still trying to get to the bottom of this but if anyone has any insight I'd appreciate it! Here's the error:

        Net::SMTPSyntaxError in UsersController#create

        501 Syntax error in parameters or arguments

        RAILS_ROOT: c:/development/class-ruby/sandbox/test-rest-auth
        Application Trace | Framework Trace | Full Trace

        c:/ruby/lib/ruby/1.8/net/smtp.rb:680:in `check_response'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:653:in `getok'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:623:in `helo'
        vendor/plugins/action_mailer_tls/lib/smtp_tls.rb:42:in `do_helo'
        vendor/plugins/action_mailer_tls/lib/smtp_tls.rb:15:in `do_start'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:378:in `start'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:316:in `start'
        c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:628:in `perform_delivery_smtp'
        c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `__send__'
        c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `deliver!'
        c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:383:in `method_missing'
        app/models/user_observer.rb:3:in `after_create'
        app/controllers/users_controller.rb:18:in `create'
        • ^
        • v
        P.S. Looking at your settings: It "smells" like you're using a server that does not support TLS. So that would be the wrong port. Are you going after GMail?
        • ^
        • v
        Ana: For restful auth, you need to have your SMTP settings all right. You can change them "globally" by putting them in config/environment.rb, or for a particular environment (development, production, etc.) by putting them in the environment-specific file in config/environments/ -- e.g., config/environments/development.rb. Have you done so? For GMail, those settings look like this:

        config.action_mailer.smtp_settings = {
        :address => 'smtp.gmail.com',
        :port => 587,
        :authentication => :plain,
        :user_name => 'GMAILUSERNAME',
        :password => 'GMAILPASSWORD'
        }

        Additonally, for GMail, you need to support TLS security. To do this, you want to use the right plugin:

        script/plugin install http://code.openrain.com/rails/action_mailer_tls/

        If you are NOT using GMail, note that the standard (non-secured) port for SMTP is: 25. I.e., instead of 587 above. Also, if you're using regular SMTP (not GMail), look again in AWDR.
        • ^
        • v
        Hi John, I followed all the steps in the screencast including installing tls and setting the gmail settings. I've got a stripped down test prog below that still has the same issue. I'm on windows xp if that makes a difference.

        require 'action_mailer'
        require 'vendor\plugins\action_mailer_tls\lib\smtp_tls'
        class MyMailer < ActionMailer::Base
        def message()
        from 'viewsnortheast@gmail.com'
        recipients 'viewsnortheast@gmail.com'
        subject 'this is a test message'
        body 'this is the body'
        end
        end
        ActionMailer::Base.delivery_method = :smtp
        ActionMailer::Base.smtp_settings = {
        :address => 'smtp.gmail.com',
        :port => 587,
        :authentication => :plain,
        :user_name => MYEMAIL,
        :password => MYPASSWORD
        }
        puts MyMailer.create_message()
        MyMailer.deliver_message()
        • ^
        • v
        Works perfectly for me. On my system, I did have to require 'rubygems' at the start, and I changed backwards slashes to forwards to get the smtp_tls.rb require to work.

        Could you paste in the exception trace for the sample program?

        Incidentally, you are showing something that works but that I couldn't find in the documentation: Where did you read that you should sent a String to body? Docs always use a Hash and a template.
        • ^
        • v
        Drat. Good to know that the code works but I begin to fear it is a windows issue!
        Here's the output (I added require 'rubygems' at the start):

        $ ruby mytestmail.rb
        From: viewsnortheast@gmail.com
        To: viewsnortheast@gmail.com
        Subject: this is a test message
        Mime-Version: 1.0
        Content-Type: text/plain; charset=utf-8

        this is the body
        c:/ruby/lib/ruby/1.8/net/smtp.rb:680:in `check_response': 501 Syntax error in parameters or arguments (Net::SMTPSyntaxEr
        ror)
        from c:/ruby/lib/ruby/1.8/net/smtp.rb:653:in `getok'
        from c:/ruby/lib/ruby/1.8/net/smtp.rb:623:in `helo'
        from ./vendor\plugins\action_mailer_tls\lib\smtp_tls.rb:42:in `do_helo'
        from ./vendor\plugins\action_mailer_tls\lib\smtp_tls.rb:15:in `do_start'
        from c:/ruby/lib/ruby/1.8/net/smtp.rb:378:in `start'
        from c:/ruby/lib/ruby/1.8/net/smtp.rb:316:in `start'
        from c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:628:in `perform_delivery_smtp'
        from c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `__send__'
        from c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `deliver!'
        from c:/ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:383:in `method_missing'
        from mytestmail.rb:32


        For using string as the body, I found this tutorial: http://rubybook.ca/2008/07/13/gmail/
        • ^
        • v
        I will try it on Windows tomorrow.

        I sent you an e-mail earlier -- check again for another msg.
        • ^
        • v
        Hey, I solved my problem by adding a couple of options to config.action_mailer.smtp_settings:

        :tls => 'true',
        :domain => 'gmail.com',
        • ^
        • v
        I'm having a similar issue: 530 5.7.0 Must issue a STARTTLS command first. k44sm41710024rnd.1

        C:/Ruby/lib/ruby/1.8/net/smtp.rb:576:in `auth_plain'
        C:/Ruby/lib/ruby/1.8/net/smtp.rb:570:in `__send__'
        C:/Ruby/lib/ruby/1.8/net/smtp.rb:570:in `authenticate'
        C:/Ruby/lib/ruby/1.8/net/smtp.rb:410:in `do_start'
        C:/Ruby/lib/ruby/1.8/net/smtp.rb:377:in `start'
        C:/Ruby/lib/ruby/1.8/net/smtp.rb:315:in `start'
        C:/Ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:628:in `perform_delivery_smtp'
        C:/Ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `__send__'
        C:/Ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:508:in `deliver!'
        C:/Ruby/lib/ruby/gems/1.8/gems/actionmailer-2.1.1/lib/action_mailer/base.rb:383:in `method_missing'
        app/models/user_observer.rb:3:in `after_create'
        app/controllers/users_controller.rb:18:in `create'

        Code from my environment.rb file:
        Rails::Initializer.run do |config|
        config.active_record.observers = :user_observer
        config.gem 'rubyist-aasm', :lib => 'aasm', :source => 'http://gems.github.com'
        config.action_mailer.smtp_settings = {
        :address => 'smtp.gmail.com',
        :port => 587,
        :authentication => :plain,
        :user_name => 'myemail',
        :password => 'mypassword',
        :tls => 'true',
        :domain => 'gmail.com'
        }

        I've tried to reinstall action_mailer_tls but it looks like the website isn't up -- is there another place to get it?
        • ^
        • v
        You can get it from github -- did you restart your server after installing the plugin?

        The error message indicates that you weren't able to establish an SSL connection with gmail.
        • ^
        • v
        Reinstalling the action_mailer_tls plugin did the trick - thanks!
        • ^
        • v
        Very nice! I had been fooling around with this same plugin for possible use in the final project. It works really nicely. Thanks for putting together the screencasts. It cleared up some lingering questions I had.

        Mike
        • ^
        • v
        Glad you like it. Most of the other screencasts out there regarding restful_authentication are broken for various reasons.

        Coming: Another screencast that shows how to get at your RESTful services with authentication -- and how to refactor a bit of your app into RESTful form.
        • ^
        • v
        This is the one that I used: http://www.avnetlabs.com/rails/restful-authenti...

        I had looked at a few and they each were dated and broken.

        I'm looking forward to seeing the next screencast... hoping you could show how to best use the authentication with RESTful clients. In my case, I'm looking to implement "basic authentication" from a service running on a PC. It needs to login and report usage information. I'm using Net::HTTP::Post, and I have it working, but probably could be improved to be more 'Best Practices' like.

        Mike
        • ^
        • v
        Though this worked for me, I am not sure that I could make this work, without following the instructions step by step. There's a lot of configuration, installation, version-matching going on that I am not familiar with at all. There's still a lot of magic. I am wondering if the OPEN ID, which was part of the final project is as complicated.
        I am not sure what the relationship between OPEN ID and the restful authentication.
        If it is that complicated, I probably would not choose this feature in the final project.


        By the way, since I can reuse the same email address when testing, is it safe just to go into the database and
        change the email address of existing user, and hence, when I retry creating a different user, I can reuse my email address.
        • ^
        • v
        A few points:

        1. restful_auth gets you more than just the ability to login: It provides for securing your REST data so that unathorized users can't use your service. Open id alone would not get you that.

        2. All open id is about is having your credentials clearing happen on another server. By this means, you enter an open id into a site that supports it, and then the check for your credentials jumps to your open id provider. If you check out, then it jumps back to your app. So, in a lot of ways, open id is a whole different thing. Since maybe users don't have open id's, it is a terrible idea to support only open id.

        3. You can blend in open id to restful_authentication. I believe there is a screen on this at railscasts.com -- i hcw no idea if the procedure outlined there would work with what I've described in my screencast.

        4. There *is* a lot of magic implementing restful_auth. That is why I provide the screencast. It's hard. On the other hand, authentication is also hard (actually really hard to get right -- cookie handling is just the tip of the iceberg).

        5. I actually think the restful_authentication plugin is pretty awful. Please don't quite me. There are things coming along that will be better.
        • ^
        • v
        script/plugin install http://svn.techno-weenie.net/projects/plugins/r...
        worked better for me
        • ^
        • v
        Found this info: More recent versions of restful_authentication have moved to a different location, git://github.com/technoweenie/restful-authentication.git. Using that version, which has changed slightly will require you to install Git on your computer. For more on Git, see http://git.or.cz/
        • ^
        • v
        As you can see above, I point out that you can download the ZIP of the plugin. You do not need git!
        • ^
        • v
        Can you determine if that version is the latest one? I.e., same version as what is on github?
        • ^
        • v
        I started over with the zip download/renaming method and
        script/generate authenticated User Session --aasm
        worked.
        So the other download I had used may indeed not be a recent enough version.
        • ^
        • v
        The main reason I did the screencast was to make sure that you have a combination of versions of these components that are known to work. I think you mentioned that you are using Rails 2.2? I think Rails 2.2 adds support for TLS, which means that you wouldn't need that extra plugin for that.

        But, really, all bets are off unless you use the versions above. To do it with Rails 2.2 should be pretty easy, but I think a stumbling block would be researching whether or not you need a plugin for special TLS handling. Also, either way (Rails 2.2 TLS or using a special plugin) it is essential that you use the right port in your mail config settings as given in the screencast).

      blog comments powered by Disqus