diff options
Diffstat (limited to 'django_authopenid/util.py')
-rw-r--r-- | django_authopenid/util.py | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/django_authopenid/util.py b/django_authopenid/util.py new file mode 100644 index 00000000..841a81c7 --- /dev/null +++ b/django_authopenid/util.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +from openid.store.interface import OpenIDStore +from openid.association import Association as OIDAssociation +from openid.extensions import sreg +import openid.store + +from django.db.models.query import Q +from django.conf import settings +from django.http import str_to_unicode + + +# needed for some linux distributions like debian +try: + from openid.yadis import xri +except: + from yadis import xri + +import time, base64, md5, operator +import urllib + +from models import Association, Nonce + +__all__ = ['OpenID', 'DjangoOpenIDStore', 'from_openid_response', 'clean_next'] + +DEFAULT_NEXT = getattr(settings, 'OPENID_REDIRECT_NEXT', '/') +def clean_next(next): + if next is None: + return DEFAULT_NEXT + next = str_to_unicode(urllib.unquote(next), 'utf-8') + next = next.strip() + if next.startswith('/'): + return next + return DEFAULT_NEXT + +class OpenID: + def __init__(self, openid_, issued, attrs=None, sreg_=None): + self.openid = openid_ + self.issued = issued + self.attrs = attrs or {} + self.sreg = sreg_ or {} + self.is_iname = (xri.identifierScheme(openid_) == 'XRI') + + def __repr__(self): + return '<OpenID: %s>' % self.openid + + def __str__(self): + return self.openid + +class DjangoOpenIDStore(OpenIDStore): + def __init__(self): + self.max_nonce_age = 6 * 60 * 60 # Six hours + + def storeAssociation(self, server_url, association): + assoc = Association( + server_url = server_url, + handle = association.handle, + secret = base64.encodestring(association.secret), + issued = association.issued, + lifetime = association.issued, + assoc_type = association.assoc_type + ) + assoc.save() + + def getAssociation(self, server_url, handle=None): + assocs = [] + if handle is not None: + assocs = Association.objects.filter( + server_url = server_url, handle = handle + ) + else: + assocs = Association.objects.filter( + server_url = server_url + ) + if not assocs: + return None + associations = [] + for assoc in assocs: + association = OIDAssociation( + assoc.handle, base64.decodestring(assoc.secret), assoc.issued, + assoc.lifetime, assoc.assoc_type + ) + if association.getExpiresIn() == 0: + self.removeAssociation(server_url, assoc.handle) + else: + associations.append((association.issued, association)) + if not associations: + return None + return associations[-1][1] + + def removeAssociation(self, server_url, handle): + assocs = list(Association.objects.filter( + server_url = server_url, handle = handle + )) + assocs_exist = len(assocs) > 0 + for assoc in assocs: + assoc.delete() + return assocs_exist + + def useNonce(self, server_url, timestamp, salt): + if abs(timestamp - time.time()) > openid.store.nonce.SKEW: + return False + + query = [ + Q(server_url__exact=server_url), + Q(timestamp__exact=timestamp), + Q(salt__exact=salt), + ] + try: + ononce = Nonce.objects.get(reduce(operator.and_, query)) + except Nonce.DoesNotExist: + ononce = Nonce( + server_url=server_url, + timestamp=timestamp, + salt=salt + ) + ononce.save() + return True + + ononce.delete() + + return False + + def cleanupNonce(self): + Nonce.objects.filter(timestamp<int(time.time()) - nonce.SKEW).delete() + + def cleanupAssociations(self): + Association.objects.extra(where=['issued + lifetimeint<(%s)' % time.time()]).delete() + + def getAuthKey(self): + # Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY + return md5.new(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN] + + def isDumb(self): + return False + +def from_openid_response(openid_response): + """ return openid object from response """ + issued = int(time.time()) + sreg_resp = sreg.SRegResponse.fromSuccessResponse(openid_response) \ + or [] + + return OpenID( + openid_response.identity_url, issued, openid_response.signed_fields, + dict(sreg_resp) + ) |