{"id":598,"date":"2011-11-27T02:00:28","date_gmt":"2011-11-27T02:00:28","guid":{"rendered":"http:\/\/41j.com\/blog\/?p=598"},"modified":"2011-11-27T02:01:27","modified_gmt":"2011-11-27T02:01:27","slug":"adding-user-authentication-to-a-ruby-on-the-rails-application","status":"publish","type":"post","link":"https:\/\/41j.com\/blog\/2011\/11\/adding-user-authentication-to-a-ruby-on-the-rails-application\/","title":{"rendered":"Adding User Authentication to a Ruby on the Rails Application"},"content":{"rendered":"<p>Adding User authentication to a Ruby on the rails app. This follows the method discussed in &#8220;Agile Web Development with Rails&#8221;. Some of the example code is copied from there.<\/p>\n<p>0. Create user database:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nrails generate scaffold User name:string password_digest:string\r\nrake db:migrate\r\n<\/pre>\n<p>1. Edit app\/models\/user.rb such that it reads:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nclass User &lt; ActiveRecord::Base\r\n  validates :name, presence: true, uniqueness: true\r\n  has_secure_password # This makes the password a digest and forces you to enter it twice.\r\nend\r\n<\/pre>\n<p>2. add bcrypt to the gemfile, edit Gemfile:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\ngem 'bcrypt-ruby'\r\n<\/pre>\n<p>You may need to run &#8220;bundle install&#8221;.<\/p>\n<p>3. Edit the user edit form to add password confirmation:<\/p>\n<p>app\/views\/users\/_form.html.erb so that it reads as follows:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n&lt;%= form_for(@user) do |f| %&gt;\r\n  &lt;% if @user.errors.any? %&gt;\r\n    &lt;div id=&quot;error_explanation&quot;&gt;\r\n      &lt;h2&gt;&lt;%= pluralize(@user.errors.count, &quot;error&quot;) %&gt; prohibited this user from being saved:&lt;\/h2&gt;\r\n\r\n      &lt;ul&gt;\r\n      &lt;% @user.errors.full_messages.each do |msg| %&gt;\r\n        &lt;li&gt;&lt;%= msg %&gt;&lt;\/li&gt;\r\n      &lt;% end %&gt;\r\n      &lt;\/ul&gt;\r\n    &lt;\/div&gt;\r\n  &lt;% end %&gt;\r\n\r\n  &lt;fieldset&gt;\r\n\r\n  &lt;div class=&quot;field&quot;&gt;\r\n    &lt;%= f.label :name %&gt;&lt;br \/&gt;\r\n    &lt;%= f.text_field :name %&gt;\r\n  &lt;\/div&gt;\r\n  &lt;div class=&quot;field&quot;&gt;\r\n    &lt;%= f.label :password, 'Password' %&gt;&lt;br \/&gt;\r\n    &lt;%= f.password_field :password %&gt;\r\n  &lt;\/div&gt;\r\n\r\n  &lt;div&gt;\r\n    &lt;%= f.label :password_confirmation, 'Confirm' %&gt;:\r\n    &lt;%= f.password_field :password_confirmation %&gt;\r\n  &lt;\/div&gt;\r\n\r\n  &lt;div class=&quot;actions&quot;&gt;\r\n    &lt;%= f.submit %&gt;\r\n  &lt;\/div&gt;\r\n\r\n  &lt;\/fieldset&gt;\r\n&lt;% end %&gt;\r\n<\/pre>\n<p>4. Create session controller&#8230;<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nrails generate controller Sessions new create destroy\r\n<\/pre>\n<p>Edit: app\/controllers\/sessions_controller.rb<\/p>\n<p>Should look like this following edits:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nclass SessionsController &lt; ApplicationController\r\n  skip_before_filter :authorize\r\n\r\n  def new\r\n  end\r\n\r\n  def create\r\n    user = User.find_by_name(params&#x5B;:name])\r\n    if user and user.authenticate(params&#x5B;:password])\r\n      session&#x5B;:user_id] = user.id\r\n      #redirect_to admin_url # use this to redirect the user somewhere after login\r\n    else\r\n      redirect_to login_url, alert: &quot;Invalid user\/password combination&quot;\r\n    end\r\n  end\r\n\r\n  def destroy\r\n    session&#x5B;:user_id] = nil\r\n  end\r\n\r\nend\r\n<\/pre>\n<p>You should open localhost:3000\/users at this point and create a user. We&#8217;ll be adding authentication next and you will need at least one user to be able to login and create more.<\/p>\n<p>5. Create the login page.<\/p>\n<p>Edit app\/views\/sessions\/new.html.erb to read:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;div class=&quot;depot_form&quot; &gt;\r\n&lt;% if flash&#x5B;:alert] %&gt;\r\n&lt;p id=&quot;notice&quot; &gt;&lt;%= flash&#x5B;:alert] %&gt;&lt;\/p&gt;\r\n&lt;% end %&gt;\r\n\r\n&lt;%= form_tag do %&gt;\r\n&lt;fieldset&gt;\r\n&lt;legend&gt;Please Log In&lt;\/legend&gt;\r\n\r\n&lt;div&gt;\r\n&lt;label for=&quot;name&quot; &gt;Name:&lt;\/label&gt;\r\n&lt;%= text_field_tag :name, params&#x5B;:name] %&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;div&gt;\r\n&lt;label for=&quot;password&quot; &gt;Password:&lt;\/label&gt;\r\n&lt;%= password_field_tag :password, params&#x5B;:password] %&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;div&gt;\r\n&lt;%= submit_tag &quot;Login&quot; %&gt;\r\n&lt;\/div&gt;\r\n&lt;\/fieldset&gt;\r\n&lt;% end %&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>Edit the route controller:<\/p>\n<p>config\/routes.rb remove:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\n  get &quot;sessions\/new&quot;\r\n\r\n  get &quot;sessions\/create&quot;\r\n\r\n  get &quot;sessions\/destroy&quot;\r\n<\/pre>\n<p>add:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\n  controller :sessions do\r\n    get 'login' =&gt; :new\r\n    post 'login' =&gt; :create\r\n    delete 'logout' =&gt; :destroy\r\n  end\r\n<\/pre>\n<p>6. Now we need to add a &#8220;filter&#8221; to provide for authenication:<\/p>\n<p>edit app\/controllers\/application_controller.rb<\/p>\n<p>It should read as follows:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nclass ApplicationController &lt; ActionController::Base\r\n  protect_from_forgery\r\n\r\n  before_filter :authorize\r\n\r\n  # ...\r\n\r\n  protected\r\n\r\n  def authorize\r\n    unless User.find_by_id(session&#x5B;:user_id])\r\n      redirect_to login_url, notice: &quot;Please log in&quot;\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>7. You&#8217;ll need to skip authorisation for all controllers that don&#8217;t need a login.<\/p>\n<p>The following with skip authorisation for all methods in a controller add the following after the beginning of the class definiton:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nskip_before_filter :authorize\r\n<\/pre>\n<p>For particular methods:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\nskip_before_filter :authorize, only: &#x5B;:create, :update, :destroy]\r\n<\/pre>\n<p>8. Logoff code:<\/p>\n<p>Add the following on pages where you want a logoff button:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\n&lt;% if session&#x5B;:user_id] %&gt;\r\n&lt;%= button_to 'Logout', logout_path, method: :delete %&gt;\r\n&lt;% end %&gt;\r\n&lt;\/div&gt;\r\n&lt;div id=&quot;main&quot; &gt;\r\n&lt;%= yield %&gt;\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Adding User authentication to a Ruby on the rails app. This follows the method discussed in &#8220;Agile Web Development with Rails&#8221;. Some of the example code is copied from there. 0. Create user database: rails generate scaffold User name:string password_digest:string rake db:migrate 1. Edit app\/models\/user.rb such that it reads: class User &lt; ActiveRecord::Base validates :name, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-598","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1RRoU-9E","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/comments?post=598"}],"version-history":[{"count":2,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/598\/revisions"}],"predecessor-version":[{"id":600,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/598\/revisions\/600"}],"wp:attachment":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/media?parent=598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/categories?post=598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/tags?post=598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}