I built a Chrome extension that saves web content to my Rails app. Originally I was able to rely on the existing Rails/Devise user session to ensure content was being saved to the right user, as long as the CORS settings were opened up on my API controller (see code below). As long as the user was logged in, AJAX calls to my site from the Chrome extension were being authenticated correctly, no matter what site the extension was being used on.
However, in early 2020 Chrome introduced changes to how they they handle cross-site requests (see here, here, and here). Specifically, a cookie's SameSite attribute would now default to 'Lax' instead of 'None', and so to use a cross-site cookie, the cookie setting would need to be explicitly set to SameSite=None; Secure
.
Rails' own user session cookie does not have the SameSite=None; Secure
settings, and so using the Rails session to authenticate my Chrome extension's request was no longer an option.
My fix was to generate my own API authentication cookie whenever the user logged into the app, which did have the necessary SameSite=None; Secure
applied. I was able to authenticate API calls from my Chrome extension using this cookie, and all was well.
And then in early September 2020 it suddenly stopped working. Rails no longer reads the cross-site cookie from Chrome extension requests. There's no error or warning, the value is just null.
API Controller:
# This gets called when user logs into app:
def set_cross_site_cookie
# NOTE: Won't work in dev because secure = true
cookies[:foo_cookie] = {
value: 'bar',
expires: 1.year.from_now,
same_site: :none, # Required in order to access from Chrome extension on different site
secure: true # Required in order to access from Chrome extension on different site
}
cookie = cookies[:foo_cookie]
render json: {cookie: cookie}
end
# This SHOULD work when called from our Chrome extension:
def get_cross_site_cookie
# Add headers to allow CORS requests
# SEE: http://stackoverflow.com/questions/298745/how-do-i-send-a-cross-domain-post-request-via-javascript
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Request-Method'] = %w{GET POST OPTIONS}.join(",")
cookie = cookies[:foo_cookie]
render json: {cookie: cookie}
end
Rails 5, Rack 2.1
(NOTE: In order to set Rails cookies with option same_site: none
you apparently need need to be on a rack version that's higher than 2.1.0 - SEE: https://github.com/rails/rails/pull/28297#issuecomment-600566751)
Anybody know what happened?