diff --git a/tiled/_tests/test_authentication.py b/tiled/_tests/test_authentication.py index 6995d4cec..93b76b61a 100644 --- a/tiled/_tests/test_authentication.py +++ b/tiled/_tests/test_authentication.py @@ -13,7 +13,7 @@ from ..adapters.mapping import MapAdapter from ..client import Context, from_context from ..client.auth import CannotRefreshAuthentication -from ..client.context import clear_default_identity, get_default_identity +from ..client.context import CannotPrompt, clear_default_identity, get_default_identity from ..server import authentication from ..server.app import build_app_from_config from .utils import fail_with_status_code @@ -94,6 +94,41 @@ def test_password_auth(enter_username_password, config): from_context(context, username="alice") +def test_password_auth_hook(config): + with Context.from_app(build_app_from_config(config)) as context: + # Passing prompt_for_reauthentication=False should riase an + with pytest.raises(CannotPrompt): + context.authenticate( + username="alice", password="secret1", prompt_for_reauthentication=False + ) + + # Log in as Alice. + context.authenticate( + username="alice", password="secret1", prompt_for_reauthentication=True + ) + assert "authenticated as 'alice'" in repr(context) + context.logout() + + # Log in as Bob. + context.authenticate( + username="bob", password="secret2", prompt_for_reauthentication=True + ) + assert "authenticated as 'bob'" in repr(context) + context.logout() + + # Bob's password should not work for Alice. + with fail_with_status_code(HTTP_401_UNAUTHORIZED): + context.authenticate( + username="alice", password="secret2", prompt_for_reauthentication=True + ) + + # Empty password should not work. + with fail_with_status_code(HTTP_401_UNAUTHORIZED): + context.authenticate( + username="alice", password="", prompt_for_reauthentication=True + ) + + def test_logout(enter_username_password, config, tmpdir): """ Logging out revokes the session, such that it cannot be refreshed. diff --git a/tiled/client/context.py b/tiled/client/context.py index 551f2292a..bd9f44f6a 100644 --- a/tiled/client/context.py +++ b/tiled/client/context.py @@ -27,7 +27,7 @@ def prompt_for_credentials(username, password): """ Utility function that displays a username prompt. """ - if username and password: + if username is not None and password is not None: # If both are provided, return them as-is, without prompting. return username, password elif username: @@ -539,7 +539,7 @@ def authenticate( except CannotRefreshAuthentication: # Continue below, where we will prompt for log in. self.http_client.auth = None - if not prompt_for_reauthentication: + if not prompt_for_reauthentication and not password: raise else: # We have a live session for the specified provider and username already. @@ -556,7 +556,7 @@ def authenticate( to force it to prompt. - Provide an API key in the environment variable TILED_API_KEY for Tiled to use. - Catch the CannotPrompt exception and handle it in your application if providing both - username and password programmatically. + username and password programmatically with prompt_for_reauthentication=True. """ ) self.http_client.auth = None