Switch our temporary token lookups for signed grants which will not require DB access.
This commit is contained in:
parent
4e5d671349
commit
78c8354174
4 changed files with 81 additions and 54 deletions
63
auth/auth.py
63
auth/auth.py
|
@ -6,6 +6,7 @@ from datetime import datetime
|
|||
from flask import request, session
|
||||
from flask.ext.principal import identity_changed, Identity
|
||||
from flask.ext.login import current_user
|
||||
from flask.sessions import SecureCookieSessionInterface, BadSignature
|
||||
from base64 import b64decode
|
||||
|
||||
import scopes
|
||||
|
@ -22,6 +23,9 @@ from util.http import abort
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
SIGNATURE_PREFIX = 'signature='
|
||||
|
||||
|
||||
def _load_user_from_cookie():
|
||||
if not current_user.is_anonymous():
|
||||
try:
|
||||
|
@ -69,7 +73,7 @@ def _validate_and_apply_oauth_token(token):
|
|||
identity_changed.send(app, identity=new_identity)
|
||||
|
||||
|
||||
def process_basic_auth(auth):
|
||||
def _process_basic_auth(auth):
|
||||
normalized = [part.strip() for part in auth.split(' ') if part]
|
||||
if normalized[0].lower() != 'basic' or len(normalized) != 2:
|
||||
logger.debug('Invalid basic auth format.')
|
||||
|
@ -127,44 +131,41 @@ def process_basic_auth(auth):
|
|||
logger.debug('Basic auth present but could not be validated.')
|
||||
|
||||
|
||||
def process_token(auth):
|
||||
def generate_signed_token(grants):
|
||||
ser = SecureCookieSessionInterface().get_signing_serializer(app)
|
||||
data_to_sign = {
|
||||
'grants': grants,
|
||||
}
|
||||
|
||||
encrypted = ser.dumps(data_to_sign)
|
||||
return '{0}{1}'.format(SIGNATURE_PREFIX, encrypted)
|
||||
|
||||
|
||||
def _process_signed_grant(auth):
|
||||
normalized = [part.strip() for part in auth.split(' ') if part]
|
||||
if normalized[0].lower() != 'token' or len(normalized) != 2:
|
||||
logger.debug('Not an auth token: %s' % auth)
|
||||
logger.debug('Not a token: %s', auth)
|
||||
return
|
||||
|
||||
token_details = normalized[1].split(',')
|
||||
if not normalized[1].startswith(SIGNATURE_PREFIX):
|
||||
logger.debug('Not a signed grant token: %s', auth)
|
||||
return
|
||||
|
||||
if len(token_details) != 1:
|
||||
logger.warning('Invalid token format: %s' % auth)
|
||||
abort(401, message='Invalid token format: %(auth)s', issue='invalid-auth-token', auth=auth)
|
||||
|
||||
def safe_get(lst, index, default_value):
|
||||
try:
|
||||
return lst[index]
|
||||
except IndexError:
|
||||
return default_value
|
||||
|
||||
token_vals = {val[0]: safe_get(val, 1, '') for val in
|
||||
(detail.split('=') for detail in token_details)}
|
||||
|
||||
if 'signature' not in token_vals:
|
||||
logger.warning('Token does not contain signature: %s' % auth)
|
||||
abort(401, message='Token does not contain a valid signature: %(auth)s',
|
||||
issue='invalid-auth-token', auth=auth)
|
||||
encrypted = normalized[1][len(SIGNATURE_PREFIX):]
|
||||
ser = SecureCookieSessionInterface().get_signing_serializer(app)
|
||||
|
||||
try:
|
||||
token_data = model.load_token_data(token_vals['signature'])
|
||||
|
||||
except model.InvalidTokenException:
|
||||
logger.warning('Token could not be validated: %s', token_vals['signature'])
|
||||
abort(401, message='Token could not be validated: %(auth)s', issue='invalid-auth-token',
|
||||
token_data = ser.loads(encrypted, max_age=app.config['SIGNED_GRANT_EXPIRATION_SEC'])
|
||||
except BadSignature:
|
||||
logger.warning('Signed grant could not be validated: %s', encrypted)
|
||||
abort(401, message='Signed grant could not be validated: %(auth)s', issue='invalid-auth-token',
|
||||
auth=auth)
|
||||
|
||||
logger.debug('Successfully validated token: %s', token_data.code)
|
||||
set_validated_token(token_data)
|
||||
logger.debug('Successfully validated signed grant with data: %s', token_data)
|
||||
|
||||
identity_changed.send(app, identity=Identity(token_data.code, 'token'))
|
||||
loaded_identity = Identity(None, 'signed_grant')
|
||||
loaded_identity.provides.update(token_data['grants'])
|
||||
identity_changed.send(app, identity=loaded_identity)
|
||||
|
||||
|
||||
def process_oauth(func):
|
||||
|
@ -192,8 +193,8 @@ def process_auth(func):
|
|||
|
||||
if auth:
|
||||
logger.debug('Validating auth header: %s' % auth)
|
||||
process_token(auth)
|
||||
process_basic_auth(auth)
|
||||
_process_signed_grant(auth)
|
||||
_process_basic_auth(auth)
|
||||
else:
|
||||
logger.debug('No auth header.')
|
||||
|
||||
|
|
Reference in a new issue