class OpenID::Association
An Association holds the shared secret between a relying party and an OpenID provider.
Constants
- FIELD_ORDER
Attributes
assoc_type[R]
handle[R]
issued[R]
lifetime[R]
secret[R]
Public Class Methods
deserialize(serialized)
click to toggle source
Load a serialized Association
# 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)
click to toggle source
Create an Association with an issued time of now
# 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
new(handle, secret, issued, lifetime, assoc_type)
click to toggle source
# 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
Public Instance Methods
==(other)
click to toggle source
# 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)
click to toggle source
Return whether the message's signature passes
# File lib/openid/association.rb, line 122 def check_message_signature(message) message_sig = message.get_arg(OPENID_NS, 'sig') if message_sig.nil? raise ProtocolError, "#{message} has no sig." end calculated_sig = get_message_signature(message) return CryptUtil.const_eq(calculated_sig, message_sig) end
expires_in(now=nil)
click to toggle source
The number of seconds until this association expires
# 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)
click to toggle source
Get the signature for this message
# File lib/openid/association.rb, line 132 def get_message_signature(message) Util.to_base64(sign(make_pairs(message))) end
make_pairs(message)
click to toggle source
Generate the list of pairs that form the signed elements of the given message
# File lib/openid/association.rb, line 111 def make_pairs(message) signed = message.get_arg(OPENID_NS, 'signed') if signed.nil? raise ProtocolError, 'Missing signed list' end signed_fields = signed.split(',', -1) data = message.to_post_args signed_fields.map {|field| [field, data.fetch('openid.'+field,'')] } end
serialize()
click to toggle source
Serialize the association to a form that's consistent across JanRain OpenID libraries.
# 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, true) end
sign(pairs)
click to toggle source
Generate a signature for a sequence of [key, value] pairs
# 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)
click to toggle source
Add a signature (and a signed list) to a message.
# File lib/openid/association.rb, line 151 def sign_message(message) if (message.has_key?(OPENID_NS, 'sig') or message.has_key?(OPENID_NS, 'signed')) raise ArgumentError, 'Message already has signed list or signature' end extant_handle = message.get_arg(OPENID_NS, 'assoc_handle') if extant_handle and extant_handle != self.handle raise ArgumentError, "Message has a different association handle" end signed_message = message.copy() signed_message.set_arg(OPENID_NS, 'assoc_handle', self.handle) message_keys = signed_message.to_post_args.keys() signed_list = [] message_keys.each { |k| if k.start_with?('openid.') signed_list << k[7..-1] end } signed_list << 'signed' signed_list.sort! signed_message.set_arg(OPENID_NS, 'signed', signed_list.join(',')) sig = get_message_signature(signed_message) signed_message.set_arg(OPENID_NS, 'sig', sig) return signed_message end