Add the ability to use an oauth token to interact with the index and registry.
This commit is contained in:
parent
0992c8a47e
commit
a9c0e016f3
2 changed files with 46 additions and 29 deletions
67
auth/auth.py
67
auth/auth.py
|
@ -21,6 +21,39 @@ from util.http import abort
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_and_apply_oauth_token(token):
|
||||||
|
validated = oauth.validate_access_token(token)
|
||||||
|
if not validated:
|
||||||
|
logger.warning('OAuth access token could not be validated: %s', token)
|
||||||
|
authenticate_header = {
|
||||||
|
'WWW-Authenticate': ('Bearer error="invalid_token", '
|
||||||
|
'error_description="The access token is invalid"'),
|
||||||
|
}
|
||||||
|
abort(401, message='OAuth access token could not be validated: %(token)s',
|
||||||
|
issue='invalid-oauth-token', token=token, header=authenticate_header)
|
||||||
|
elif validated.expires_at <= datetime.now():
|
||||||
|
logger.info('OAuth access with an expired token: %s', token)
|
||||||
|
authenticate_header = {
|
||||||
|
'WWW-Authenticate': ('Bearer error="invalid_token", '
|
||||||
|
'error_description="The access token expired"'),
|
||||||
|
}
|
||||||
|
abort(401, message='OAuth access token has expired: %(token)s',
|
||||||
|
issue='invalid-oauth-token', token=token, headers=authenticate_header)
|
||||||
|
|
||||||
|
# We have a valid token
|
||||||
|
scope_set = scopes.scopes_from_scope_string(validated.scope)
|
||||||
|
logger.debug('Successfully validated oauth access token: %s with scope: %s', token,
|
||||||
|
scope_set)
|
||||||
|
|
||||||
|
set_authenticated_user(validated.authorized_user)
|
||||||
|
set_validated_oauth_token(validated)
|
||||||
|
|
||||||
|
new_identity = QuayDeferredPermissionUser(validated.authorized_user.username, 'username',
|
||||||
|
scope_set)
|
||||||
|
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]
|
normalized = [part.strip() for part in auth.split(' ') if part]
|
||||||
if normalized[0].lower() != 'basic' or len(normalized) != 2:
|
if normalized[0].lower() != 'basic' or len(normalized) != 2:
|
||||||
|
@ -45,6 +78,10 @@ def process_basic_auth(auth):
|
||||||
except model.DataModelException:
|
except model.DataModelException:
|
||||||
logger.debug('Invalid token: %s' % credentials[1])
|
logger.debug('Invalid token: %s' % credentials[1])
|
||||||
|
|
||||||
|
elif credentials[0] == '$oauthtoken':
|
||||||
|
oauth_token = credentials[1]
|
||||||
|
validate_and_apply_oauth_token(oauth_token)
|
||||||
|
|
||||||
elif '+' in credentials[0]:
|
elif '+' in credentials[0]:
|
||||||
logger.debug('Trying robot auth with credentials %s' % str(credentials))
|
logger.debug('Trying robot auth with credentials %s' % str(credentials))
|
||||||
# Use as robot auth
|
# Use as robot auth
|
||||||
|
@ -120,35 +157,7 @@ def process_oauth(f):
|
||||||
return
|
return
|
||||||
|
|
||||||
token = normalized[1]
|
token = normalized[1]
|
||||||
validated = oauth.validate_access_token(token)
|
validate_and_apply_oauth_token(token)
|
||||||
if not validated:
|
|
||||||
logger.warning('OAuth access token could not be validated: %s', token)
|
|
||||||
authenticate_header = {
|
|
||||||
'WWW-Authenticate': ('Bearer error="invalid_token", '
|
|
||||||
'error_description="The access token is invalid"'),
|
|
||||||
}
|
|
||||||
abort(401, message='OAuth access token could not be validated: %(token)s',
|
|
||||||
issue='invalid-oauth-token', token=token, header=authenticate_header)
|
|
||||||
elif validated.expires_at <= datetime.now():
|
|
||||||
logger.info('OAuth access with an expired token: %s', token)
|
|
||||||
authenticate_header = {
|
|
||||||
'WWW-Authenticate': ('Bearer error="invalid_token", '
|
|
||||||
'error_description="The access token expired"'),
|
|
||||||
}
|
|
||||||
abort(401, message='OAuth access token has expired: %(token)s',
|
|
||||||
issue='invalid-oauth-token', token=token, headers=authenticate_header)
|
|
||||||
|
|
||||||
# We have a valid token
|
|
||||||
scope_set = scopes.scopes_from_scope_string(validated.scope)
|
|
||||||
logger.debug('Successfully validated oauth access token: %s with scope: %s', token,
|
|
||||||
scope_set)
|
|
||||||
|
|
||||||
set_authenticated_user(validated.authorized_user)
|
|
||||||
set_validated_oauth_token(validated)
|
|
||||||
|
|
||||||
new_identity = QuayDeferredPermissionUser(validated.authorized_user.username, 'username',
|
|
||||||
scope_set)
|
|
||||||
identity_changed.send(app, identity=new_identity)
|
|
||||||
elif not current_user.is_anonymous():
|
elif not current_user.is_anonymous():
|
||||||
logger.debug('Loading user from cookie: %s', current_user.get_id())
|
logger.debug('Loading user from cookie: %s', current_user.get_id())
|
||||||
set_authenticated_user_deferred(current_user.get_id())
|
set_authenticated_user_deferred(current_user.get_id())
|
||||||
|
|
|
@ -7,6 +7,7 @@ from functools import wraps
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from data import model
|
from data import model
|
||||||
|
from data.model import oauth
|
||||||
from data.queue import webhook_queue
|
from data.queue import webhook_queue
|
||||||
from app import mixpanel, app
|
from app import mixpanel, app
|
||||||
from auth.auth import process_auth
|
from auth.auth import process_auth
|
||||||
|
@ -78,6 +79,13 @@ def create_user():
|
||||||
except model.InvalidTokenException:
|
except model.InvalidTokenException:
|
||||||
abort(400, 'Invalid access token.', issue='invalid-access-token')
|
abort(400, 'Invalid access token.', issue='invalid-access-token')
|
||||||
|
|
||||||
|
elif username == '$oauthtoken':
|
||||||
|
validated = oauth.validate_access_token(password)
|
||||||
|
if validated is not None:
|
||||||
|
return success
|
||||||
|
else:
|
||||||
|
abort(400, 'Invalid oauth access token.', issue='invalid-oauth-access-token')
|
||||||
|
|
||||||
elif '+' in username:
|
elif '+' in username:
|
||||||
try:
|
try:
|
||||||
model.verify_robot(username, password)
|
model.verify_robot(username, password)
|
||||||
|
|
Reference in a new issue