Devise InvalidAuthenticityToken - ruby-on-rails

I am trying to create an authentication system with devise. When I try to login with a post request, without ajax, it gives me the "ActionController::InvalidAuthenticityToken" Error.
I've seen that this is supposed to be a common bug with devise. I've seen some usual approaches to it, which don't work for me:
To include an csrf token on the html: It is already included in the login site
Include a hackish solution like this: skip_before_action :verify_authenticity_token, if: -> { controller_name.include? 'sessions' }
. Unfortunately this doesn't change a thing. In the original solution I've seen it suggested to include it into Users::SessionsController. I can change whatever I like in this controller or even delete the whole controller and it still works the same.
This is supposed to be a problem with protecting from forgery according to other sources, but I can literally remove it from the application controller and I still have the same error.
class ApplicationController < ActionController::Base
# protect_from_forgery with: :exception
end
I believe that Devise checks the token independently from the rest of my app. This would also explain why it doesn't work even though there is a token at the sign in form. I have no clue what to do about it though.

Related

Rails 6 `protect_from_forgery with: :null_session` not working

In an effort to learn React and using Rails together I am in the process of building a simple "Todo" app. Im using axios to make requests to my rails api within react components.
So far everything was working fine until I made my first POST request. Im pointing to the right place and sending fine params but saw I was getting Can't verify CSRF token authenticity.. Upon further googling it appears that adding:
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
end
Would fix my issue. But despite server restarts/etc... I still receive the same error when sending a POST request. Also adding prepend: true does not help either (as was suggested by another member).
Is there something im missing? This seems like a straightforward problem from what i've read but it doesn't seem to be working for me.
Im on Rails 6.0
if you just want the error to go away, use:
class ApplicationController < ActionController::Base
skip_forgery_protection
end
But if you would like to actually take advantage of the Rails forgery protection, then add an "X-CSRF-Token" header to your post request from React. The value for this header can be retrieved by javascript from the page's head element, in a meta tag included by Rails. For example (using jQuery):
var csrf_token_value = $('meta[name="csrf-token"]').attr('content')

Using token from Simple authentication Token in controller

I am using Simple Authentication token for my APIs in Rails.
As given in the documentation: https://github.com/gonzalo-bulnes/simple_token_authentication:
In my User model, I have added the following line:
acts_as_token_authenticatable
Whenever I login or logout, I am able to get and change the athentication tokens as expected.
What I don't understand is, what is the use of the below line.
acts_as_token_authentication_handler_for User
I have a controller called ProfilesController in which I have added this line. Whether or not I add this line in the controller makes no difference. I am able to call methods in the similar way as I use without adding it.
Can you please explain me what this does?
That is because that gem says this behaviour of incorrect or no credentials is configurable.
What happens when a request is provided with no credentials or
incorrect credentials is highly configurable
For denying access you have to set the fallback
If you have devise set it to fallback: :devise or fallback: :exception in your app/controllers/application_controller.rb

Using devise_token_auth with jsonapi-resources

I am trying to use devise_token_auth with jsonapi-resources. I have it set up where I can create users and sign in, but I cannot figure out how to access a controller that has needs to authenticate a user first. Here is my controller that I am trying to require authentication:
class FriendsController < JSONAPI::ResourceController
include DeviseTokenAuth::Concerns::SetUserByToken
before_action :authenticate_user!
end
When I try localhost:3000/friends, I get a 401 "Authorized users only." error, so I think it works. I think my main problem is Im not sure what to do with the access-token I get when I sign in. I have tried setting it in the header in my request, but still get the same "Authorized users only" error.
Better a late answer than none... devise_token_auth and jsonapi_resources work pretty well for me in a test setup. But, you need to set the request header correctly. It is not enough to transmit the "auth-token" header, you also heave to transmit the "client" token, the "uid" and the "token-type" header as well. Although I'm not entirely sure if the latter is actually required.
Devise token authentication is quite independent of jsonapi-resources. If you can get token authentication working (as explained in this answer, for example: Custom devise api token auth) you can simply extend your controller (or your ApplicationController) with the authentication concern and it should behave as a normal Rails controller would.

Devise and CSRF

I am getting a CSRF Warning in my Rails logs intermittently. I think I have resolved the issue but would like some advice as to whether the solution is sound from a security point of view.
It's a Rails 4 app with Devise application with some Angular JS. Sometimes on a certain page the user session can time out and then we make an AJAX request (though I can see this in normal html requests too it just mainfests itself more regularly in JS) We get a 401 in the logs and can handle from that point. The problem is before that before that 401 we are getting the following message:
WARNING: Can't verify CSRF token authenticity
which is noisy and so I don't know if there is a real attack going on. They're logged out and their token is, I believe, no longer valid.
I believe this is because in Application Controller protect_from_forgery happens before my devise authenticate_user! filter. So:
class ApplicationController < ActionController::Base
protect_from_forgery
etc....
end
Happens before
class MyController < ApplicationController
before_filter :authenticate_user!
def new
end
end
If I change the above to prepend_before_action :authenticate_user! the CSRF message goes away. My question is there a (security) reason to not do this? I haven't seen other people do this so assume they must be getting this message too? It makes sense to me that Devise is one of the very first things that happens in our filter chain but don't see that as common practice.
Thanks in advance :)

How to make sure Rails API is secured from CSRF?

I've been developing Rails app with REST API for access from mobile application.
It works quite well. When user logs in from mobile application, he gets auth_token that he uses in his future requests to API. The issue is that API is also accessible from web by going to path /api/v1/... and because of this, it has to be protected from CSRF.
I have BaseApiController class which inherits from ApplicationController that has protect_from_forgery "enabled". Here's example:
class Api::V1::BaseApiController < ApplicationController
# ...
end
class ApplicationController < ActionController::Base
protect_from_forgery
# ...
end
Now, when I do non-GET requests to my API, with auth_token, my request gets completed successfully, but in the logs I can see the famous WARNING: Can't verify CSRF token authenticity. If I remove protect_from_forgery from my BaseApiController, I don't get any warnings (obviously), but then my API is vulnerable to CSRF attacks (I made a simple HTML form that successfully changes the data across domains when there's no protect_from_forgery).
My question is: How to assure my API stays secure, but also remove the warning when doing non-GET requests?
Here's one of the solutions I've come up with, but it looks more like a hack and executes one extra DB query:
class Api::V1::BaseApiController < ApplicationController
# ...
def verified_request?
super || User.where(authentication_token: params['auth_token']).count > 0
end
end
More details about the project: Rails 3.2.14, Devise, AngularJS. The project's source code can be found here.
You may see people suggest that CSRF is not an issue for API requests (there is no state to begin with, so what is there to hijack anyhow?), so some suggest the following to simply eliminate the warning:
skip_before_filter :verify_authenticity_token, :only => [:your_method]
However, there was some commentary that it is possible to commit CSRF with text/plain using various Flash and Java-based methods. I believe that was the reason for the security patch in rails a while back: http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/
In any event, a good solution that actually checks for an authenticity token can be found here: WARNING: Can't verify CSRF token authenticity rails
It involves actually setting the header in your request.
Good luck!

Resources