ben tedder : code things

Solving 'Authorized Users Only' with Rails 5 API and Devise Token Auth

I have a RAILS 5 API setup to handle authentication and basic endpoints. I was able to login and move around the app, but any time I tried to access an endpoint that had before_action :authenticate_user! I was getting the error 'Authorized users only.'

After searching and searching I ran across a few things. First, there was this thread: https://github.com/lynndylanhurley/devisetokenauth/issues/74

I tried several of those things, and they didn't work. Turns out that cookies are turned off by default in Rails 5, so you can simply add the following to your application.rb file:

  config.middleware.use ActionDispatch::Cookies
  config.middleware.use ActionDispatch::Session::CookieStore

Once those two lines are added, check out @dominicwong617's answer and change any reference to authenticate_user! to authenticate_current_user.

All of that worked for me. I'm not sure how I feel about adding cookie support to the Rails 5 API...seems to kind of go against the point. But this works for now. Refactoring may be in my future.

Here's the full code in Application Controller:

class ApplicationController < ActionController::API
  include DeviseTokenAuth::Concerns::SetUserByToken
  include ActionController::Cookies

  def authenticate_current_user
    head :unauthorized if get_current_user.nil?
  end

  def get_current_user
    return nil unless cookies[:auth_headers]
    auth_headers = JSON.parse cookies[:auth_headers]

    expiration_datetime = DateTime.strptime(auth_headers['expiry'], '%s')
    current_user = User.find_by(uid: auth_headers['uid'])

    if current_user &&
       current_user.tokens.has_key?(auth_headers['client']) &&
       expiration_datetime > DateTime.now

       @current_user = current_user
    end

    @current_user
  end
end