Class: Utopia::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/utopia/session.rb,
lib/utopia/session/lazy_hash.rb,
lib/utopia/session/serialization.rb

Overview

A middleware which provides a secure client-side session storage using a private symmetric encrpytion key.

Defined Under Namespace

Classes: LazyHash, PayloadError, Serialization

Constant Summary collapse

MAXIMUM_SIZE =
1024*32
SECRET_KEY =
'UTOPIA_SESSION_SECRET'.freeze
RACK_SESSION =
"rack.session".freeze
CIPHER_ALGORITHM =
"aes-256-cbc"
DEFAULT_EXPIRES_AFTER =

The session will expire if no requests were made within 24 hours:

3600*24
DEFAULT_UPDATE_TIMEOUT =

At least, the session will be updated every 1 hour:

3600

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, session_name: RACK_SESSION, secret: nil, expires_after: DEFAULT_EXPIRES_AFTER, update_timeout: DEFAULT_UPDATE_TIMEOUT, secure: false, same_site: :lax, maximum_size: MAXIMUM_SIZE, **options) ⇒ Session

Returns a new instance of Session.

Parameters:

  • session_name (String) (defaults to: RACK_SESSION)

    The name of the session cookie.

  • secret (Array) (defaults to: nil)

    The secret text used to generate a symetric encryption key for the coookie data.

  • same_site (Symbol, String) (defaults to: :lax)

    Controls how the cookie is provided to the site.

  • expires_after (String) (defaults to: DEFAULT_EXPIRES_AFTER)

    The cache-control header to set for static content.

  • options (Hash<Symbol,Object>)

    Additional defaults used for generating the cookie by ‘Rack::Utils.set_cookie_header!`.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/utopia/session.rb', line 55

def initialize(app, session_name: RACK_SESSION, secret: nil, expires_after: DEFAULT_EXPIRES_AFTER, update_timeout: DEFAULT_UPDATE_TIMEOUT, secure: false, same_site: :lax, maximum_size: MAXIMUM_SIZE, **options)
	@app = app
	
	@session_name = session_name
	@cookie_name = @session_name + ".encrypted"
	
	if secret.nil? or secret.empty?
		raise ArgumentError, "invalid session secret: #{secret.inspect}"
	end
	
	# This generates a 32-byte key suitable for aes.
	@key = Digest::SHA2.digest(secret)
	
	@expires_after = expires_after
	@update_timeout = update_timeout
	
	@cookie_defaults = {
		domain: nil,
		path: "/",
		
		# The SameSite attribute controls when the cookie is sent to the server, from 3rd parties (None), from requests with external referrers (Lax) or from within the site itself (Strict).
		same_site: same_site,
		
		# The Secure attribute is meant to keep cookie communication limited to encrypted transmission, directing browsers to use cookies only via secure/encrypted connections. However, if a web server sets a cookie with a secure attribute from a non-secure connection, the cookie can still be intercepted when it is sent to the user by man-in-the-middle attacks. Therefore, for maximum security, cookies with the Secure attribute should only be set over a secure connection.
		secure: secure,
		
		# The HttpOnly attribute directs browsers not to expose cookies through channels other than HTTP (and HTTPS) requests. This means that the cookie cannot be accessed via client-side scripting languages (notably JavaScript), and therefore cannot be stolen easily via cross-site scripting (a pervasive attack technique).
		http_only: true,
	}.merge(options)
	
	@serialization = Serialization.new
	@maximum_size = maximum_size
end

Instance Attribute Details

Returns the value of attribute cookie_defaults.



95
96
97
# File 'lib/utopia/session.rb', line 95

def cookie_defaults
  @cookie_defaults
end

Returns the value of attribute cookie_name.



89
90
91
# File 'lib/utopia/session.rb', line 89

def cookie_name
  @cookie_name
end

#expires_afterObject (readonly)

Returns the value of attribute expires_after.



92
93
94
# File 'lib/utopia/session.rb', line 92

def expires_after
  @expires_after
end

#keyObject (readonly)

Returns the value of attribute key.



90
91
92
# File 'lib/utopia/session.rb', line 90

def key
  @key
end

#update_timeoutObject (readonly)

Returns the value of attribute update_timeout.



93
94
95
# File 'lib/utopia/session.rb', line 93

def update_timeout
  @update_timeout
end

Instance Method Details

#call(env) ⇒ Object



109
110
111
112
113
114
115
116
117
# File 'lib/utopia/session.rb', line 109

def call(env)
	session_hash = prepare_session(env)

	status, headers, body = @app.call(env)

	update_session(env, session_hash, headers)

	return [status, headers, body]
end

#freezeObject



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/utopia/session.rb', line 97

def freeze
	return self if frozen?
	
	@cookie_name.freeze
	@key.freeze
	@expires_after.freeze
	@update_timeout.freeze
	@cookie_defaults.freeze
	
	super
end