Rails 6.0.2.1 - “sameSite” attribute set to “none” “secure” attribute - ruby-on-rails

Firefox error:
Cookie “_myapp_session” will be soon rejected because it has the
“sameSite” attribute set to “none” or an invalid value, without the
“secure” attribute. To know more about the “sameSite“ attribute, read
https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite
"To fix this, you will have to add the Secure attribute to your SameSite=None cookies."
How do I add the secure attribute into my SameSite=None cookie, when using Rails 6?
I do not want to add a separate gem to accomplish this.This error randomly appeared, I assume there was a browser change. Does rails 6 have a native way to fix this? I read this post,
Thank you

You can configure your session store to use secure cookies in production, just add this to an initializer:
MyApp::Application.config.session_store :cookie_store, key: '_my_app_session', secure: Rails.env.production?
You may already have it on config/initializers/session_store.rb.
Documentation and pertinent issue. This will be fixed in Rails 6.1.

You need this line in your Rails config file:
# Specify cookies SameSite protection level: either :none, :lax, or :strict.
#
# This change is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.1.
Rails.application.config.action_dispatch.cookies_same_site_protection = :lax

Update to rails 6.1 (see documentation here on how to do that)
Add the following line to config/application.rb (see the doc here for details on the cookies_same_site_protection option):
# config/application.rb
...
module YouAppName
class Application < Rails::Application
...
# Specify cookies SameSite protection level: either :none, :lax, or :strict.
# This change is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.1.
# Was not in Rails 6.0. Default in rails 6.1 is :lax, not :strict
config.action_dispatch.cookies_same_site_protection = :strict
...
end
end
This line could also be added to config/environments/development.rb, config/environments/production.rb or to an initializer depending on your needs.

Related

Reading Rails 4.1 session cookie in Rails 6

I’m attempting to strangle a legacy Rails 4.1 application by using a proxy in front of it and sending some requests to a new Rails 6 application.
The Rails 4 application is responsible for user authentication and setting the initial session cookie.
Is there a way to get the Rails 6 application to read/write Rails 4.1 compatible session cookies?
Thanks
I wanted to write an answer here as I recently had to dig through some Rails guts to solve this issue. First, make sure both apps share the same secret_key_base, cookie domain, and cookie key. This will let the apps at least read the same session cookie:
MyApp::Application.config.session_store :cookie_store, {
domain: 'myapp.com', # can omit if they're on the same domain
key: '_myapp_session', # need to be explicit here
expire_after: 60.minutes
}
Then, you need to make sure both apps can read the actual payload. The default cookie serialization is moving to JSON in Rails 7, but any older version will still default to :marshal (which uses the basic Ruby Marshal module). Make sure you're using the same serializer.
Rails.application.config.action_dispatch.cookies_serializer = :marshal
Lastly, if your newer app is Rails 6.2+, be warned that Rails started wrapping all cookie payloads (regardless of serialization method) in a JSON envelope. This envelope can't be opened by Rails 4.2 or older apps. So your session can move from Rails 4.2 -> 6.2, but not back...
Unless you monkeypatch it with a custom deserializer, like so:
class WrappedSerializer
def self.base_serializer
Marshal # or JSON, if you're using :json above
end
def self.load(value)
# if this is a Rails 4-created session, parsing will fail & hit the rescue
json = JSON.parse(value) rescue nil
return base_serializer.load(value) if json.nil? || !json.key?('_rails')
base_serializer.load(Base64.decode64(json.dig('_rails', 'message')))
end
def self.dump(value)
base_serializer.dump(value)
end
end
module ActionDispatch
class Cookies
module SerializedCookieJars
def serializer
WrappedSerializer
end
end
end
end
I should point out that, because this strips the envelope which might contain a custom expiry time, the Rails 5.2+ feature of being able to set custom expiry times will not work for any sessions that transition back to your Rails 4 app. If you use that feature, you could probably find a way change the above serializer to rewrap the payload when it deserializes.

Setting session_id cookie SameSite property in Rails

I am attempting to set the SameSite property in my session's cookie in my Rails 5.0.7.2 application but I am having problems determining where and how to set this up.
It looks like a way of determining the SameSite protection level globally will be introduced in Rails 6.1 see: https://github.com/rails/rails/commit/cd1aeda0a9dc15f09d7bf1b8b59e2ce07946f031. That said, how does one go about setting this in a prior version?
The way SameSite is treated will be changing coming Chrome version 80 and I am attempting to prepare for this, specifically as it relates to:
"Cookies for cross-site usage must specify SameSite=None; Secure to enable inclusion in third party context."
See https://web.dev/samesite-cookie-recipes/ fore more info.
I was able to do this with the secure_headers gem and rails 4.2.11.1, I put the config in an initializer
SecureHeaders::Configuration.default do |config|
config.cookies = {
samesite: {
none: true
}
}
end
https://github.com/twitter/secure_headers/blob/master/docs/cookies.md

