Add support for XEP-0235: OAuth over XMPP
This commit is contained in:
parent
357406d801
commit
a88b9737ff
1
setup.py
1
setup.py
@ -97,6 +97,7 @@ packages = [ 'sleekxmpp',
|
||||
'sleekxmpp/plugins/xep_0221',
|
||||
'sleekxmpp/plugins/xep_0224',
|
||||
'sleekxmpp/plugins/xep_0231',
|
||||
'sleekxmpp/plugins/xep_0235',
|
||||
'sleekxmpp/plugins/xep_0249',
|
||||
'sleekxmpp/plugins/xep_0258',
|
||||
'sleekxmpp/features',
|
||||
|
@ -60,6 +60,7 @@ __all__ = [
|
||||
'xep_0223', # Persistent Storage of Private Data via Pubsub
|
||||
'xep_0224', # Attention
|
||||
'xep_0231', # Bits of Binary
|
||||
'xep_0235', # OAuth Over XMPP
|
||||
'xep_0242', # XMPP Client Compliance 2009
|
||||
'xep_0249', # Direct MUC Invitations
|
||||
'xep_0256', # Last Activity in Presence
|
||||
|
16
sleekxmpp/plugins/xep_0235/__init__.py
Normal file
16
sleekxmpp/plugins/xep_0235/__init__.py
Normal 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)
|
32
sleekxmpp/plugins/xep_0235/oauth.py
Normal file
32
sleekxmpp/plugins/xep_0235/oauth.py
Normal 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')
|
80
sleekxmpp/plugins/xep_0235/stanza.py
Normal file
80
sleekxmpp/plugins/xep_0235/stanza.py
Normal 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
|
Loading…
Reference in New Issue
Block a user