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, 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.

  • 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!.



53
54
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
# File 'lib/utopia/session.rb', line 53

def initialize(app, session_name: RACK_SESSION, secret: nil, expires_after: DEFAULT_EXPIRES_AFTER, update_timeout: DEFAULT_UPDATE_TIMEOUT, secure: false, maximum_size: MAXIMUM_SIZE, **options)
	@app = app
	
	@session_name = session_name
	@cookie_name = @session_name + ".encrypted"
	
	if secret.nil? or secret.empty?
		secret = SecureRandom.hex(32)
		warn "#{self.class} secret is #{secret.inspect}, generating transient secret key!" if $VERBOSE
	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 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.



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

def cookie_defaults
  @cookie_defaults
end

Returns the value of attribute cookie_name.



83
84
85
# File 'lib/utopia/session.rb', line 83

def cookie_name
  @cookie_name
end

#expires_afterObject (readonly)

Returns the value of attribute expires_after.



86
87
88
# File 'lib/utopia/session.rb', line 86

def expires_after
  @expires_after
end

#keyObject (readonly)

Returns the value of attribute key.



84
85
86
# File 'lib/utopia/session.rb', line 84

def key
  @key
end

#update_timeoutObject (readonly)

Returns the value of attribute update_timeout.



87
88
89
# File 'lib/utopia/session.rb', line 87

def update_timeout
  @update_timeout
end

Instance Method Details

#call(env) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/utopia/session.rb', line 103

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



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/utopia/session.rb', line 91

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