Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access to current_user variable? #28

Closed
kareemgrant opened this issue Sep 13, 2014 · 19 comments
Closed

Access to current_user variable? #28

kareemgrant opened this issue Sep 13, 2014 · 19 comments

Comments

@kareemgrant
Copy link

I'm using devise_token_auth along with ng-token-auth library for my angular frontend and everything seems to be working well until I try to access the current_user variable to reference the signed in user. I looked at the code and see that you're using @current_user and that works temporarily, but after a few server requests, I lose reference to @current_user and the variable returns nil even though I have successfully logged in. This prevents me from conducting simple authorization checks (for example: does the current_user belong to the requested account?). Is there something that I'm missing?

In a vanilla devise implementation, you would use a before_action :authenticate_user! in your controller to get access to the devise helper methods (current_user, user_signed_in?, etc). However, that is throwing an error as well.

Thanks!

@lynndylanhurley
Copy link
Owner

@kareemgrant - current_user should be available if the request was made using valid credentials. I'll look into this ASAP.

@ghost
Copy link

ghost commented Sep 15, 2014

I've run into this a handful of times recently with plain, old devise; whatever mechanism/pattern devise uses in recent versions to include the helpers app-wide seems to need devise_for :users in routes without a namespace or scope, even if devise_for :users is already in routes but within a scope or namespace. I've never taken the time to figure out why this occurs, nor do I recall ever reading anything in their documentation about this. I just, however, got the helpers working the same way even with devise_token_auth. This is currently working (rails 4.1.6, devise_token_auth 0.1.27, devise 3.2.4):

require 'api_constraints'

Rails.application.routes.draw do
  devise_for :users

  namespace :api, defaults: { format: :json } do
    scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
      mount_devise_token_auth_for 'User', at: '/auth'
    end
  end
end

@lynndylanhurley
Copy link
Owner

@kareemgrant - Can you verify that your controllers include the controller concern describe here? @current_user should be available when valid auth headers are present in all controllers that include this concern.

@kareemgrant
Copy link
Author

@lynndylanhurley yep, i've already added the DeviseTokenAuth::Concerns::SetUserByToken concern to my application_controller.

I'm using the Rails-api gem, which excludes view related modules that come with a vanilla rails implementation - maybe this could be the root of the problem?

I've inspected the @user/@current_user variable in the source code of the gem here and it successfully returns the logged in user. However, when I try to inspect any of those variables outside of the gem (like in my application controller or interior controllers) those values return nil.

@bitzpusher Thanks for the tip, I've tried your advice of adding devise_for :users to my routes file but still not able to maintain access to the current user.

@lynndylanhurley
Copy link
Owner

@kareemgrant - I don't think Rails-api is causing this problem. There are no view-related modules involved in setting the @current_user variable.

Do your controllers all inherit from your ApplicationController? If they do, the class definitions will look like this:

class ExampleController < ApplicationController

If they don't inherit from ApplicationController, then they may look like this:

class ExampleController < ActionController::API

or this:

class ExampleController < ActionController::Base

If the controllers don't inherit from the ApplicationController, then they will not inherit the SetUserByToken concern. Can you confirm that each of your controllers inherit from the ApplicationController?

@kareemgrant
Copy link
Author

@lynndylanhurley my base application controller inherits from the ActionController::API (this is where I add the SetUserByToken concern):

class ApplicationController < ActionController::API

And all of the controllers inside the api/v1 domain inherit from the above ApplicationController:

class Api::V1::UsersController < ApplicationController

@lynndylanhurley
Copy link
Owner

@kareemgrant - it sounds like everything is set up correctly.

You said that you were able to inspect @current_user in the concern. Can you try to inspect @current_user on this line, at the very end of the set_user_by_token method? I just want to make sure that the user's credentials are passing authentication.

@kareemgrant
Copy link
Author

@lynndylanhurley yes, I have access to @current_user on this line.

I made my ApplicationController inherit from ActionController::Base instead of ActionController::API. As a result, I now have access to current_user on my first 2 requests to the server but on any other requests current_user is nil:

For example - after successfully logging in, I make a request to fetch the user object associated with the id from the ng-token-auth response and then I make a request to fetch the account associated with that user. In both of the those requests, I have access to the current_user and the set_user_by_token method is called as a before_action. However, on the next request - where I attempt to pull down data associated with the account, the before_action is not called and I don't have access to the current_user in the controller.

@lynndylanhurley
Copy link
Owner