Error starting Rails server: "unexpected .."

I set up a Rails app on OpenShift and pulled the default code. When I tried running it, I got the following error:
C:/Development/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `load': C:/HEATH3N/FirstApp/config/initializers/session_store.rb:1: syntax error, unexpected .. (SyntaxError)
../../.openshift/lib/session_store.rb
I'm unclear as to what the problem is. I looked at the problematic file and don't see anything wrong. I found other questions on Stack Overflow asking about another problem with the file (the new hash style isn't supported on older Ruby versions) but I'm using Ruby 2.3 (Rails 4.1.4) and my error is different.
require File.join(Rails.root,'lib','openshift_secret_generator.rb')
# Be sure to restart your server when you modify this file.
# Set token based on intialize_secret function (defined in initializers/secret_generator.rb)
Rails.application.config.session_store :cookie_store, :key => initialize_secret(
:session_store,
'_railsapp_session'
)
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rails generate session_migration")
# RailsApp::Application.config.session_store :active_record_store
Try something like so -
require File.expand_path(‘../lib/openshift_secret_generator.rb‘, __FILE__)
or
require Rails.root.join('lib', 'openshift_secret_generator.rb').to_s
Please do update if either or both work for you.

rails 4 email preview in production

I am using rails 4.1.1 and ActionMailer::Preview for previewing emails. In development environment everything is working excellent.
But in production environment the preview routes are not accessible. I store the previews in test/mailers/previews/
Is is possible to enable them for production?
In addition to this:
config.action_mailer.show_previews = true
you will also need to set
config.consider_all_requests_local = true
in your environment for the preview routes to be accessible. This has other implications as well (see https://stackoverflow.com/a/373135/1599045) so you likely don't want to enable this in production. However, if you have a custom environment that's not development, the combination of those two should get things working.
EDITED TO ADD:
The original question was for rails 4.1.1, which doesn't have config.action_mailer.show_previews available. To get ActionMailer previews working in non-development environments in rails 4.1.1, you need to first add some routes to config/routes.rb (in this case, my environment is named custom):
if Rails.env.custom?
get '/rails/mailers' => "rails/mailers#index"
get '/rails/mailers/*path' => "rails/mailers#preview"
end
Then you need to autoload the libraries needed in your environment's config file (in my case, config/environments/custom.rb):
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil
config.autoload_paths += [config.action_mailer.preview_path]
This seems to perform the same task as config.action_mailer.show_previews does.
As with 4.2, you will still need to adjust the local request configuration as above depending on whether your custom environment is being used locally or on a server.
To do it without opening a big security hole:
production.rb
MyApp::Application.configure do
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/spec/mailer_previews" : nil
config.autoload_paths += [config.action_mailer.preview_path]
routes.append do
get '/rails/mailers' => "rails/mailers#index"
get '/rails/mailers/*path' => "rails/mailers#preview"
end
end
class ::Rails::MailersController
before_filter :authenticate_admin!
def local_request?
true
end
private
def authenticate_admin!
...
end
end
It's possible to enable previews in production by config.action_mailer.show_previews = true as the best answer says.
I just want to add how you can render previews in iframe within your own admin area, eg. in active admin (Rails 5.1)
And also I found out that it is not so hard to write your own email previews administration, and don't use rails standard previews at all. You can then add your own features such as changing preview parameters or Send button to see this email in your phone.
From Rails 4.2 you can use the flag in production.rb (or other custom enviroment):
config.action_mailer.show_previews = true
I haven't found anything similar in Rails 4.1.
Update:
If Rspec used, for example, there will be need to add the path:
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"
Default path is "#{Rails.root}/test/mailers/previews".
And no need to touch config.consider_all_requests_local
Here's what I did for Rails 5.2:
production.rb
config.action_mailer.show_previews = true
config.action_mailer.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/spec/mailers/previews" : nil
class ::Rails::MailersController
include ::ApplicationController::Authorization
before_action :require_admin
end
Assuming your ApplicationController::Authorization module has the code for require_admin. I preferred this approach rather than rewriting my authorization code. Remembering to include the :: in front was tricky, because saying include ApplicationController::... will look within the Rails::MailersController namespace.

Rails I18n validation deprecation warning

I just updated to rails 4.0.2 and I'm getting this warning:
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Is there any security issue in setting it to false?
Important: Make sure your app is not using I18n 0.6.8, it has a bug that prevents the configuration to be set correctly.
Short answer
In order to silence the warning edit the application.rb file and include the following line inside the Rails::Application body
config.i18n.enforce_available_locales = true
The possible values are:
false: if you
want to skip the locale validation
don't care about locales
true: if you
want the application to raise an error if an invalid locale is passed (or)
want to default to the new Rails behaviors (or)
care about locale validation
Note:
The old default behavior corresponds to false, not true.
If you are setting the config.i18n.default_locale configuration or other i18n settings, make sure to do it after setting the config.i18n.enforce_available_locales setting.
If your use third party gems that include I18n features, setting the variable through the Application config object, may not have an effect. In this case, set it directly to I18n using I18n.config.enforce_available_locales.
Caveats
Example
require File.expand_path('../boot', __FILE__)
# ...
module YouApplication
class Application < Rails::Application
# ...
config.i18n.enforce_available_locales = true
# or if one of your gem compete for pre-loading, use
I18n.config.enforce_available_locales = true
# ...
end
end
Long answer
The deprecation warning is now displayed both in Rails 4 (>= 4.0.2) and Rails 3.2 (>= 3.2.14). The reason is explained in this commit.
Enforce available locales
When I18n.config.enforce_available_locales is true we'll raise an
I18n::InvalidLocale exception if the passed locale is unavailable.
The default is set to nil which will display a deprecation error.
If set to false we'll skip enforcing available locales altogether (old behaviour).
This has been implemented in the following methods :
I18n.config.default_locale=
I18n.config.locale=
I18n.translate
I18n.localize
I18n.transliterate
Before this change, if you passed an unsupported locale, Rails would silently switch to it if the locale is valid (i.e. if there is a corresponding locale file in the /config/locales folder), otherwise the locale would default to the config.i18n.default_locale configuration (which defaults to :en).
The new version of the I18n gem, forces developers to be a little bit more conscious of the locale management.
In the future, the behavior will change and if a locale is invalid, the Rails app will raise an error.
In preparation of such change (that may potentially break several applications that until today were relying on silent defaults), the warning is forcing you to explicitly declare which validation you want to perform, during the current transition period.
To restore the previous behavior, simply set the following configuration to false
config.i18n.enforce_available_locales = false
otherwise, set it to true to match the new Rails defaults or if you want to be more rigid on domain validation and avoid switching to the default in case of invalid locale.
config.i18n.enforce_available_locales = true
Caveat
If you are setting the config.i18n.default_locale configuration or using any of the previously mentioned methods (default_locale=, locale=, translate, etc), make sure to do it after setting the config.i18n.enforce_available_locales setting. Otherwise, the deprecation warning will keep on popping up. (Thanks Fábio Batista).
If you use third party gems that include I18n features, setting the variable through may not have effect. In fact, the issue is the same as described in the previous point, just a little bit harder to debug.
This issue is a matter of precedence. When you set the config in your Rails app, the value is not immediately assigned to the I18n gem. Rails stores each config in an internal object, loads the dependencies (Railties and third party gems) and then it passes the configuration to the target classes. If you use a gem (or Rails plugin) that calls any of the I18n methods before the config is assigned to I18n, then you'll get the warning.
In this case, you need to skip the Rails stack and set the config immediately to the I18n gem by calling
I18n.config.enforce_available_locales = true
instead of
config.i18n.enforce_available_locales = true
The issue is easy to prove. Try to generate a new empty Rails app and you will see that setting config.i18n in the application.rb works fine.
If in your app it does not, there is an easy way to debug the culprit. Locate the i18n gem in your system, open the i18n.rb file and edit the method enforce_available_locales! to include the statement puts caller.inspect.
This will cause the method to print the stacktrace whenever invoked. You will be able to determine which gem is calling it by inspecting the stacktrace (in my case it was Authlogic).
["/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/i18n-0.6.9/lib/i18n.rb:150:in `translate'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/i18n/translator.rb:8:in `translate'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/i18n.rb:79:in `translate'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/email.rb:68:in `validates_format_of_email_field_options'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/email.rb:102:in `block in included'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/email.rb:99:in `class_eval'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/email.rb:99:in `included'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/base.rb:37:in `include'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/base.rb:37:in `block in acts_as_authentic'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/base.rb:37:in `each'",
"/Users/weppos/.rvm/gems/ruby-2.0.0-p247#application/gems/authlogic-3.1.0/lib/authlogic/acts_as_authentic/base.rb:37:in `acts_as_authentic'",
"/Users/weppos/Projects/application/app/models/user.rb:8:in `<class:User>'",
"/Users/weppos/Projects/application/app/models/user.rb:1:in `<top (required)>'",
Just for completeness, note that you can also get rid of the warning by setting I18n.enforce_available_locales to true (or false) in config/application.rb:
require File.expand_path('../boot', __FILE__)
.
.
.
module SampleApp
class Application < Rails::Application
.
.
.
I18n.enforce_available_locales = true
.
.
.
end
end
I18n.config.enforce_available_locales = true worked for me in Rails 3.2.16 (I put it in config/application.rb)
Doesn't seem that way - that'd be previous behavior of the way i18n works - new behavior (true) will raise an error when you ask for a locale not implemented/available.
See the commit that added this warning: https://github.com/svenfuchs/i18n/commit/3b6e56e06fd70f6e4507996b017238505e66608c
If you want to care about locales write into appilcation.rb file.
config.i18n.enforce_available_locales = true
You can write false if locale validation and do not care about that.

Resources