Sessions

Kindly borrowed from Sinatra's docs :)

A session is used to keep state during requests. If activated, you have one session hash per user session:

enable :sessions

get '/' do
  "value = #{session[:value].inspect}"
end

get '/:value' do
  session[:value] = params[:value]
end

Note that enable :sessions actually stores all data in a cookie. This might not always be what you want (storing lots of data will increase your traffic, for instance). You can use any Rack session middleware by passing it to the sessions setting:

set :sessions, use: Rack::Session::Pool, config: { same_site: :lax, expire_after: 2592000 }

get '/' do
  "value = #{session[:value].inspect}"
end

get '/:value' do
  session[:value] = params[:value]
end

With use:, cookie options such as same_site and secure go in config:. Rack::Session::Pool keeps sessions in the memory of one process, so with Puma workers, several Falcon processes or several servers, use a store they share.

To improve security, the session data in the cookie is signed with a session secret. A random secret is generated for you by Sinatra. However, since this secret will change with every start of your application, you might want to set the secret yourself, so all your application instances share it:

configure :production do
  set :session_secret, ENV.fetch('SESSION_SECRET')
end

Projects generated with Padrino 0.18.0 or later already read SESSION_SECRET in config/apps.rb, with a fallback value generated with the project for when it isn't set. Don't rely on that committed value in production:

set :session_secret, ENV.fetch('SESSION_SECRET') { '...' } # the generated value

Older projects set only a random one there. The secret must be at least 64 bytes long. Generate your own with padrino rake secret, or:

$ ruby -rsecurerandom -e 'puts SecureRandom.hex(64)'

If you want to configure it further, you may also store a hash with options in the sessions setting:

set :sessions, domain: 'foo.com'

To share your session across other apps on subdomains of foo.com, prefix the domain with a . like this instead:

set :sessions, domain: '.foo.com'

The same hash sets the cookie's SameSite and Secure attributes:

set :sessions, same_site: :lax, secure: true

Use set :sessions in place of enable :sessions, not after it: a later enable :sessions sets the setting back to true and drops the options.

same_site takes :lax, :strict or :none. Apps generated by Padrino use same_site: :lax. Browsers drop a same_site: :none cookie unless it is also secure: true. The cookie is also HttpOnly by default.

secure: true tells the browser to send the cookie only over HTTPS. Rack also skips saving the session when it sees a plain HTTP request, so over HTTP every request starts with an empty session, and logins and CSRF tokens stop working. Turn it on only where the site is served over HTTPS. Apps generated by Padrino turn it on in production:

set :sessions, same_site: :lax, secure: Padrino.env == :production

If a proxy or load balancer handles TLS and talks to the app over HTTP, it must send the X-Forwarded-Proto: https header so that Rack sees the request as HTTPS. A production app served over plain HTTP, such as padrino s -e production on your own machine, needs secure: false.

The apps of a project share one session cookie, so give each of them the same secure: setting: an app without it rewrites the cookie without the flag.

Type to search the guides.