lynndylanhurley / lynndylanhurley/devise_token_auth
unable to sign_out user1 and sign_in user2 in 1 call.
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 3.6k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
I use devise_token_auth as authentication for an API-backend. To be able to view what other people would see, i use a header that identifies a user, and should show you the call as if you were that user, if you have the authority to do so (read: you are an admin).
When i used
new_user = User.findByUid request.headers['x-fake-user']
sign_out current_api_user
sign_in new_user
i still got the old user as current_api_user. To note here is that i use both devise and devise_token_auth, both on User, but devise is only for admin login to adminpanel, devise_token_auth is used seperate and without the use_legacy_devise feature because i do not want sessions over multiple calls if used with a token.
as a workaround i extended the SetUserByToken Concern and have overwritten the set_user_by_token method to use this header and log in that user after the admin is authenticated and before he is signed_in. But now the function does not update any more to newer versions. So can this behavior of sign_out (and sign_in) be fixed to create a new session?
for those with the same problem, here is my workaround code untill it is fixed:
module SetUserByTokenAndSwitchUser
extend ActiveSupport::Concern
include DeviseTokenAuth::Concerns::SetUserByToken
# user auth
def set_user_by_token(mapping=nil)
# determine target authentication class
rc = resource_class(mapping)
# no default user defined
return unless rc
#gets the headers names, which was set in the initialize file
uid_name = DeviseTokenAuth.headers_names[:'uid']
access_token_name = DeviseTokenAuth.headers_names[:'access-token']
client_name = DeviseTokenAuth.headers_names[:'client']
# parse header for values necessary for authentication
uid = request.headers[uid_name] || params[uid_name]
@token ||= request.headers[access_token_name] || params[access_token_name]
@client_id ||= request.headers[client_name] || params[client_name]
# client_id isn't required, set to 'default' if absent
@client_id ||= 'default'
# ensure we clear the client_id
if !@token
@client_id = nil
return
end
return false unless @token
# mitigate timing attacks by finding by uid instead of auth token
user = uid && rc.find_by_uid(uid)
if user && user.valid_token?(@token, @client_id)
# sign_in with bypass: true will be deprecated in the next version of Devise
if user.has_role?(:admin) && !request.headers['x-fake-user'].nil?
@admin_user = user
user = rc.find_by_email(request.headers['x-Switch-User'])
bypass_sign_in(user, scope: :user)
else
bypass_sign_in(user, scope: :user)
end
return @resource = user
else
# zero all values previously set values
@client_id = nil
return @resource = nil
end
end
def update_auth_header
if @admin_user && !@admin_user.nil?
@resource = @admin_user
end
super
end
end
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the DeviseTokenAuth SetUserByToken concern and its set_user_by_token and update_auth_header entry points, then reproduce the sign_out/current_api_user/sign_in sequence described in the issue. Done means the requested user becomes current_api_user in the same call while preserving the admin context and token authentication behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100