diff --git a/app.py b/app.py index 0292d6a1f..488c108d4 100644 --- a/app.py +++ b/app.py @@ -35,7 +35,7 @@ else: app.config.from_object(config) -Principal(app, use_sessions=True) +Principal(app, use_sessions=False) login_manager = LoginManager() login_manager.init_app(app) diff --git a/auth/auth.py b/auth/auth.py index 6c50685a3..b21800896 100644 --- a/auth/auth.py +++ b/auth/auth.py @@ -2,16 +2,19 @@ import logging from functools import wraps from datetime import datetime -from flask import request, _request_ctx_stack, session +from flask import request, session from flask.ext.principal import identity_changed, Identity +from flask.ext.login import current_user from base64 import b64decode +import scopes + from data import model from data.model import oauth from app import app from permissions import QuayDeferredPermissionUser -import scopes - +from auth_context import (set_authenticated_user, set_validated_token, + set_authenticated_user_deferred) from util.http import abort @@ -34,8 +37,7 @@ def process_basic_auth(auth): try: token = model.load_token_data(credentials[1]) logger.debug('Successfully validated token: %s' % credentials[1]) - ctx = _request_ctx_stack.top - ctx.validated_token = token + set_validated_token(token) identity_changed.send(app, identity=Identity(token.code, 'token')) return @@ -49,8 +51,7 @@ def process_basic_auth(auth): try: robot = model.verify_robot(credentials[0], credentials[1]) logger.debug('Successfully validated robot: %s' % credentials[0]) - ctx = _request_ctx_stack.top - ctx.authenticated_user = robot + set_authenticated_user(robot) deferred_robot = QuayDeferredPermissionUser(robot.username, 'username') identity_changed.send(app, identity=deferred_robot) @@ -63,8 +64,7 @@ def process_basic_auth(auth): if authenticated: logger.debug('Successfully validated user: %s' % authenticated.username) - ctx = _request_ctx_stack.top - ctx.authenticated_user = authenticated + set_authenticated_user(authenticated) new_identity = QuayDeferredPermissionUser(authenticated.username, 'username') identity_changed.send(app, identity=new_identity) @@ -102,8 +102,7 @@ def process_token(auth): auth=auth) logger.debug('Successfully validated token: %s', token_data.code) - ctx = _request_ctx_stack.top - ctx.validated_token = token_data + set_validated_token(token_data) identity_changed.send(app, identity=Identity(token_data.code, 'token')) @@ -141,15 +140,18 @@ def process_oauth(f): scope_set = scopes.scopes_from_scope_string(validated.scope) logger.debug('Successfully validated oauth access token: %s with scope: %s', token, scope_set) - - ctx = _request_ctx_stack.top - ctx.authenticated_user = validated.authorized_user + set_authenticated_user(validated.authorized_user) new_identity = QuayDeferredPermissionUser(validated.authorized_user.username, 'username', scope_set) identity_changed.send(app, identity=new_identity) + elif not current_user.is_anonymous(): + logger.debug('Loading user from cookie: %s', current_user.get_id()) + set_authenticated_user_deferred(current_user.get_id()) + loaded = QuayDeferredPermissionUser(current_user.get_id(), 'username') + identity_changed.send(app, identity=loaded) else: - logger.debug('No auth header.') + logger.debug('No auth header or user session.') return f(*args, **kwargs) return wrapper diff --git a/auth/auth_context.py b/auth/auth_context.py index 09ff8d759..16d62f5d9 100644 --- a/auth/auth_context.py +++ b/auth/auth_context.py @@ -1,7 +1,44 @@ +import logging + from flask import _request_ctx_stack +from data import model + + +logger = logging.getLogger(__name__) + def get_authenticated_user(): - return getattr(_request_ctx_stack.top, 'authenticated_user', None) + user = getattr(_request_ctx_stack.top, 'authenticated_user', None) + if not user: + username = getattr(_request_ctx_stack.top, 'authenticated_username', None) + if not username: + logger.debug('No authenticated user or deferred username.') + return None + + logger.debug('Loading deferred authenticated user.') + loaded = model.get_user(username) + set_authenticated_user(loaded) + user = loaded + + logger.debug('Returning authenticated user: %s', user.username) + return user + + +def set_authenticated_user(user_or_robot): + ctx = _request_ctx_stack.top + ctx.authenticated_user = user_or_robot + + +def set_authenticated_user_deferred(username_or_robotname): + logger.debug('Deferring loading of authenticated user object: %s', username_or_robotname) + ctx = _request_ctx_stack.top + ctx.authenticated_username = username_or_robotname + def get_validated_token(): return getattr(_request_ctx_stack.top, 'validated_token', None) + + +def set_validated_token(token): + ctx = _request_ctx_stack.top + ctx.validated_token = token diff --git a/auth/permissions.py b/auth/permissions.py index f3695bf81..b236a9204 100644 --- a/auth/permissions.py +++ b/auth/permissions.py @@ -2,6 +2,7 @@ import logging from flask.ext.principal import (identity_loaded, UserNeed, Permission, Identity, identity_changed) +from flask.ext.login import current_user from collections import namedtuple from functools import partial @@ -171,14 +172,15 @@ def on_identity_loaded(sender, identity): # We have verified an identity, load in all of the permissions if isinstance(identity, QuayDeferredPermissionUser): - logger.debug('Deferring permissions for user: %s' % identity.id) + logger.debug('Deferring permissions for user: %s', identity.id) elif identity.auth_type == 'username': + logger.debug('Switching username permission to deferred object: %s', identity.id) switch_to_deferred = QuayDeferredPermissionUser(identity.id, 'username') identity_changed.send(app, identity=switch_to_deferred) elif identity.auth_type == 'token': - logger.debug('Loading permissions for token: %s' % identity.id) + logger.debug('Loading permissions for token: %s', identity.id) token_data = model.load_token_data(identity.id) repo_grant = _RepositoryNeed(token_data.repository.namespace, @@ -188,4 +190,4 @@ def on_identity_loaded(sender, identity): identity.provides.add(repo_grant) else: - logger.error('Unknown identity auth type: %s' % identity.auth_type) + logger.error('Unknown identity auth type: %s', identity.auth_type) diff --git a/endpoints/api/user.py b/endpoints/api/user.py index e7f4e58f1..2d1c815e2 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -111,11 +111,8 @@ class User(ApiResource): @nickname('getLoggedInUser') def get(self): """ Get user information for the authenticated user. """ - if get_authenticated_user() is None: - return {'anonymous': True} - user = get_authenticated_user() - if not user or user.organization: + if user is None or user.organization: return {'anonymous': True} return user_view(user) diff --git a/endpoints/common.py b/endpoints/common.py index a4747b21f..33feea2a2 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -12,7 +12,7 @@ from data import model from data.queue import dockerfile_build_queue from app import app, login_manager from auth.permissions import QuayDeferredPermissionUser -from api.discovery import swagger_route_data +from endpoints.api.discovery import swagger_route_data logger = logging.getLogger(__name__) @@ -35,9 +35,10 @@ def truthy_param(param): @login_manager.user_loader def load_user(username): - logger.debug('Loading user: %s' % username) + logger.debug('User loader loading deferred user: %s' % username) return _LoginWrappedDBUser(username) + class _LoginWrappedDBUser(UserMixin): def __init__(self, db_username, db_user=None):