How do I set the session cookie's HttpOnly setting to false? - ruby-on-rails

In Ruby on Rails, how do I set the session cookie's httpOnly setting to false?

In Rails 4, you need to edit config/initializers/session_store.rb
Rails.application.config.session_store(
:cookie_store,
key: '_socializus_session',
httponly: false,
)

This is how i did it with Rails 3:
Testapp::Application.config.session_store :cookie_store, key: '_testapp_session', :domain => :all, :httponly => false

I figured this out. In /config/environment.rb include this code:
config.action_controller.session = {
:httponly => false
}

Rails has it set by default to true.
I don't recommend to change it because it will set you cookies accessable for changing from JS like: document.cookie
In Rails 3+ you can change your cookies configuration from config/initializers/session_store.rb:
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: "_my_application_session", httponly: false

Related

Session's storage and expiration in Rails

I'm new at Ruby/Rails, and I've got some questions about session mechanism in Rails and about sessions as a whole.
I've read that session mechanism in Rails 4 uses cookies as a
default store. Is it true?
As I know, sessions are destroyed after
closing a browser. Can I change time of expiration manually?
Thanks in advance.
Yes, sessions are stored in a cookie by default. If you look under config/initializers/ you will find a session_store.rb file with the following contents.
Appname::Application.config.session_store :cookie_store, key: '_appname_session'
As far as overriding this behaviour, you can create a custom cookie and set its expiration date to the time you want. Generally that's how user sessions are handled when creating authentication. For example:
def sign_in(user)
cookies[:session_token] = { value: user.session_token, expires: 1.day.from_now }
self.current_user = user
end
Then you use that cookie to persist the user session.
you can set timeout using expire_after in initializer
My::Application.config.session_store :active_record_store, {
key: "session_id",
domain: "domain.com",
expire_after: 12.hours,
}
Yes
Yes
Both of these things can be set in config/initializers/session_store.rb. E.g.:
MyApp::Application.config.session_store :cookie_store,
:key => '_my_app_session',
:expire_after => 30.minutes

Sessions never expire in rails 3.2

My sessions seem to never expire, even though I configured my session_store.rb file to have this code:
Barcadia::Application.config.session_store :cookie_store,
:key => '_barcadia_session',
:expire_after => 15.minutes
I want users to have to re-login if they have been idle for more than 15 minutes. I am using rails 3.2 and I've tried both cookie_store and active_record_store... Nothing seems to work.
The only thing i see missing are the brackets:
Barcadia::Application.config.session_store :cookie_store, {
:key => '_barcadia_session',
:expire_after => 15.minutes
}
Some::Application.config.session_store :active_record_store, {
expire_after: 24.hours,
}
this worked for me

With Rails and Devise, how do I set the cookie properties if I'm using ActiveRecord store?

In myapp/config/initializers/session_store.rb, I have the following:
Myapp::Application.config.session_store :cookie_store, :key => '_myapp_session', :domain => :all
The :key option sets the name to use for the cookie, and :domain => :all says that the cookie can be shared across subdomains.
Now I want to move to using ActiveRecord to store the session. If I do this:
Myapp::Application.config.session_store :active_record_store
... although the session is stored in the database, there is still, of course, a cookie. But I no longer have control over its name or scope.
How can I use ActiveRecord store for the session and still specify the cookie name and domain?
Figured it out
It's very simple, actually:
Myapp::Application.config.session_store :active_record_store, :key => '_myapp_session', :domain => :all

Rails 3 additional session configuration options (key, expires_after, secure)

