Fix and templatize the logic for external JWT AuthN and registry v2 Auth.
Make it explicit that the registry-v2 stuff is not ready for prime time.
This commit is contained in:
parent
768192927a
commit
bc29561f8f
11 changed files with 223 additions and 79 deletions
|
@ -53,20 +53,22 @@ def _get_federated_user(username, email, federated_service, create_new_user):
|
|||
return (db_user, None)
|
||||
|
||||
|
||||
class JWTAuthUsers(object):
|
||||
class ExternalJWTAuthN(object):
|
||||
""" Delegates authentication to a REST endpoint that returns JWTs. """
|
||||
PUBLIC_KEY_FILENAME = 'jwt-authn.cert'
|
||||
|
||||
def __init__(self, verify_url, issuer, override_config_dir, http_client, public_key_path=None):
|
||||
def __init__(self, verify_url, issuer, override_config_dir, http_client, max_fresh_s,
|
||||
public_key_path=None):
|
||||
self.verify_url = verify_url
|
||||
self.issuer = issuer
|
||||
self.client = http_client
|
||||
self.max_fresh_s = max_fresh_s
|
||||
|
||||
default_key_path = os.path.join(override_config_dir, JWTAuthUsers.PUBLIC_KEY_FILENAME)
|
||||
default_key_path = os.path.join(override_config_dir, ExternalJWTAuthN.PUBLIC_KEY_FILENAME)
|
||||
public_key_path = public_key_path or default_key_path
|
||||
if not os.path.exists(public_key_path):
|
||||
error_message = ('JWT Authentication public key file "%s" not found in directory %s' %
|
||||
(JWTAuthUsers.PUBLIC_KEY_FILENAME, override_config_dir))
|
||||
(ExternalJWTAuthN.PUBLIC_KEY_FILENAME, override_config_dir))
|
||||
|
||||
raise Exception(error_message)
|
||||
|
||||
|
@ -102,10 +104,11 @@ class JWTAuthUsers(object):
|
|||
if not 'exp' in payload:
|
||||
raise Exception('Missing exp field in JWT')
|
||||
|
||||
# Verify that the expiration is no more than 300 seconds in the future.
|
||||
# Verify that the expiration is no more than self.max_fresh_s seconds in the future.
|
||||
expiration = datetime.utcfromtimestamp(payload['exp'])
|
||||
if expiration > datetime.utcnow() + timedelta(seconds=300):
|
||||
logger.debug('Payload expiration is outside of the 300 second window: %s', payload['exp'])
|
||||
if expiration > datetime.utcnow() + timedelta(seconds=self.max_fresh_s):
|
||||
logger.debug('Payload expiration is outside of the %s second window: %s', self.max_fresh_s,
|
||||
payload['exp'])
|
||||
return (None, 'Invalid username or password')
|
||||
|
||||
# Parse out the username and email.
|
||||
|
@ -330,7 +333,9 @@ class UserAuthentication(object):
|
|||
elif authentication_type == 'JWT':
|
||||
verify_url = app.config.get('JWT_VERIFY_ENDPOINT')
|
||||
issuer = app.config.get('JWT_AUTH_ISSUER')
|
||||
users = JWTAuthUsers(verify_url, issuer, override_config_dir, app.config['HTTPCLIENT'])
|
||||
max_fresh_s = app.config.get('JWT_AUTH_MAX_FRESH_S', 300)
|
||||
users = ExternalJWTAuthN(verify_url, issuer, override_config_dir, max_fresh_s,
|
||||
app.config['HTTPCLIENT'])
|
||||
else:
|
||||
raise RuntimeError('Unknown authentication type: %s' % authentication_type)
|
||||
|
||||
|
|
Reference in a new issue