# 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:

```ruby
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:

```ruby
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:

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

The secret must be at least 64 bytes long. New projects set a random one in
`config/apps.rb`. Generate your own with:

```bash
$ 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:

```ruby
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:

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

## Cookie flags

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

```ruby
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, for example in production:

```ruby
set :sessions, same_site: :lax

configure :production do
  set :sessions, same_site: :lax, secure: true
end
```

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.