Can someone point out what the new Rails 3.x session configuration options are?
I'm trying to duplicate the same configuration that I have in my Rails 2.3.x application.
This is the configuration that I used in the application:
#environment.rb
config.action_controller.session_store = :active_record_store
config.action_controller.session = {
:key => '_something', #non-secure for development
:secret => 'really long random string'
}
# production.rb - override environment.rb for production
config.action_controller.session = {
:key => '_something_secure',
:secret => 'really long random string',
:expire_after => 60*60,#time in seconds
:secure => true #The session will now not be sent or received on HTTP requests.
}
However, in Rails 3.x, I can only find mention of the following:
AppName::Application.config.session_store :active_record_store
AppName::Application.config.secret_token = 'really long random string'
AppName::Application.config.cookie_secret = 'another really long random string'
Are there other config settings to control the key, expire_after time, and secure option?
Regarding the latter, if "config.force_ssl = true" is set in production.rb, I assume the secure option is no longer required?
Thanks very much!
You now configure the Cookie-based session store through an initializer, probably in config/initializers/session_store.rb. In Rails 3 the session store is a piece of middleware, and the configuration options are passed in with a single call to config.session_store:
Your::Application.config.session_store :cookie_store, :key => '_session'
You can put any extra options you want in the hash with :key, e.g.
Your::Application.config.session_store :cookie_store, {
:key => '_session_id',
:path => '/',
:domain => nil,
:expire_after => nil,
:secure => false,
:httponly => true,
:cookie_only => true
}
(Those are just the standard defaults)
If you force SSL in production then setting secure on the cookie shouldn't really make a difference in practice, but you might want to set it just to be on the safe side...
Your::Application.config.session_store :cookie_store, {
:key => '_session_id',
:secure => Rails.env.production?
}

How can I make cookies secure (https-only) by default in rails?

In a Rails controller, I can set a cookie like this:
cookies[:foo] = "bar"
And specify that the "secure" (https-only) flag be on like this:
cookies[:foo, :secure => true] = "bar"
:secure is false by default. How can I have cookies be secure by default, application-wide?
This is on Rails 2.3.8
There's no need to monkeypatch ActionController/ActionDispatch, and force_ssl has side effects (e.g. when behind an ELB).
The most straightforward way to achieve secure cookies is to modify config/initializers/session_store.rb:
MyApp::Application.config.session_store(
:cookie_store,
key: '_my_app_session',
secure: Rails.env.production?
)
starting with rails 3.1, according to the rails security guide, you can simply set the following in your application.rb:
config.force_ssl = true
this forces the cookie to be sent over https only (and I assume everything else, too).
Thanks #knx, you sent me down the right path. Here's the monkeypatch I came up with, which seems to be working:
class ActionController::Response
def set_cookie_with_security(key, value)
value = { :value => value } if Hash != value.class
value[:secure] = true
set_cookie_without_security(key, value)
end
alias_method_chain :set_cookie, :security
end
What do you think?
Quick and dirty solution: i think it is possible by modifying []= method in action pack cookies module (actionpack/lib/action_controller/cookies.rb)
from:
def []=(name, options)
if options.is_a?(Hash)
options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
options["name"] = name.to_s
else
options = { "name" => name.to_s, "value" => options }
end
set_cookie(options)
end
to:
def []=(name, options)
if options.is_a?(Hash)
options.merge!({:secure => true})
options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options }
options["name"] = name.to_s
else
options = { "name" => name.to_s, "value" => options }
end
set_cookie(options)
end
# session only available over HTTPS
ActionController::Base.session_options[:secure] = true
You should look at the rack-ssl-enforcer gem. I was just looking for a clean answer to this and it solves the problem independent of which version of Rails you're on, plus it's extremely configurable.
You can do this as mentioned in some of the above answers (use secure option in the config/initializers/session_store.rb file):
MyApp::Application.config.session_store :cookie_store, key: '_my_app_session',
secure: Rails.env.production?
which will only secure the session cookie, but other cookies will not be secure.
If you want to secure all the cookies in your Rails app by default, you can use the secure_headers gem. Just add the secure_headers gem to your Gemfile, bundle install the gem and create a config/initializers/secure_headers.rb file with this content:
SecureHeaders::Configuration.default do |config|
config.cookies = {
secure: true, # mark all cookies as "Secure"
}
end
This will make all the cookies secure in your Rails app by default.
You can also add these recommended configurations and set the httponly and samesite options as well:
SecureHeaders::Configuration.default do |config|
config.cookies = {
secure: true, # mark all cookies as "Secure"
httponly: true, # mark all cookies as "HttpOnly"
samesite: {
lax: true # mark all cookies as SameSite=lax
}
}
end

Resources