Class: OpenID::Association
- Inherits:
-
Object
- Object
- OpenID::Association
- Defined in:
- lib/openid/association.rb
Overview
An Association holds the shared secret between a relying party and an OpenID provider.
Constant Summary collapse
- FIELD_ORDER =
[:version, :handle, :secret, :issued, :lifetime, :assoc_type,]
Instance Attribute Summary collapse
-
#assoc_type ⇒ Object
readonly
Returns the value of attribute assoc_type.
-
#handle ⇒ Object
readonly
Returns the value of attribute handle.
-
#issued ⇒ Object
readonly
Returns the value of attribute issued.
-
#lifetime ⇒ Object
readonly
Returns the value of attribute lifetime.
-
#secret ⇒ Object
readonly
Returns the value of attribute secret.
Class Method Summary collapse
-
.deserialize(serialized) ⇒ Object
Load a serialized Association.
-
.from_expires_in(expires_in, handle, secret, assoc_type) ⇒ Object
Create an Association with an issued time of now.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#check_message_signature(message) ⇒ Object
Return whether the message’s signature passes.
-
#expires_in(now = nil) ⇒ Object
The number of seconds until this association expires.
-
#get_message_signature(message) ⇒ Object
Get the signature for this message.
-
#initialize(handle, secret, issued, lifetime, assoc_type) ⇒ Association
constructor
A new instance of Association.
-
#make_pairs(message) ⇒ Object
Generate the list of pairs that form the signed elements of the given message.
-
#serialize ⇒ Object
Serialize the association to a form that’s consistent across JanRain OpenID libraries.
-
#sign(pairs) ⇒ Object
Generate a signature for a sequence of [key, value] pairs.
-
#sign_message(message) ⇒ Object
Add a signature (and a signed list) to a message.
Constructor Details
#initialize(handle, secret, issued, lifetime, assoc_type) ⇒ Association
Returns a new instance of Association.
54 55 56 57 58 59 60 |
# File 'lib/openid/association.rb', line 54 def initialize(handle, secret, issued, lifetime, assoc_type) @handle = handle @secret = secret @issued = issued @lifetime = lifetime @assoc_type = assoc_type end |
Instance Attribute Details
#assoc_type ⇒ Object (readonly)
Returns the value of attribute assoc_type.
21 22 23 |
# File 'lib/openid/association.rb', line 21 def assoc_type @assoc_type end |
#handle ⇒ Object (readonly)
Returns the value of attribute handle.
21 22 23 |
# File 'lib/openid/association.rb', line 21 def handle @handle end |
#issued ⇒ Object (readonly)
Returns the value of attribute issued.
21 22 23 |
# File 'lib/openid/association.rb', line 21 def issued @issued end |
#lifetime ⇒ Object (readonly)
Returns the value of attribute lifetime.
21 22 23 |
# File 'lib/openid/association.rb', line 21 def lifetime @lifetime end |
#secret ⇒ Object (readonly)
Returns the value of attribute secret.
21 22 23 |
# File 'lib/openid/association.rb', line 21 def secret @secret end |
Class Method Details
.deserialize(serialized) ⇒ Object
Load a serialized Association
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/openid/association.rb', line 27 def self.deserialize(serialized) parsed = Util.kv_to_seq(serialized) parsed_fields = parsed.map{|k, v| k.to_sym} if parsed_fields != FIELD_ORDER raise ProtocolError, 'Unexpected fields in serialized association'\ " (Expected #{FIELD_ORDER.inspect}, got #{parsed_fields.inspect})" end version, handle, secret64, issued_s, lifetime_s, assoc_type = parsed.map {|field, value| value} if version != '2' raise ProtocolError, "Attempted to deserialize unsupported version "\ "(#{parsed[0][1].inspect})" end self.new(handle, Util.from_base64(secret64), Time.at(issued_s.to_i), lifetime_s.to_i, assoc_type) end |
.from_expires_in(expires_in, handle, secret, assoc_type) ⇒ Object
Create an Association with an issued time of now
49 50 51 52 |
# File 'lib/openid/association.rb', line 49 def self.from_expires_in(expires_in, handle, secret, assoc_type) issued = Time.now self.new(handle, secret, issued, expires_in, assoc_type) end |
Instance Method Details
#==(other) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/openid/association.rb', line 136 def ==(other) (other.class == self.class and other.handle == self.handle and other.secret == self.secret and # The internals of the time objects seemed to differ # in an opaque way when serializing/unserializing. # I don't think this will be a problem. other.issued.to_i == self.issued.to_i and other.lifetime == self.lifetime and other.assoc_type == self.assoc_type) end |
#check_message_signature(message) ⇒ Object
Return whether the message’s signature passes
122 123 124 125 126 127 128 129 |
# File 'lib/openid/association.rb', line 122 def () = .get_arg(OPENID_NS, 'sig') if .nil? raise ProtocolError, "#{} has no sig." end calculated_sig = () return calculated_sig == end |
#expires_in(now = nil) ⇒ Object
The number of seconds until this association expires
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/openid/association.rb', line 81 def expires_in(now=nil) if now.nil? now = Time.now.to_i else now = now.to_i end time_diff = (issued.to_i + lifetime) - now if time_diff < 0 return 0 else return time_diff end end |
#get_message_signature(message) ⇒ Object
Get the signature for this message
132 133 134 |
# File 'lib/openid/association.rb', line 132 def () Util.to_base64(sign(make_pairs())) end |
#make_pairs(message) ⇒ Object
Generate the list of pairs that form the signed elements of the given message
111 112 113 114 115 116 117 118 119 |
# File 'lib/openid/association.rb', line 111 def make_pairs() signed = .get_arg(OPENID_NS, 'signed') if signed.nil? raise ProtocolError, 'Missing signed list' end signed_fields = signed.split(',', -1) data = .to_post_args signed_fields.map {|field| [field, data.fetch('openid.'+field,'')] } end |
#serialize ⇒ Object
Serialize the association to a form that’s consistent across JanRain OpenID libraries.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/openid/association.rb', line 64 def serialize data = { :version => '2', :handle => handle, :secret => Util.to_base64(secret), :issued => issued.to_i.to_s, :lifetime => lifetime.to_i.to_s, :assoc_type => assoc_type, } Util.assert(data.length == FIELD_ORDER.length) pairs = FIELD_ORDER.map{|field| [field.to_s, data[field]]} return Util.seq_to_kv(pairs, strict=true) end |
#sign(pairs) ⇒ Object
Generate a signature for a sequence of [key, value] pairs
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/openid/association.rb', line 96 def sign(pairs) kv = Util.seq_to_kv(pairs) case assoc_type when 'HMAC-SHA1' CryptUtil.hmac_sha1(@secret, kv) when 'HMAC-SHA256' CryptUtil.hmac_sha256(@secret, kv) else raise ProtocolError, "Association has unknown type: "\ "#{assoc_type.inspect}" end end |
#sign_message(message) ⇒ Object
Add a signature (and a signed list) to a message.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/openid/association.rb', line 151 def () if (.has_key?(OPENID_NS, 'sig') or .has_key?(OPENID_NS, 'signed')) raise ArgumentError, 'Message already has signed list or signature' end extant_handle = .get_arg(OPENID_NS, 'assoc_handle') if extant_handle and extant_handle != self.handle raise ArgumentError, "Message has a different association handle" end = .copy() .set_arg(OPENID_NS, 'assoc_handle', self.handle) = .to_post_args.keys() signed_list = [] .each { |k| if k.starts_with?('openid.') signed_list << k[7..-1] end } signed_list << 'signed' signed_list.sort! .set_arg(OPENID_NS, 'signed', signed_list.join(',')) sig = () .set_arg(OPENID_NS, 'sig', sig) return end |