In previous post we saw how to buil RESTful API using Grape. In this post we will see how to add devise auth token to users and how to use it in Grape API authentication.
Lets see how this can be done assuming you already have devise setup ready.
## Add token_authenticable to devise modules (works with devise versions <=3.2)
In user.rb add :token_authenticatable to the list of devise modules, it should look something like below: <div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>classUser<ActiveRecord::Base
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'># ..code..
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> devise:database_authenticatable,
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> :token_authenticatable,
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> :invitable,
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> :registerable,
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> :recoverable,
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> :rememberable,
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> :trackable,
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> :validatable
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'> attr_accessible:name,:email,:authentication_token
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'> before_save:ensure_authentication_token
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'># ..code..
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'>end</div></div></pre></div>
We need to call save on every instance of user that will ensure authentication token is present for each user. <div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>User.all.each(&:save)</div></div></pre></div>
Secure Grape API using auth token
You need to add below code to the API::Root in-order to add token based authentication. If you are unware of API::Root then please read Building RESTful API using Grape
In below example, We are authenticating user based on two scenarios
- If user is logged on to the web app then use the same session
- If session is not available and auth token is passed then find user based on the token <div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'># lib/api/root.rb
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>moduleAPI
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> classRoot<Grape::API
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> prefix'api'
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> format:json
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> rescue_from:all,:backtrace=>true
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> error_formatter:json,API::ErrorFormatter
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> beforedo
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> error!("401 Unauthorized",401)unlessauthenticated
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'> helpersdo
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'> defwarden
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'> env['warden']
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'> defauthenticated
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'> returntrueifwarden.authenticated?
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'> params[:access_token]&&@user=User.find_by_authentication_token(params[:access_token])
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'> defcurrent_user
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'> warden.user||@user
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='27' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='28' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='29' class='code-highlight-row numbered'><div class='code-highlight-line'> mountAPI::V1::Root
</div></div><div data-line='30' class='code-highlight-row numbered'><div class='code-highlight-line'> mountAPI::V2::Root
</div></div><div data-line='31' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='32' class='code-highlight-row numbered'><div class='code-highlight-line'>end</div></div></pre></div>