Add support for XEP-0235: OAuth over XMPP

This commit is contained in:
Lance Stout 2012-09-04 19:42:49 -07:00
parent 357406d801
commit a88b9737ff
5 changed files with 130 additions and 0 deletions

View File

@ -97,6 +97,7 @@ packages = [ 'sleekxmpp',
'sleekxmpp/plugins/xep_0221', 'sleekxmpp/plugins/xep_0221',
'sleekxmpp/plugins/xep_0224', 'sleekxmpp/plugins/xep_0224',
'sleekxmpp/plugins/xep_0231', 'sleekxmpp/plugins/xep_0231',
'sleekxmpp/plugins/xep_0235',
'sleekxmpp/plugins/xep_0249', 'sleekxmpp/plugins/xep_0249',
'sleekxmpp/plugins/xep_0258', 'sleekxmpp/plugins/xep_0258',
'sleekxmpp/features', 'sleekxmpp/features',

View File

@ -60,6 +60,7 @@ __all__ = [
'xep_0223', # Persistent Storage of Private Data via Pubsub 'xep_0223', # Persistent Storage of Private Data via Pubsub
'xep_0224', # Attention 'xep_0224', # Attention
'xep_0231', # Bits of Binary 'xep_0231', # Bits of Binary
'xep_0235', # OAuth Over XMPP
'xep_0242', # XMPP Client Compliance 2009 'xep_0242', # XMPP Client Compliance 2009
'xep_0249', # Direct MUC Invitations 'xep_0249', # Direct MUC Invitations
'xep_0256', # Last Activity in Presence 'xep_0256', # Last Activity in Presence

View File

@ -0,0 +1,16 @@
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
This file is part of SleekXMPP.
See the file LICENSE for copying permission.
"""
from sleekxmpp.plugins.base import register_plugin
from sleekxmpp.plugins.xep_0235 import stanza
from sleekxmpp.plugins.xep_0235.stanza import OAuth
from sleekxmpp.plugins.xep_0235.oauth import XEP_0235
register_plugin(XEP_0235)

View File

@ -0,0 +1,32 @@
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
This file is part of SleekXMPP.
See the file LICENSE for copying permission.
"""
import logging
from sleekxmpp import Message
from sleekxmpp.plugins import BasePlugin
from sleekxmpp.xmlstream import register_stanza_plugin
from sleekxmpp.plugins.xep_0235 import stanza, OAuth
class XEP_0235(BasePlugin):
name = 'xep_0235'
description = 'XEP-0235: OAuth Over XMPP'
dependencies = set(['xep_0030'])
stanza = stanza
def plugin_init(self):
register_stanza_plugin(Message, OAuth)
def session_bind(self, jid):
self.xmpp['xep_0030'].add_feature('urn:xmpp:oauth:0')
def plugin_end(self):
self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:oauth:0')

View File

@ -0,0 +1,80 @@
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
This file is part of SleekXMPP.
See the file LICENSE for copying permission.
"""
import hmac
import hashlib
import urllib
import base64
from sleekxmpp.xmlstream import ET, ElementBase, JID
class OAuth(ElementBase):
name = 'oauth'
namespace = 'urn:xmpp:oauth:0'
plugin_attrib = 'oauth'
interfaces = set(['oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
'oauth_signature_method', 'oauth_timestamp',
'oauth_token', 'oauth_version'])
sub_interfaces = interfaces
def generate_signature(self, stanza, sfrom, sto, consumer_secret,
token_secret, method='HMAC-SHA1'):
self['oauth_signature_method'] = method
request = urllib.quote('%s&%s' % (sfrom, sto), '')
parameters = urllib.quote('&'.join([
'oauth_consumer_key=%s' % self['oauth_consumer_key'],
'oauth_nonce=%s' % self['oauth_nonce'],
'oauth_signature_method=%s' % self['oauth_signature_method'],
'oauth_timestamp=%s' % self['oauth_timestamp'],
'oauth_token=%s' % self['oauth_token'],
'oauth_version=%s' % self['oauth_version']
]), '')
sigbase = '%s&%s&%s' % (stanza, request, parameters)
consumer_secret = urllib.quote(consumer_secret, '')
token_secret = urllib.quote(token_secret, '')
key = '%s&%s' % (consumer_secret, token_secret)
if method == 'HMAC-SHA1':
sig = base64.b64encode(hmac.new(key, sigbase, hashlib.sha1).digest())
elif method == 'PLAINTEXT':
sig = key
self['oauth_signature'] = sig
return sig
def verify_signature(self, stanza, sfrom, sto, consumer_secret,
token_secret):
method = self['oauth_signature_method']
request = urllib.quote('%s&%s' % (sfrom, sto), '')
parameters = urllib.quote('&'.join([
'oauth_consumer_key=%s' % self['oauth_consumer_key'],
'oauth_nonce=%s' % self['oauth_nonce'],
'oauth_signature_method=%s' % self['oauth_signature_method'],
'oauth_timestamp=%s' % self['oauth_timestamp'],
'oauth_token=%s' % self['oauth_token'],
'oauth_version=%s' % self['oauth_version']
]), '')
sigbase = '%s&%s&%s' % (stanza, request, parameters)
consumer_secret = urllib.quote(consumer_secret, '')
token_secret = urllib.quote(token_secret, '')
key = '%s&%s' % (consumer_secret, token_secret)
if method == 'HMAC-SHA1':
sig = base64.b64encode(hmac.new(key, sigbase, hashlib.sha1).digest())
elif method == 'PLAINTEXT':
sig = key
return self['oauth_signature'] == sig