Make get_user_from_api_query_string() report detailed errors when signature checking fails (refs #5536)

This commit is contained in:
Benjamin Dauvergne 2014-09-18 11:51:54 +02:00
parent a873d2678a
commit 3074204f09
1 changed files with 24 additions and 15 deletions

View File

@ -20,55 +20,64 @@ import hashlib
import datetime
from quixote import get_request, get_publisher
from qommon.errors import AccessForbiddenError
def get_user_from_api_query_string():
query_string = get_request().get_query()
if not query_string:
return None
# verify signature
orig = get_request().form.get('orig')
if not isinstance(orig, basestring):
return None
key = get_publisher().get_site_option(orig, 'api-secrets')
if not key:
return None
signature = get_request().form.get('signature')
if not isinstance(signature, basestring):
return None
# verify signature
orig = get_request().form.get('orig')
if not isinstance(orig, basestring):
raise AccessForbiddenError('missing/multiple orig field')
key = get_publisher().get_site_option(orig, 'api-secrets')
if not key:
raise AccessForbiddenError('invalid orig')
algo = get_request().form.get('algo')
if not isinstance(algo, basestring):
return None
raise AccessForbiddenError('missing/multiple algo field')
try:
algo = getattr(hashlib, algo)
except AttributeError:
algo = hashlib.sha256
raise AccessForbiddenError('invalid algo')
if signature != base64.standard_b64encode(hmac.new(key,
query_string[:query_string.find('&signature=')],
algo).digest()):
return None
raise AccessForbiddenError('invalid signature')
timestamp = get_request().form.get('timestamp')
if not isinstance(timestamp, basestring):
return None
raise AccessForbiddenError('missing/multiple timestamp field')
delta = (datetime.datetime.utcnow().replace(tzinfo=None) -
datetime.datetime.strptime(timestamp,
'%Y-%m-%dT%H:%M:%SZ'))
if abs(delta) > datetime.timedelta(seconds=30):
return None
MAX_DELTA = 30
if abs(delta) > datetime.timedelta(seconds=MAX_DELTA):
raise AccessForbiddenError('timestamp delta is more '
'than %s seconds: %s seconds' % (MAX_DELTA, delta))
user = None
if get_request().form.get('email'):
email = get_request().form.get('email')
if not isinstance(email, basestring):
return None
raise AccessForbiddenError('multiple email field')
users = list(get_publisher().user_class.get_users_with_email(email))
if users:
user = users[0]
else:
raise AccessForbiddenError('unknown email')
elif get_request().form.get('NameID'):
ni = get_request().form.get('NameID')
if not isinstance(ni, basestring):
return None
raise AccessForbiddenError('multiple NameID field')
users = list(get_publisher().user_class.get_users_with_name_identifier(ni))
if users:
user = users[0]
else:
raise AccessForbiddenError('unknown NameID')
else:
raise AccessForbiddenError('missing email or NameID fields')
return user