Login authentication with Ember-cli, Rails and ember-cli-simple-auth-token - ruby-on-rails

I have created an ember-cli project (v 0.1.12) with ember.js (v 1.8.1) and Rails. Than I tried to install:
https://www.npmjs.com/package/ember-cli-simple-auth-token
but when I run the login POST the server responds to me with this error:
Can't verify CSRF token authenticity.
I notice that it sends only username and password, without token. What's going on here?

The short answer is that you can fix that issue in the development setting by disabling CSRF tokens all together. You wouldn't use that in production but you can at least disable it to confirm that the issue gets fixed. In the application_controller.rb file, remove: protect_from_forgery line. Also go to your session_store.rb file in initializers and set:
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :disabled
Once you get things working, you can re-add the protect_from_forgery line as so:
protect_from_forgery with: :null_session

Related

How can I set cookies in a browser from a Rails API app hosted in Heroku running the frontend in a React app hosted in Netlify?

I built an API with Rails --api --db:postgres flags. I built the frontend in another app using React create app.
Rails 6.1.4.1, Ruby 3.0.2p107
The Rails app is deployed in Heroku
The React app, in Netlify
I'm using session cookies to store the user id, and the CSRF Token for additional security (mainly for learning purposes)
Both cookies are set properly and as expected in my local environment, by running the rails server in port localhost:3001 and react in port localhost:3000.
However, after deploying Rails in herokuapp.com and React in netlify.app, although the browser receives the cookies in the response, it doesn't set them.
This is what I see in the browser:
Cookies Response
My Cors.rb file is set properly to allow my the netlify domain to connect to the server, like so my-domain.netlify.app and https://my-domain.netlify.app.
When setting the cookies I have tried every imaginable possible combination of settings, but nothing seems to work. At the moment it looks something like this:
def set_csrf_cookie
cookies['CSRF-TOKEN'] = {
value: form_authenticity_token,
domain: my-app.herokuapp.com,
same_site: :None,
secure: true
}
end
In my cors.rb file I have this code on the first line:
Rails.application.config.action_controller.forgery_protection_origin_check = false
My application.rb file has this config:
config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
My application controller looks something like this:
class ApplicationController < ActionController::API
before_action :set_csrf_cookie
include ActionController::Cookies
include ActionController::RequestForgeryProtection
protect_from_forgery with: :exception
include Response
include ExceptionHandler
def cookie
'ok'
end
private
def set_csrf_cookie
cookies['CSRF-TOKEN'] = {
value: form_authenticity_token,
domain: 'my-app.herokuapp.com',
same_site: :None,
secure: true
}
end
end
I set the cookies by making an API call from my App.js component. The call is made to the path '/', which is routed to application#cookie, which you can see in the application controller code above.
I know I am able to connect with the API because some endpoints that don't require the CSRF Token, are working properly.
I have a feeling that my issue has something to do with the app being hosted in 2 different domains. I also think that it might be a front-end issue, not a back-end issue.
Help from anyone who has successfully done this would be most appreciated.
After much research and a lot of tests, I discovered that the main reason why my cookies were not working is because of the way browsers handle third-party cookies nowadays.
It turns out that Safari and Chrome block them by default. I also missed the fact that cross-site cookies don't actually exist.
I wrote an article explaining how I solved the issue: https://medium.com/#ArturoAlvarezV/use-session-cookies-to-authenticate-a-user-with-a-rails-api-backend-hosted-in-heroku-on-one-domain-f702ddf8c07
Basically, my solution was very simple, remove cross-site-tracking protection from the browsers, using Ruby on Rails gem called 'rails_same_site_cookie', and add this line to my production.rb file:
config.action_dispatch.cookies_same_site_protection = :None
This did the trick for me. This line turned all cookies in rails to SameSite:None and Secure:true by default, including Rail's built-in session cookie.
My developer tools don't show the cookies in my cookies panel, but now they are set and sent with my credentials every time I make a request to the API.

Rails API Mode ApplicationController ignores Rails.application.config.action_controller.allow_forgery_protection

I recently converted an existing Rails 6 application to an API-only application following this guide as well as some helpful information from here.
My frontend application uses session cookies to maintain authentication with the server (with a rack-cors setup) and all that works when I manually test it. Since I'm using a session cookie, I added CSRF protection with a cookie in my application controller like this:
class ApplicationController < ActionController::API
include ActionController::Cookies
include ActionController::RequestForgeryProtection
protect_from_forgery with: :exception
after_action :set_csrf_cookie
def set_csrf_cookie
cookies['X-CSRF-Token'] = form_authenticity_token
end
The problem I'm having is that my rspec tests are all failing with CSRF-related issues. Usually CSRF is disabled in the test environment in rails (as documented here), however I ran rails console -e test the following on both the API app and the old app and got a discrepancy:
Regular rails app:
Rails.application.config.action_controller.allow_forgery_protection
>> false
ApplicationController.allow_forgery_protection
>> false
API mode app:
Rails.application.config.action_controller.allow_forgery_protection
>> false
ApplicationController.allow_forgery_protection
>> true
Sure enough, when I disable CSRF protection completely, the tests start looking better.
Is there anyway to restore this behaviour in a Rails API app?
EDIT: I've also tried the above with a fresh rails app generated by rails new --api and I got the same behaviour.

