module Jabber module PubSub # Jabber::Stream helper that will transparently sign PubSub requests module OAuthPubSubStreamHelper attr_accessor :pubsubjid, :oauth_consumer, :oauth_token, :oauth_options # enhanced #send_with_id method that signs stanzas def send_with_id(iq) if iq.first_element("pubsub") oauth = OAuthServiceHelper.create_oauth_node(self.jid, self.pubsubjid, self.oauth_consumer, self.oauth_token, self.oauth_options) iq.pubsub.add(oauth) end super(iq) end end # PubSub service helper for use with OAuth-authenticated nodes class OAuthServiceHelper < ServiceHelper def initialize(stream, pubsubjid, oauth_consumer, oauth_token, options = {}) # imbue the stream with magical OAuth signing powers stream.extend(OAuthPubSubStreamHelper) stream.oauth_consumer = oauth_consumer stream.oauth_token = oauth_token stream.oauth_options = options stream.pubsubjid = pubsubjid super(stream, pubsubjid) end # add the OAuth sauce (XEP-0235) # The `options` hash may contain the following parameters: # :oauth_nonce => nonce (one will be generated otherwise) # :oauth_timestamp => timestamp (one will be generated otherwise) # :oauth_signature_method => signature method (defaults to HMAC-SHA1) # :oauth_version => OAuth version (defaults to "1.0") def self.create_oauth_node(jid, pubsubjid, oauth_consumer, oauth_token, options = {}) require 'oauth' request = OAuth::RequestProxy.proxy \ "method" => "iq", "uri" => [jid.strip.to_s, pubsubjid.strip.to_s] * "&", "parameters" => { "oauth_consumer_key" => oauth_consumer.key, "oauth_nonce" => options[:oauth_nonce] || OAuth::Helper.generate_nonce, "oauth_timestamp" => options[:oauth_timestamp] || OAuth::Helper.generate_timestamp, "oauth_token" => oauth_token.token, "oauth_signature_method" => options[:oauth_signature_method] || "HMAC-SHA1", "oauth_version" => options[:oauth_version] || "1.0" } request.sign!(:consumer => oauth_consumer, :token => oauth_token) # TODO create XMPPElements for OAuth elements oauth = REXML::Element.new("oauth") oauth.attributes['xmlns'] = 'urn:xmpp:oauth:0' oauth_consumer_key = REXML::Element.new("oauth_consumer_key") oauth_consumer_key.text = request.oauth_consumer_key oauth.add(oauth_consumer_key) oauth_token_node = REXML::Element.new("oauth_token") oauth_token_node.text = request.oauth_token oauth.add(oauth_token_node) oauth_signature_method = REXML::Element.new("oauth_signature_method") oauth_signature_method.text = request.oauth_signature_method oauth.add(oauth_signature_method) oauth_signature = REXML::Element.new("oauth_signature") oauth_signature.text = request.oauth_signature oauth.add(oauth_signature) oauth_timestamp = REXML::Element.new("oauth_timestamp") oauth_timestamp.text = request.oauth_timestamp oauth.add(oauth_timestamp) oauth_nonce = REXML::Element.new("oauth_nonce") oauth_nonce.text = request.oauth_nonce oauth.add(oauth_nonce) oauth_version = REXML::Element.new("oauth_version") oauth_version.text = request.oauth_version oauth.add(oauth_version) oauth end end end end