diff --git a/auth/basic.py b/auth/basic.py index d551e957e..dfb945acf 100644 --- a/auth/basic.py +++ b/auth/basic.py @@ -34,7 +34,8 @@ def validate_basic_auth(auth_header): return ValidateResult(AuthKind.basic, missing=True) auth_username, auth_password_or_token = credentials - return validate_credentials(auth_username, auth_password_or_token).with_kind(AuthKind.basic) + result, _ = validate_credentials(auth_username, auth_password_or_token) + return result.with_kind(AuthKind.basic) def _parse_basic_auth_header(auth): diff --git a/auth/credentials.py b/auth/credentials.py index daff7eaec..e1e6b5bf0 100644 --- a/auth/credentials.py +++ b/auth/credentials.py @@ -1,5 +1,7 @@ import logging +from enum import Enum + from app import authentication from auth.oauth import validate_oauth_token from auth.validateresult import ValidateResult, AuthKind @@ -11,6 +13,13 @@ logger = logging.getLogger(__name__) ACCESS_TOKEN_USERNAME = '$token' OAUTH_TOKEN_USERNAME = '$oauthtoken' +class CredentialKind(Enum): + user = 'user' + robot = 'robot' + token = ACCESS_TOKEN_USERNAME + oauth_token = OAUTH_TOKEN_USERNAME + + def validate_credentials(auth_username, auth_password_or_token): """ Validates a pair of auth username and password/token credentials. """ # Check for access tokens. @@ -19,14 +28,15 @@ def validate_credentials(auth_username, auth_password_or_token): try: token = model.token.load_token_data(auth_password_or_token) logger.debug('Successfully validated basic auth for access token %s', token.id) - return ValidateResult(AuthKind.credentials, token=token) + return ValidateResult(AuthKind.credentials, token=token), CredentialKind.token except model.DataModelException: logger.warning('Failed to validate basic auth for access token %s', auth_password_or_token) - return ValidateResult(AuthKind.credentials, error_message='Invalid access token') + return (ValidateResult(AuthKind.credentials, error_message='Invalid access token'), + CredentialKind.token) # Check for OAuth tokens. if auth_username == OAUTH_TOKEN_USERNAME: - return validate_oauth_token(auth_password_or_token) + return validate_oauth_token(auth_password_or_token), CredentialKind.oauth_token # Check for robots and users. is_robot = parse_robot_username(auth_username) @@ -34,19 +44,18 @@ def validate_credentials(auth_username, auth_password_or_token): logger.debug('Found basic auth header for robot %s', auth_username) try: robot = model.user.verify_robot(auth_username, auth_password_or_token) - logger.debug('Successfully validated basic auth for robot %s', auth_username) - return ValidateResult(AuthKind.credentials, robot=robot) + return ValidateResult(AuthKind.credentials, robot=robot), CredentialKind.robot except model.InvalidRobotException as ire: logger.warning('Failed to validate basic auth for robot %s: %s', auth_username, ire.message) - return ValidateResult(AuthKind.credentials, error_message=ire.message) + return ValidateResult(AuthKind.credentials, error_message=ire.message), CredentialKind.robot # Otherwise, treat as a standard user. (authenticated, err) = authentication.verify_and_link_user(auth_username, auth_password_or_token, basic_auth=True) if authenticated: logger.debug('Successfully validated basic auth for user %s', authenticated.username) - return ValidateResult(AuthKind.credentials, user=authenticated) + return ValidateResult(AuthKind.credentials, user=authenticated), CredentialKind.user else: logger.warning('Failed to validate basic auth for user %s: %s', auth_username, err) - return ValidateResult(AuthKind.credentials, error_message=err) + return ValidateResult(AuthKind.credentials, error_message=err), CredentialKind.user diff --git a/auth/test/test_credentials.py b/auth/test/test_credentials.py index b4108f167..78438b143 100644 --- a/auth/test/test_credentials.py +++ b/auth/test/test_credentials.py @@ -1,30 +1,36 @@ -from auth.credentials import ACCESS_TOKEN_USERNAME, OAUTH_TOKEN_USERNAME, validate_credentials +from auth.credentials import (ACCESS_TOKEN_USERNAME, OAUTH_TOKEN_USERNAME, validate_credentials, + CredentialKind) from auth.validateresult import AuthKind, ValidateResult from data import model from test.fixtures import * def test_valid_user(app): - result = validate_credentials('devtable', 'password') + result, kind = validate_credentials('devtable', 'password') + assert kind == CredentialKind.user assert result == ValidateResult(AuthKind.credentials, user=model.user.get_user('devtable')) def test_valid_robot(app): robot, password = model.user.create_robot('somerobot', model.user.get_user('devtable')) - result = validate_credentials(robot.username, password) + result, kind = validate_credentials(robot.username, password) + assert kind == CredentialKind.robot assert result == ValidateResult(AuthKind.credentials, robot=robot) def test_valid_token(app): access_token = model.token.create_delegate_token('devtable', 'simple', 'sometoken') - result = validate_credentials(ACCESS_TOKEN_USERNAME, access_token.code) + result, kind = validate_credentials(ACCESS_TOKEN_USERNAME, access_token.code) + assert kind == CredentialKind.token assert result == ValidateResult(AuthKind.credentials, token=access_token) def test_valid_oauth(app): user = model.user.get_user('devtable') oauth_token = list(model.oauth.list_access_tokens_for_user(user))[0] - result = validate_credentials(OAUTH_TOKEN_USERNAME, oauth_token.access_token) + result, kind = validate_credentials(OAUTH_TOKEN_USERNAME, oauth_token.access_token) + assert kind == CredentialKind.oauth_token assert result == ValidateResult(AuthKind.oauth, oauthtoken=oauth_token) def test_invalid_user(app): - result = validate_credentials('devtable', 'somepassword') + result, kind = validate_credentials('devtable', 'somepassword') + assert kind == CredentialKind.user assert result == ValidateResult(AuthKind.credentials, error_message='Invalid Username or Password')