Commit 94960649 by Victor Shnayder

Merge pull request #821 from MITx/feature/rocha/openid-djangostore

Use django cache for OpenID provider store
parents 79996f20 e62968d5
"""A openid store using django cache"""
from openid.store.interface import OpenIDStore
from openid.store import nonce
from django.core.cache import cache
import logging
import time
DEFAULT_ASSOCIATION_TIMEOUT = 60
DEFAULT_NONCE_TIMEOUT = 600
ASSOCIATIONS_KEY_PREFIX = 'openid.provider.associations.'
NONCE_KEY_PREFIX = 'openid.provider.nonce.'
log = logging.getLogger('DjangoOpenIDStore')
def get_url_key(server_url):
key = ASSOCIATIONS_KEY_PREFIX + server_url
return key
def get_nonce_key(server_url, timestamp, salt):
key = '{prefix}{url}.{ts}.{salt}'.format(prefix=NONCE_KEY_PREFIX,
url=server_url,
ts=timestamp,
salt=salt)
return key
class DjangoOpenIDStore(OpenIDStore):
def __init__(self):
log.info('DjangoStore cache:' + str(cache.__class__))
def storeAssociation(self, server_url, association):
key = get_url_key(server_url)
log.info('storeAssociation {0}'.format(key))
associations = cache.get(key, {})
associations[association.handle] = association
cache.set(key, associations, DEFAULT_ASSOCIATION_TIMEOUT)
def getAssociation(self, server_url, handle=None):
key = get_url_key(server_url)
log.info('getAssociation {0}'.format(key))
associations = cache.get(key)
association = None
if associations:
if handle is None:
# get best association
valid = [a for a in associations if a.getExpiresIn() > 0]
if valid:
association = valid[0]
else:
association = associations.get(handle)
# check expiration and remove if it has expired
if association and association.getExpiresIn() <= 0:
if handle is None:
cache.delete(key)
else:
associations.pop(handle)
cache.set(key, association, DEFAULT_ASSOCIATION_TIMEOUT)
association = None
return association
def removeAssociation(self, server_url, handle):
key = get_url_key(server_url)
log.info('removeAssociation {0}'.format(key))
associations = cache.get(key)
removed = False
if associations:
if handle is None:
cache.delete(key)
removed = True
else:
association = associations.pop(handle)
if association:
cache.set(key, association, DEFAULT_ASSOCIATION_TIMEOUT)
removed = True
return removed
def useNonce(self, server_url, timestamp, salt):
key = get_nonce_key(server_url, timestamp, salt)
log.info('useNonce {0}'.format(key))
if abs(timestamp - time.time()) > nonce.SKEW:
return False
anonce = cache.get(key)
found = False
if anonce is None:
cache.set(key, '-', DEFAULT_NONCE_TIMEOUT)
found = False
else:
found = True
return found
def cleanupNonces(self):
# not necesary, keys will timeout
return 0
def cleanupAssociations(self):
# not necesary, keys will timeout
return 0
......@@ -7,6 +7,7 @@ import string
import fnmatch
from external_auth.models import ExternalAuthMap
from external_auth.djangostore import DjangoOpenIDStore
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login
......@@ -30,7 +31,6 @@ from openid.consumer.consumer import SUCCESS
from openid.server.server import Server
from openid.server.trustroot import TrustRoot
from openid.store.filestore import FileOpenIDStore
from openid.extensions import ax, sreg
import student.views as student_views
......@@ -271,10 +271,7 @@ def get_xrds_url(resource, request):
"""
Return the XRDS url for a resource
"""
host = request.META['HTTP_HOST']
if not host.endswith('edx.org'):
return None
host = request.get_host()
location = host + '/openid/provider/' + resource + '/'
......@@ -400,7 +397,7 @@ def provider_login(request):
return default_render_failure(request, "Invalid OpenID request")
# initialize store and server
store = FileOpenIDStore('/tmp/openid_provider')
store = DjangoOpenIDStore()
server = Server(store, endpoint)
# handle OpenID request
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment