Class: GlobalSession::Session::V4

Inherits:
Abstract
  • Object
show all
Defined in:
lib/global_session/session/v4.rb

Overview

Version 4 is based on JSON Web Token; in fact, if there is no insecure state, then a V4 session is a JWT. Otherwise, it’s a JWT with a nonstandard fourth component containing the insecure state.

Constant Summary collapse

EXPIRED_AT =
'exp'.freeze
ID =
'id'.freeze
ISSUED_AT =
'iat'.freeze
ISSUER =
'iss'.freeze
NOT_BEFORE =
'nbf'.freeze
HEADER =

Pattern that matches strings that are probably a V4 session cookie.

/^eyJ/

Instance Attribute Summary

Attributes inherited from Abstract

#authority, #created_at, #directory, #expired_at, #id, #insecure, #signed

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Abstract

#[], #[]=, #delete, #dirty?, #each_pair, #has_key?, #initialize, #inspect, #invalidate!, #keys, #new_record?, #renew!, #supports_key?, #to_h, #valid?, #values

Constructor Details

This class inherits a constructor from GlobalSession::Session::Abstract

Class Method Details



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/global_session/session/v4.rb', line 17

def self.decode_cookie(cookie)
  header, payload, sig, insec = cookie.split('.')
  header, payload, insec = [header, payload, insec].
    map { |c| c && RightSupport::Data::Base64URL.decode(c) }.
    map { |j| j && GlobalSession::Encoding::JSON.load(j) }
  sig = sig && RightSupport::Data::Base64URL.decode(sig)
  insec ||= {}

  unless Hash === header && header['typ'] == 'JWT'
    raise GlobalSession::MalformedCookie, "JWT header not present"
  end
  unless Hash === payload
    raise GlobalSession::MalformedCookie, "JWT payload not present"
  end

  [header, payload, sig, insec]
rescue JSON::ParserError => e
  raise GlobalSession::MalformedCookie, e.message
end

Instance Method Details

#to_sString

Serialize the session. If any secure attributes have changed since the session was instantiated, compute a fresh RSA signature.

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/global_session/session/v4.rb', line 41

def to_s
  if @cookie && !dirty?
    # nothing has changed; just return cached cookie
    return @cookie
  end

  unless @insecure.nil? || @insecure.empty?
    insec = GlobalSession::Encoding::JSON.dump(@insecure)
    insec = RightSupport::Data::Base64URL.encode(insec)
  end

  if @signature && !(@dirty_timestamps || @dirty_secure)
    # secure state hasn't changed; reuse JWT piece of cookie
    jwt = @cookie.split('.')[0..2].join('.')
  else
    # secure state has changed; recompute signature & make new JWT
    authority_check

    payload = @signed.dup
    payload[ID] = id
    payload[EXPIRED_AT] = @expired_at.to_i
    payload[ISSUED_AT] = @created_at.to_i
    payload[ISSUER] = @directory.local_authority_name

    sh = RightSupport::Crypto::SignedHash.new(payload, @directory.private_key, envelope: :jwt)
    jwt = sh.to_jwt(@expired_at)
  end

  if insec && !insec.empty?
    return "#{jwt}.#{insec}"
  else
    return jwt
  end
end