@kareemgrant - this issue has me scratching my head.

1. Client-side environmental issues

Are the headers actually sent with each request? Using the network tab in developer tools, inspect each request to the API to ensure that the headers (access-token, client, uid) are included.

If they are not included, make sure that the request that you're making to the API matches the apiUrl config option. Someone posted an issue earlier (#36) where they were making requests to /api, and they had set the apiUrl to http://api.example.com/api, and so the client wasn't including the auth credentials for those requests.

2. Server-side environmental issues

Is the problem that the set_user_by_token filter runs, but that @current_user is not set? If so, proceed to step 3.

If the problem is that the set_user_by_token filter isn't being run at all:

  • Are there any other gems that could be conflicting with devise_token_auth?
  • Are you using any other before_filters (devise or otherwise) that could be conflicting with the set_user_by_token filter?

3. Authentication issues

Let's try to rule out authentication failure. In config/initializers/devise_token_auth.rb, set change_headers_on_each_request to false, so that the file looks like this:

DeviseTokenAuth.setup do |config|
  config.change_headers_on_each_request = true
end

Make sure to restart your server after making this change.

If this works, then the problem is related to token handling.

Are you making all of the requests from the same browser tab? The auth headers are changed with each request by default. Problems may arise if the auth token isn't kept current. This may happen if requests are made from different tabs within the same browser.

@kareemgrant
Copy link
Author

@lynndylanhurley I went ahead and created a barebones app (using angular with ng-token-auth on the frontend) to determine if the issue was rooted in something quirky with my setup.

Using a vanilla rails implementation (no rails-api) I was able to authenticate with the server and get reference the current_user on each subsequent request. So it seems like the issue is related to my implementation. I'll go back to my original app and follow the troubleshooting steps you recently recommended.

@lynndylanhurley
Copy link
Owner

@kareemgrant - thanks for the update. Let me know if you ever figure this one out.

@smarquez1
Copy link

The same thing is happening to me when trying to post a picture using Content-Type:multipart/form-data;

As you can see in my request, the headers are NOT included:

Request URL:http://localhost:9000/api/users/update_image
Request Headers
Provisional headers are shown
Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryfBjBo49Bum6lfU0Z
If-Modified-Since:0
Origin:http://localhost:9000
Referer:http://localhost:9000/users/profile
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id:A1826156-A00D-AE23-B52C-E648E2C68395
X-XSRF-TOKEN:z9Yr5B38MXm7ZVH9IXmQBglD5o6o1U3B1M7EvoWwEYQ=
Request Payload
------WebKitFormBoundaryfBjBo49Bum6lfU0Z
Content-Disposition: form-data; name="file"; filename="sunset.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryfBjBo49Bum6lfU0Z--

@lynndylanhurley
Copy link
Owner

@kareemgrant - I pushed an update last night that provides access to current_user, user_signed_in?, and authenticate_user!. Documentation here. Use devise_token_auth version 0.1.28.beta8 and ng-token-auth version 0.0.22-beta7 for these features.

@smarquez1 - Is this only when uploading files?

@smarquez1
Copy link

@lynndylanhurley - Yes, otherwise it works correctly for me. Updated this morning from github.

@lynndylanhurley
Copy link
Owner

@smarquez1 - let's continue this on lynndylanhurley/ng-token-auth#41

@edymerchk
Copy link
Contributor

@kareemgrant did you find what was the issue?? I'm having a similar issue with rails-api

@aarmel-sw
Copy link

I had this same issue. Its how it creates the current user. If you are using the namespace V1. it will actually create current_v1_user instead of current_user.

(at least with rails 5 beta 3 api option)
If you DONT put 'devise_for :users' below you will have the issue discussed.

Same goes for the other functions :authenticate_v1_user!

Rails.application.routes.draw do
  devise_for :users
  namespace :v1 do
    mount_devise_token_auth_for 'User', at: 'auth'
    resources :beer 
  end
end

Hope that helps.

GEMFILE
devise (4.0.0.rc1)
bcrypt (> 3.0)
orm_adapter (
> 0.1)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
devise_token_auth (0.1.37)
devise (> 3.5.2, < 4.1)
rails (< 6)

@ImDineshSaini
Copy link

How to pass token in header as it is not working in Rails 5

@Samuelodan
Copy link

Thank you, @aarmel-sw . I thought it was weird that Rails was suggesting I use current_v1_user and authenticate_v1_user! in the error when I had that Namespace.

I didn't think that was supposed to be happening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants