{"id":7601,"date":"2015-09-13T12:48:54","date_gmt":"2015-09-13T12:48:54","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2015\/09\/13\/user-authentication-with-grape-and-devise-open-source-projects-intridea-grape\/"},"modified":"2015-09-13T12:48:54","modified_gmt":"2015-09-13T12:48:54","slug":"user-authentication-with-grape-and-devise-open-source-projects-intridea-grape","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2015\/09\/13\/user-authentication-with-grape-and-devise-open-source-projects-intridea-grape\/","title":{"rendered":"User Authentication with Grape and Devise-open source projects intridea\/grape"},"content":{"rendered":"<p>I have difficulties to understand and also properly implement <strong><em>User Authentication<\/em><\/strong> in APIs. In other words, I have serious problem to understand the integration of Grape API with front-end frameworks such as Backbone.js, AngularJS or Ember.js.<\/p>\n<p>I&#8217;m trying to pivot all different approaches and read a lot about that, but Google returns me truly bad resources and it seems to me, like there is no really good article on this topic &#8211; <em>Rails and User authentication with Devise and front-end frameworks<\/em>.<\/p>\n<p>I will describe my current pivot and I hope you can provide me some feedback on my implementation and maybe point me to the right direction.<\/p>\n<p><strong>Current implementation<\/strong><\/p>\n<p>I have backend <strong>Rails REST API<\/strong> with following <strong><em>Gemfile<\/em><\/strong>(I will purposely shorten all file code)<\/p>\n<pre><code>gem 'rails', '4.1.6'\ngem 'mongoid', '~&gt; 4.0.0'\ngem 'devise'\ngem 'grape'\ngem 'rack-cors', :require =&gt; 'rack\/cors'\n<\/code><\/pre>\n<p>My current implementation has only APIs with following Routes(<strong><em>routes.rb<\/em><\/strong>):<\/p>\n<pre><code>api_base      \/api        API::Base\n     GET        \/:version\/posts(.:format)\n     GET        \/:version\/posts\/:id(.:format)\n     POST       \/:version\/posts(.:format)\n     DELETE     \/:version\/posts\/:id(.:format)\n     POST       \/:version\/users\/authenticate(.:format)\n     POST       \/:version\/users\/register(.:format)\n     DELETE     \/:version\/users\/logout(.:format)\n<\/code><\/pre>\n<p>I created have following model <strong><em>user.rb<\/em><\/strong><\/p>\n<pre><code>class User\n  include Mongoid::Document\n  devise :database_authenticatable, :registerable,\n         :recoverable, :rememberable, :trackable, :validatable\n\n  field :email,              type: String, default: \"\"\n  field :encrypted_password, type: String, default: \"\"\n\n  field :authentication_token,  type: String\n\n  before_save :ensure_authentication_token!\n\n  def ensure_authentication_token!\n    self.authentication_token ||= generate_authentication_token\n  end\n\n  private\n\n  def generate_authentication_token\n    loop do\n      token = Devise.friendly_token\n      break token unless User.where(authentication_token: token).first\n    end\n  end   \nend\n<\/code><\/pre>\n<p>In my controllers I created following folder structure: <em>controllers-&gt;api-&gt;v1<\/em> and I have created following shared module Authentication (<strong><em>authentication.rb<\/em><\/strong>)<\/p>\n<pre><code>module API\n  module V1\n    module Authentication\n      extend ActiveSupport::Concern\n\n      included do\n        before do\n           error!(\"401 Unauthorized\", 401) unless authenticated?\n         end\n\n         helpers do\n           def warden\n             env['warden']\n           end\n\n           def authenticated?\n             return true if warden.authenticated?\n             params[:access_token] &amp;&amp; @user = User.find_by(authentication_token: params[:access_token])\n           end\n\n           def current_user\n             warden.user || @user\n           end\n         end\n       end\n     end\n   end\nend\n<\/code><\/pre>\n<p>So every time when I want to ensure, that my resource will be called with Authentication Token, I can simply add this by calling: <code>include API::V1::Authentication<\/code> to the Grape resource:<\/p>\n<pre><code>module API\n  module V1\n    class Posts &lt; Grape::API\n      include API::V1::Defaults\n      include API::V1::Authentication\n<\/code><\/pre>\n<p>Now I have another Grape resource called Users(users.rb) and here I implement methods for authentication, registration and logout.(I think that I mix here apples with pears, and I should extract the login\/logout process to another Grape resource &#8211; Session).<\/p>\n<pre><code>module API\n  module V1\n    class Users &lt; Grape::API\n      include API::V1::Defaults\n\n      resources :users do\n        desc \"Authenticate user and return user object, access token\"\n        params do\n           requires :email, :type =&gt; String, :desc =&gt; \"User email\"\n           requires :password, :type =&gt; String, :desc =&gt; \"User password\"\n         end\n         post 'authenticate' do\n           email = params[:email]\n           password = params[:password]\n\n           if email.nil? or password.nil?\n             error!({:error_code =&gt; 404, :error_message =&gt; \"Invalid email or password.\"}, 401)\n             return\n           end\n\n           user = User.find_by(email: email.downcase)\n           if user.nil?\n              error!({:error_code =&gt; 404, :error_message =&gt; \"Invalid email or password.\"}, 401)\n              return\n           end\n\n           if !user.valid_password?(password)\n              error!({:error_code =&gt; 404, :error_message =&gt; \"Invalid email or password.\"}, 401)\n              return\n           else\n             user.ensure_authentication_token!\n             user.save\n             status(201){status: 'ok', token: user.authentication_token }\n           end\n         end\n\n         desc \"Register user and return user object, access token\"\n         params do\n            requires :first_name, :type =&gt; String, :desc =&gt; \"First Name\"\n            requires :last_name, :type =&gt; String, :desc =&gt; \"Last Name\"\n            requires :email, :type =&gt; String, :desc =&gt; \"Email\"\n            requires :password, :type =&gt; String, :desc =&gt; \"Password\"\n          end\n          post 'register' do\n            user = User.new(\n              first_name: params[:first_name],\n              last_name:  params[:last_name],\n              password:   params[:password],\n              email:      params[:email]\n            )\n\n            if user.valid?\n              user.save\n              return user\n            else\n              error!({:error_code =&gt; 404, :error_message =&gt; \"Invalid email or password.\"}, 401)\n            end\n          end\n\n          desc \"Logout user and return user object, access token\"\n           params do\n              requires :token, :type =&gt; String, :desc =&gt; \"Authenticaiton Token\"\n            end\n            delete 'logout' do\n\n              user = User.find_by(authentication_token: params[:token])\n\n              if !user.nil?\n                user.remove_authentication_token!\n                status(200)\n                {\n                  status: 'ok',\n                  token: user.authentication_token\n                }\n              else\n                error!({:error_code =&gt; 404, :error_message =&gt; \"Invalid token.\"}, 401)\n              end\n            end\n      end\n    end\n  end\nend\n<\/code><\/pre>\n<p>I realize that I present here a ton of code and it might not make sense, but this is what I currently have and I&#8217;m able to use the <code>authentication_token<\/code> for calls against my API which are protected by module <code>Authentication<\/code>.<\/p>\n<p>I feel like this solution is not good, but I really looking for easier way how to achieve user authentication through APIs. I have several questions which I listed below.<\/p>\n<p><strong>Questions<\/strong><\/p>\n<ol>\n<li>Do you think this kind of implementation is dangerous, if so, why? &#8211; I think that it is, because of the usage of one token. Is there a way how to improve this pattern? I&#8217;ve also seen implementation with separate model <code>Token<\/code> which has expiration time, etc. But I think this is almost like reinventing wheel, because for this purpose I can implement OAuth2. I would like to have lighter solution.<\/li>\n<li>It is good practice to create new module for Authentication and include it only into resources where it is needed?<\/li>\n<li>Do you know about any good tutorial on this topic &#8211; implementing Rails + Devise + Grape? Additionally, do you know about any good open-source Rails project, which is implemented this way?<\/li>\n<li>How can I implement it with different approach which is more safer?<\/li>\n<\/ol>\n<p>I apologize for such a long post, but I hope that more people has the same problem and it might help me to find more answers on my questions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have difficulties to understand and also properly implement User Authentication in APIs. In other words, I have serious problem to understand the integration of Grape API with front-end frameworks such as Backbone.js, AngularJS or Ember.js. I&#8217;m trying to pivot all different approaches and read a lot about that, but Google returns me truly bad [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7601","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7601","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=7601"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7601\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=7601"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=7601"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=7601"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}