import time import jwt from flask import _request_ctx_stack from werkzeug.http import dump_cookie from flask_atlas_auth.manager import AuthManager from flask_atlas_auth.models import User, AnonymousUser from .helpers import TestClaim, TestAudienceClaim class TestAuthManager: def test_init_app(self, mocker): app = mocker.MagicMock() mocker.patch( "flask_atlas_auth.manager.AuthManager.public_key", return_value="key", new_callable=mocker.PropertyMock, ) manager = AuthManager() manager.init_app(app) assert app.auth_manager == manager assert app.after_request.call_args_list == [ mocker.call(manager._load_user), mocker.call(manager._refresh_token), ] def test_get_token_cookie(self, app, faker): fake_token = faker.pystr() header = dump_cookie( app.config.get("ATLAS_BEARER_TOKEN_COOKIE_NAME"), fake_token ) with app.test_request_context(environ_base={"HTTP_COOKIE": header}): token = app.auth_manager._get_token() assert token == fake_token def test_get_token_auth_header(self, app, faker): fake_token = faker.pystr() with app.test_request_context( environ_base={"HTTP_AUTHORIZATION": f"Bearer {fake_token}"} ): token = app.auth_manager._get_token() assert token == fake_token def test_get_validation_params_aud(self, app, mocker): test_claimset = { "aud": "test_aud", f"{app.get('ATLAS_RELATED_CLAIMS_NAMESPACE')}/{TestClaim.path}": { TestClaim.value_field: TestClaim.Values.test_value1.value }, "other_product/other_path": { "id": "other_id", "slug": "other_slug", }, } mocked_jwt_decode = mocker.patch("jwt.decode") mocked_jwt_decode.return_value = test_claimset assert app.auth_manager._get_validation_params(test_claimset) == { "audience": TestAudienceClaim.Values.list(), "leeway": AuthManager.DEFAULT_TOKEN_LEEWAY } def test_get_validation_params_no_aud(self, app, mocker): test_claimset = { f"{app.get('ATLAS_RELATED_CLAIMS_NAMESPACE')}/{TestClaim.path}": { TestClaim.value_field: TestClaim.Values.test_value1.value }, "other_product/other_path": { "id": "other_id", "slug": "other_slug", }, } mocked_jwt_decode = mocker.patch("jwt.decode") mocked_jwt_decode.return_value = test_claimset assert app.auth_manager._get_validation_params(test_claimset) == { "leeway": AuthManager.DEFAULT_TOKEN_LEEWAY } def test_get_assigned_claims(self, app): test_claimset = { f"{app.config.get('ATLAS_RELATED_CLAIMS_NAMESPACE')}/{TestClaim.path}": { # noqa TestClaim.value_field: TestClaim.Values.test_value1.value }, "other_product/other_path": { "id": "other_id", "slug": "other_slug", }, } expected_claims = [TestClaim(TestClaim.Values.test_value1)] actual_claims = app.auth_manager._get_assigned_claims(test_claimset) assert actual_claims == expected_claims def test_update_request_context_with_user_empty(self, app, faker): with app.test_request_context(): app.auth_manager._update_request_context_with_user(None) ctx = _request_ctx_stack.top ctx.user = AnonymousUser() def test_update_request_context_with_user_non_empty(self, app, faker): with app.test_request_context(): user = User(faker.pystr(), faker.email(), faker.pystr(), []) app.auth_manager._update_request_context_with_user(user) ctx = _request_ctx_stack.top ctx.user = user def test_load_user_failure_no_token(self, app, mocker): with app.test_request_context(): mocked_anonymous = mocker.patch( "flask_atlas_auth.models.AnonymousUser" ).return_value expected_response = mocker.MagicMock() mocked_update_request_context_with_user = mocker.patch( "flask_atlas_auth.manager.AuthManager." "_update_request_context_with_user" ) actual_response = app.auth_manager._load_user(expected_response) assert expected_response == actual_response assert mocked_update_request_context_with_user.call_args_list == [ mocker.call(mocked_anonymous) ] def test_load_user_failure_invalid_token(self, app, mocker, fake_token): # real like token with not matching signature corrupted_token = fake_token[:-1] header = dump_cookie( app.config.get("ATLAS_BEARER_TOKEN_COOKIE_NAME"), corrupted_token ) mocked_anonymous = mocker.patch( "flask_atlas_auth.models.AnonymousUser" ).return_value with app.test_request_context(environ_base={"HTTP_COOKIE": header}): expected_response = mocker.MagicMock() mocked_update_request_context_with_user = mocker.patch( "flask_atlas_auth.manager.AuthManager." "_update_request_context_with_user" ) mocker.patch("jwt.decode") actual_response = app.auth_manager._load_user(expected_response) assert expected_response == actual_response assert mocked_update_request_context_with_user.call_args_list == [ mocker.call(mocked_anonymous) ] def test_load_user_success(self, app, mocker, fake_token): fake_payload = jwt.decode( fake_token, options={"verify_signature": False} ) expected_user = User( fake_payload.get("sub"), fake_payload.get("email"), fake_payload.get("name"), [], ) header = dump_cookie( app.config.get("ATLAS_BEARER_TOKEN_COOKIE_NAME"), fake_token ) mocker.patch("jwt.decode").return_value = fake_payload with app.test_request_context(environ_base={"HTTP_COOKIE": header}): expected_response = mocker.MagicMock() mocked_update_request_context_with_user = mocker.patch( "flask_atlas_auth.manager.AuthManager." "_update_request_context_with_user" ) actual_response = app.auth_manager._load_user(expected_response) assert expected_response == actual_response assert mocked_update_request_context_with_user.call_args_list == [ mocker.call(expected_user) ] def test_refresh_token_success(self, app, mocker, fake_token, faker): fake_payload = jwt.decode( fake_token, options={"verify_signature": False} ) fake_refresh_data = { "access_token": faker.pystr(), "refresh_token": faker.pystr(), } fake_refresh_token = faker.pystr() header_bearer = dump_cookie( app.config.get("ATLAS_BEARER_TOKEN_COOKIE_NAME"), fake_token ) header_refresh = dump_cookie( app.config.get("ATLAS_REFRESH_TOKEN_COOKIE_NAME"), fake_refresh_token ) fake_payload["exp"] = int(time.time()) - 61 mocker.patch("jwt.decode").return_value = fake_payload mocked_post = mocker.patch("requests.post").return_value mocked_post.status_code = 200 mocked_post.json.return_value = fake_refresh_data with app.test_request_context( environ_base={"HTTP_COOKIE": f"{header_bearer}; {header_refresh}"} ): mocked_response = mocker.MagicMock() actual_response = app.auth_manager._refresh_token(mocked_response) assert actual_response.method_calls == [ mocker.call.set_cookie( app.config["ATLAS_BEARER_TOKEN_COOKIE_NAME"], fake_refresh_data["access_token"], httponly=True, domain=None, secure=True, max_age=AuthManager.DEFAULT_COOKIES_MAX_AGE, ), mocker.call.set_cookie( app.config["ATLAS_REFRESH_TOKEN_COOKIE_NAME"], fake_refresh_data["refresh_token"], httponly=True, domain=None, secure=True, max_age=AuthManager.DEFAULT_COOKIES_MAX_AGE, ), ]