I'm using Ember
front-end with Grape
API and to authenticate a page I have something like:
def current_user
return nil if headers['Authorization'].nil?
@current_user ||= User.find_by_authentication_token(
headers['Authorization']
)
end
At the moment I'm using ember-simple-auth
which sends something like as a header:
Token token="n2Rs5tokenLH", email="my@email.com"
Check out the Grape logger:
User Load (38.1ms) SELECT "users".* FROM "users" WHERE "users"."authentication_token" = 'Token token="n2Rs5tokenLH", email="my@email.com"' LIMIT 1
Now in rails I usually use authenticate_or_request_with_http_token
to handle this. and I don't want to handle this manually using stuff like gsub
or regular expressions. What is the best way to handle this in Grape?
Please note that the Grape API is mounted inside a rails project and inside app/api/backend/v1/default.rb
:
module Backend
module V1
module Defaults
extend ActiveSupport::Concern
included do
version 'v1', using: :path
format :json
prefix :api
rescue_from :all do |e|
Backend::Base.logger.error e
end
helpers do
def current_user
return nil if headers['Authorization'].nil?
@current_user ||= User.find_by_authentication_token(
headers['Authorization']
)
end
def authenticate!
error!('401 Unauthorized', 401) unless current_user
end
end
end
end
end
end
Edit:
I just found out that I can use ActionController::HttpAuthentication::Token.token_and_options
to do the job, however I'm not sure how should I include this in Grape
project.
The structure of the app looks like:
⇒ tree app/api
app/api
└── backend
├── base.rb
└── v1
├── defaults.rb
└── ....
I tried to include ActionController::HttpAuthentication::Token
in defaults.rb
something like:
helpers do
include ActionController::HttpAuthentication::Token
def current_user
return nil if headers['Authorization'].nil?
@current_user ||= User.find_by_authentication_token(
token_and_options(headers['Authorization'])
)
end
def authenticate!
error!('401 Unauthorized', 401) unless current_user
end
end
But now I'm getting:
undefined method `authorization' for #<String:0x007ff51cdb85f8>
I had to add a customized token_and_options
function which looks like:
def token_and_options(auth_string)
if header = auth_string.to_s[/^Token (.*)/]
values = $1.split(',').
inject({}) do |memo, value|
value.strip!
key, value = value.split(/\=\"?/)
value.chomp!('"')
value.gsub!(/\\\"/, '"')
memo.update(key => value)
end
values.delete("token")
end
end
And then parse token with something like: token_and_options(headers['Authorization'])