Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in cookie content using Sinatra session & Rack::Session::EncryptedCookie

I'm learning Sinatra framework & developing a login system. I came across two ways of using cookies.

A simple Sinatra inbuilt way:

enable :sessions
set :session_secret, 'random-key'

This approach produces following cookie content while logged in (used session.inspect to get the output):

{"session_id"=>"6be0b9a31831604ba51114d265ba952482e0b2da6ced6c54e15ebe7f212858ca", 
"tracking"=>{"HTTP_USER_AGENT"=>"b8c1e8f89eeaea0b825bed0d811f0c7678e98c74", 
"HTTP_ACCEPT_ENCODING"=>"a0bfc876d68fe7aea700da5ea8925abac6f2f794", 
"HTTP_ACCEPT_LANGUAGE"=>"dd065ed263c67d799f943ab6c39b55c5e008cbb5"}, 
"csrf"=>"b480324f510e4f391d15cee8236a8fb74a5aaa5ce2f9ad38e4dbb025a823b16e",    
"name"=>"john"}

Another approach is using an encrypted cookie :

require 'sinatra'
require 'encrypted_cookie'

use Rack::Session::EncryptedCookie, :secret => "random-key"

But this approach produces following cookie content while logged in (used session.inspect here too):

{:name=>"john"}

Why enable :sessions is creating such a big cookie with all that information & why is it required (especially those HTTP_... parts?) Because Rack::Session::EncryptedCookie isn't generating any of it.

Do you think that using enable :sessions should be preferred because it has csrf token & session id? Or do you think that Rack::Session::EncryptedCookie is enough since it is encrypted?

I have following versions of gems installed :

encrypted_cookie (0.0.4)
rack (1.5.2)
rack_csrf (2.4.0)
sinatra (1.4.3)
thin (1.5.1)

Please tell me if you need more information...

like image 722
Rahul Avatar asked Nov 13 '22 02:11

Rahul


1 Answers

Because Sinatra will use rack-protection middleware when you enable :sessions. It makes cookie bigger but more secure.

Relevant snippet:

def setup_default_middleware(builder)
  builder.use ExtendedRack
  builder.use ShowExceptions       if show_exceptions?
  builder.use Rack::MethodOverride if method_override?
  builder.use Rack::Head
  setup_logging    builder
  setup_sessions   builder
  setup_protection builder
end

def setup_sessions(builder)
  return unless sessions?
  options = {}
  options[:secret] = session_secret if session_secret?
  options.merge! sessions.to_hash if sessions.respond_to? :to_hash
  builder.use session_store, options
end

def setup_protection(builder)
  return unless protection?
  options = Hash === protection ? protection.dup : {}
  options = {
    img_src:  "'self' data:",
    font_src: "'self'"
  }.merge options

  protect_session = options.fetch(:session) { sessions? }
  options[:without_session] = !protect_session

  options[:reaction] ||= :drop_session

  builder.use Rack::Protection, options
end
  • sessions? returns true if you enable :sessions
  • session_store is Rack::Session::Cookie by default

The difference between Rack::Session::EncryptedCookie

That is, if you want to use Rack::Session::EncryptedCookie with rack-production, it can be easily done by:

enable :sessions
set :session_store, Rack::Session::EncryptedCookie

FYI, since encrypted_cookie is lack of some features (secret rotation, custom serializer, etc) and no longer under maintenance, I made another one to replace it.

Hope it helps.

like image 81
Weihang Jian Avatar answered Nov 15 '22 04:11

Weihang Jian