651666b60b
Breaks out the validation code from the auth context modification calls, makes decorators easier to define and adds testing for each individual piece. Will be the basis of better error messaging in the following change.
55 lines
2 KiB
Python
55 lines
2 KiB
Python
import logging
|
|
|
|
from flask.sessions import SecureCookieSessionInterface, BadSignature
|
|
|
|
from app import app
|
|
from auth.validateresult import AuthKind, ValidateResult
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# The prefix for all signatures of signed granted.
|
|
SIGNATURE_PREFIX = 'sigv2='
|
|
|
|
def generate_signed_token(grants, user_context):
|
|
""" Generates a signed session token with the given grants and user context. """
|
|
ser = SecureCookieSessionInterface().get_signing_serializer(app)
|
|
data_to_sign = {
|
|
'grants': grants,
|
|
'user_context': user_context,
|
|
}
|
|
|
|
encrypted = ser.dumps(data_to_sign)
|
|
return '{0}{1}'.format(SIGNATURE_PREFIX, encrypted)
|
|
|
|
|
|
def validate_signed_grant(auth_header):
|
|
""" Validates a signed grant as found inside an auth header and returns whether it points to
|
|
a valid grant.
|
|
"""
|
|
if not auth_header:
|
|
return ValidateResult(AuthKind.signed_grant, missing=True)
|
|
|
|
# Try to parse the token from the header.
|
|
normalized = [part.strip() for part in auth_header.split(' ') if part]
|
|
if normalized[0].lower() != 'token' or len(normalized) != 2:
|
|
logger.debug('Not a token: %s', auth_header)
|
|
return ValidateResult(AuthKind.signed_grant, missing=True)
|
|
|
|
# Check that it starts with the expected prefix.
|
|
if not normalized[1].startswith(SIGNATURE_PREFIX):
|
|
logger.debug('Not a signed grant token: %s', auth_header)
|
|
return ValidateResult(AuthKind.signed_grant, missing=True)
|
|
|
|
# Decrypt the grant.
|
|
encrypted = normalized[1][len(SIGNATURE_PREFIX):]
|
|
ser = SecureCookieSessionInterface().get_signing_serializer(app)
|
|
|
|
try:
|
|
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)
|
|
return ValidateResult(AuthKind.signed_grant,
|
|
error_message='Signed grant could not be validated')
|
|
|
|
logger.debug('Successfully validated signed grant with data: %s', token_data)
|
|
return ValidateResult(AuthKind.signed_grant, signed_data=token_data)
|