Rails 6 - InvalidAuthenticityToken on Heroku

I've seen no answers on SO so far that don't answer this without suggesting to just disable it (which I don't want to do).
Locally, everything works, but deployed to producton on Heroku I'm getting InvalidAuthenticityToken.
From everything I can see, everything is set up properly.
Fresh app on Rails 6.0.3.1 (so it's not migrated where the setting may be disabled by default)
RAILS_MASTER_KEY set in Heroku for session
session_store.rb set to Rails.application.config.session_store :cookie_store, key: '__app_session', expire_after: 1.year
csrf_meta_tags in my layout as well as csp_meta_tag
ajax not used, this is a plain form_with. I can see the CSRF tag in dev tools so I know it's in the HTML
I considered it maybe is because of this in ApplicationController:
before_action :authenticate
however it seems that prepend: true is no longer set within the application controller...
I tried overriding it anyway by just adding it (even though it's not there by default and it still doesnt work if I add this above the before_action line)
protect_from_forgery with: :exception, prepend: true
Edit I'll also say the fixed Sidekiq showing forbidden when trying to issue DELETE commands as well (kill job button)
Try adding config.force_ssl = true in your config/environments/production.rb and make sure your SSL is configured properly like you said switching to Full SSL instead of Flexible.

ActionController::InvalidAuthenticityToken Rails 5 / Devise / Audited / PaperTrail gem

Background Details
I am using Devise for authentication to login to a Rails 5 application.
Whenever I bundle either the Audited or Paper Trail gem, when I attempt to #create a new session (via the sign in form - /users/sign_in), I receive the following error:
ActionController::InvalidAuthenticityToken
Environment Details
Ruby 2.3.1
Gems:
rails 5.0.2
devise => 4.2.1
paper_trail => 7.0.1
Steps to Reproduce:
Create Rails 5 application
Add Devise gem
Add Audited or Paper Trail gem
Attempt to login
As it turns out, Devise documentation is quite revealing with regard to this error:
For Rails 5, note that protect_from_forgery is no longer prepended to
the before_action chain, so if you have set authenticate_user before
protect_from_forgery, your request will result in "Can't verify CSRF
token authenticity." To resolve this, either change the order in which
you call them, or use protect_from_forgery prepend: true.
The fix was to change code in my application controller from this:
protect_from_forgery with: :exception
To this:
protect_from_forgery prepend: true
This issue did not manifest itself until I attempted adding Audited or Paper Trail gems.
This happened to me on my development machine. Turns out I was setting
Rails.application.config.session_store
for security purpose in production. And somehow in this code gets run on development mode. And I have to comment out this line and it works fine now.
Rails.application.config.session_store :cookie_store, key: '_my_session', secure: true, same_site: :strict
Another thing to try for anyone running into this is to add the following to your environment configuration file:
config.action_controller.forgery_protection_origin_check = false
For me, production was working correctly but staging and development were not and this fixed it for me.
In my project we have that problem and we can't to override protect_from_forgery.
The solution founded is indicate the github of audited and worked for me.
Put this in gemfile:
gem "audited", github: "collectiveidea/audited"
As mentioned in the documentation.
For Rails 5, note that protect_from_forgery is no longer prepended
to the before_action chain, so if you have set authenticate_user
before protect_from_forgery, your request will result in "Can't verify
CSRF token authenticity." To resolve this, either change the order in
which you call them, or use protect_from_forgery prepend: true.
I have used something like this and it works for me.
class WelcomeController < ::Base
protect_from_forgery with: :exception
before_action :authenticate_model!
end
The solution for me was to manually go to my browser's settings and delete the cache.

problems with sign out, cookies and devise on rails

I have been trying to sign in after signing out on my application using devise but I am having an issue with the cookies I think because I have to refresh my web page in order to sign in again. I tried using activerecord-session_store gem and I follow the steps to configure it. I mean, I installed the gem, I generated the recommended migration on the gem documentation and generated the table using rake db:migrate command, I also changes the session_store.rb file but I feel that I am missing something to make it work since I tried it and the same happens. Please help me if you feel I am missing something or if you have other solution for this problem. Many thanks in advance
You are probably getting a "Can't verify CSRF token authenticity" error. Can you check your server logs?
In your ApplicationController please add the following and check if you get an error.
protect_from_forgery with: :exception

Resources