Controllers
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'
Cookie flags
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.