Class: GlobalSession::Session::V2
- Defined in:
- lib/global_session/session/v2.rb
Overview
Global session V2 uses msgpack serialization and no compression. Its msgpack structure is an Array with the following format:
[<uuid_string>,
<signing_authority_string>,
<creation_timestamp_integer>,
<expiration_timestamp_integer>,
{<signed_data_hash>},
{<unsigned_data_hash>},
<binary_signature_string>]
The design goal of V2 is to minimize the size of the base64-encoded session state in order to make GlobalSession more amenable to use as a browser cookie.
Limitations of V2 include the following:
-
Some Ruby implementations (e.g. JRuby) lack a msgpack library
-
The sign and verify algorithms, while safe, do not comply fully with PKCS7; they rely on the OpenSSL low-level crypto API instead of using the higher-level EVP (envelope) API.
Constant Summary collapse
- HEADER =
Pattern that matches strings that are probably a V2 session cookie.
/^l9/
Instance Attribute Summary
Attributes inherited from Abstract
#authority, #created_at, #directory, #expired_at, #id, #insecure, #signed
Class Method Summary collapse
-
.decode_cookie(cookie) ⇒ Object
Utility method to decode a cookie; good for console debugging.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Lookup a value by its key.
-
#[]=(key, value) ⇒ Object
Set a value in the global session hash.
-
#dirty? ⇒ Boolean
Determine whether any state has changed since the session was loaded.
-
#each_pair(&block) ⇒ Object
Iterate over each key/value pair.
-
#keys ⇒ Object
Return the keys that are currently present in the global session.
-
#signature_digest ⇒ Object
Return the SHA1 hash of the most recently-computed RSA signature of this session.
-
#to_s ⇒ Object
Serialize the session to a form suitable for use with HTTP cookies.
-
#values ⇒ Object
Return the values that are currently present in the global session.
Methods inherited from Abstract
#delete, #has_key?, #initialize, #inspect, #invalidate!, #new_record?, #renew!, #supports_key?, #to_h, #valid?
Constructor Details
This class inherits a constructor from GlobalSession::Session::Abstract
Class Method Details
.decode_cookie(cookie) ⇒ Object
Utility method to decode a cookie; good for console debugging. This performs no validation or security check of any sort.
Parameters
- cookie(String)
-
well-formed global session cookie
55 56 57 58 |
# File 'lib/global_session/session/v2.rb', line 55 def self.() msgpack = GlobalSession::Encoding::Base64Cookie.load() return GlobalSession::Encoding::Msgpack.load(msgpack) end |
Instance Method Details
#[](key) ⇒ Object
Lookup a value by its key.
Parameters
- key(String)
-
the key
Return
- value(Object)
-
The value associated with
key, or nil ifkeyis not present
141 142 143 144 |
# File 'lib/global_session/session/v2.rb', line 141 def [](key) key = key.to_s #take care of symbol-style keys @signed[key] || @insecure[key] end |
#[]=(key, value) ⇒ Object
Set a value in the global session hash. If the supplied key is denoted as secure by the global session schema, causes a new signature to be computed when the session is next serialized.
Parameters
- key(String)
-
The key to set
- value(Object)
-
The value to set
Return
- value(Object)
-
Always returns the value that was set
Raise
- InvalidSession
-
if the session has been invalidated (and therefore can’t be written to)
- ArgumentError
-
if the configuration doesn’t define the specified key as part of the global session
- NoAuthority
-
if the specified key is secure and the local node is not an authority
- UnserializableType
-
if the specified value can’t be serialized as msgpack
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/global_session/session/v2.rb', line 162 def []=(key, value) key = key.to_s #take care of symbol-style keys raise GlobalSession::InvalidSession unless valid? if @schema_signed.include?(key) @signed[key] = value @dirty_secure = true elsif @schema_insecure.include?(key) @insecure[key] = value @dirty_insecure = true else raise ArgumentError, "Attribute '#{key}' is not specified in global session configuration" end return value end |
#dirty? ⇒ Boolean
Determine whether any state has changed since the session was loaded.
102 103 104 |
# File 'lib/global_session/session/v2.rb', line 102 def dirty? !!(super || @dirty_secure || @dirty_insecure) end |
#each_pair(&block) ⇒ Object
Iterate over each key/value pair
Block
An iterator which will be called with each key/value pair
Return
Returns the value of the last expression evaluated by the block
129 130 131 132 |
# File 'lib/global_session/session/v2.rb', line 129 def each_pair(&block) # :yields: |key, value| @signed.each_pair(&block) @insecure.each_pair(&block) end |
#keys ⇒ Object
Return the keys that are currently present in the global session.
Return
- keys(Array)
-
List of keys contained in the global session
110 111 112 |
# File 'lib/global_session/session/v2.rb', line 110 def keys @signed.keys + @insecure.keys end |
#signature_digest ⇒ Object
Return the SHA1 hash of the most recently-computed RSA signature of this session. This isn’t really intended for the end user; it exists so the Web framework integration code can optimize request speed by caching the most recently verified signature in the local session and avoid re-verifying it on every request.
Return
- digest(String)
-
SHA1 hex-digest of most-recently-computed signature
187 188 189 |
# File 'lib/global_session/session/v2.rb', line 187 def signature_digest @signature ? digest(@signature) : nil end |
#to_s ⇒ Object
Serialize the session to a form suitable for use with HTTP cookies. If any secure attributes have changed since the session was instantiated, compute a fresh RSA signature.
Return
- cookie(String)
-
Base64Cookie-encoded, Msgpack-serialized global session
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/global_session/session/v2.rb', line 66 def to_s if @cookie && !dirty? #use cached cookie if nothing has changed return @cookie end hash = {'id' => @id, 'tc' => @created_at.to_i, 'te' => @expired_at.to_i, 'ds' => @signed} if @signature && !(@dirty_timestamps || @dirty_secure) #use cached signature unless we've changed secure state = @authority else = @directory. hash['a'] = signed_hash = RightSupport::Crypto::SignedHash.new( hash.reject { |k,v| ['dx', 's'].include?(k) }, @directory.private_key, encoding: GlobalSession::Encoding::Msgpack) @signature = signed_hash.sign(@expired_at) end hash['dx'] = @insecure hash['s'] = @signature hash['a'] = array = attribute_hash_to_array(hash) msgpack = GlobalSession::Encoding::Msgpack.dump(array) return GlobalSession::Encoding::Base64Cookie.dump(msgpack) end |
#values ⇒ Object
Return the values that are currently present in the global session.
Return
- values(Array)
-
List of values contained in the global session
118 119 120 |
# File 'lib/global_session/session/v2.rb', line 118 def values @signed.values + @insecure.values end |