class Contacts::WindowsLive
Attributes
delegation_token[RW]
token_expires_at[RW]
Public Class Methods
new(options={})
click to toggle source
# File lib/contacts/windows_live.rb, line 53 def initialize(options={}) @token_expires_at = nil @location_id = nil @delegation_token = nil end
Public Instance Methods
authentication_url(target=self.return_url, options={})
click to toggle source
# File lib/contacts/windows_live.rb, line 73 def authentication_url(target=self.return_url, options={}) if force_origin context = target target = force_origin + URI.parse(target).path end url = "https://consent.live.com/Delegation.aspx" query = { 'ps' => 'Contacts.Invite', 'ru' => target, 'pl' => privacy_policy_url, 'app' => app_verifier, } query['appctx'] = context if context "#{url}?#{params_to_query(query)}" end
contacts(options={})
click to toggle source
# File lib/contacts/windows_live.rb, line 113 def contacts(options={}) return nil if @delegation_token.nil? || @token_expires_at < Time.now # TODO: Handle expired token. xml = request_contacts parse_xml(xml) end
forced_redirect_url(params)
click to toggle source
# File lib/contacts/windows_live.rb, line 90 def forced_redirect_url(params) target_origin = params['appctx'] and "#{target_origin}?#{params_to_query(params)}" end
initialize_serialized(data)
click to toggle source
# File lib/contacts/windows_live.rb, line 59 def initialize_serialized(data) @token_expires_at = Time.at(data['token_expires_at'].to_i) @location_id = data['location_id'] @delegation_token = data['delegation_token'] end
serializable_data()
click to toggle source
# File lib/contacts/windows_live.rb, line 65 def serializable_data data = {} data['token_expires_at'] = @token_expires_at.to_i if @token_expires_at data['location_id'] = @location_id if @location_id data['delegation_token'] = @delegation_token if @delegation_token data end
Private Instance Methods
app_verifier()
click to toggle source
# File lib/contacts/windows_live.rb, line 130 def app_verifier token = params_to_query({ 'appid' => application_id, 'ts' => Time.now.to_i, }) token << "&sig=#{CGI.escape(Base64.encode64(sign(token)))}" end
backwards_query_to_params(data)
click to toggle source
Like query_to_params
, but do the unescaping before the splitting on '&' and '=', like Microsoft does it.
# File lib/contacts/windows_live.rb, line 162 def backwards_query_to_params(data) params={} CGI.unescape(data).split(/&/).each do |pair| key, value = *pair.split(/=/) params[key] = value ? value : '' end params end
consent_authentic?(query)
click to toggle source
# File lib/contacts/windows_live.rb, line 152 def consent_authentic?(query) body, encoded_signature = query.split(/&sig=/) signature = Base64.decode64(CGI.unescape(encoded_signature)) sign(body) == signature end
decode_eact(eact)
click to toggle source
# File lib/contacts/windows_live.rb, line 142 def decode_eact(eact) token = Base64.decode64(CGI.unescape(eact)) iv, crypted = token[0...16], token[16..-1] cipher = OpenSSL::Cipher::AES128.new("CBC") cipher.decrypt cipher.iv = iv cipher.key = encryption_key cipher.update(crypted) + cipher.final end
encryption_key()
click to toggle source
# File lib/contacts/windows_live.rb, line 126 def encryption_key OpenSSL::Digest::SHA256.digest("ENCRYPTION#{secret_key}")[0...16] end
parse_xml(xml)
click to toggle source
# File lib/contacts/windows_live.rb, line 179 def parse_xml(xml) document = Nokogiri::XML(xml) document.search('/LiveContacts/Contacts/Contact').map do |contact| email = contact.at('PreferredEmail').inner_text.strip names = [] element = contact.at('Profiles/Personal/FirstName') and names << element.inner_text.strip element = contact.at('Profiles/Personal/LastName') and names << element.inner_text.strip Contact.new(email,names.join(' ')) end end
request_contacts()
click to toggle source
# File lib/contacts/windows_live.rb, line 171 def request_contacts http = Net::HTTP.new('livecontacts.services.live.com', 443) http.use_ssl = true url = "/users/@L@#{@location_id}/rest/invitationsbyemail" authorization = "DelegatedToken dt=\"#{@delegation_token}\"" http.get(url, {"Authorization" => authorization}).body end
sign(token)
click to toggle source
# File lib/contacts/windows_live.rb, line 138 def sign(token) OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, signature_key, token) end
signature_key()
click to toggle source
# File lib/contacts/windows_live.rb, line 122 def signature_key OpenSSL::Digest::SHA256.digest("SIGNATURE#{secret_key}")[0...16] end