import time import jwt import pytest from flask import url_for from atlas_um.tokens.bearer_tokens import DNABearerToken from atlas_um.helpers.either import Right, Left from tests.atlas_um.factories import DNAAccountFactory from tests.atlas_um.pytest_helpers import get_cookie class TestToken: FAKE_HOST = "atlas_um.test" def test_success(self, app, pgdb_session): token = DNABearerToken(DNAAccountFactory.build()).encode() with app.test_request_context(): url = url_for("token.get_token") with app.test_client() as client: client.set_cookie( app.config.get("DNA_BEARER_TOKEN_COOKIE_NAME"), token, domain=self.FAKE_HOST, httponly=True, ) resp = client.get(url) expires_in = jwt.decode(token, options={"verify_signature": False})[ "exp" ] - int(time.time()) assert resp.status_code == 200 assert resp.json["access_token"] == token assert resp.json["token_type"] == "Bearer" assert resp.json["expires_in"] == expires_in def test_failure(self, app): with app.test_request_context(): url = url_for("token.get_token") with app.test_client() as client: resp = client.get(url) assert resp.status_code == 401 class TestRefreshToken: FAKE_HOST = "atlas_um.test" @pytest.fixture def app_config(self): def inner(app): app.config["SERVER_NAME"] = self.FAKE_HOST app.config["ALLOWED_HOSTS"] = [self.FAKE_HOST] return inner @pytest.mark.parametrize( "token_source", [ "cookie", "body", ], ) def test_success(self, app, pgdb_session, faker, mocker, token_source): dna_account = DNAAccountFactory.build() token = faker.pystr() new_token = faker.pystr() new_access_token = faker.pystr() mocked_service = mocker.patch( "atlas_um.tokens.services.RotateTokensService.execute" ) mocked_service.return_value = Right( (new_token, new_access_token, dna_account) ) mocker.patch( "tldextract.extract" ).return_value.registered_domain = self.FAKE_HOST with app.test_request_context(): url = url_for("token.refresh_token_view", _external=True) with app.test_client() as client: if token_source == "cookie": client.set_cookie( app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME"), token, domain=self.FAKE_HOST, httponly=True, ) data = {} else: data = {"refresh_token": token} resp = client.post(url, data=data) assert resp.status_code == 200 assert mocked_service.call_args_list == [mocker.call(token, None)] assert resp.json == { "access_token": new_access_token, "expires_in": 300, "refresh_token": new_token, "token_type": "Bearer", } bearer_cookie = get_cookie( resp, app.config.get("DNA_BEARER_TOKEN_COOKIE_NAME") ) assert ( bearer_cookie.get(app.config.get("DNA_BEARER_TOKEN_COOKIE_NAME")) == new_access_token ) assert "HttpOnly" in bearer_cookie assert "Secure" in bearer_cookie assert bearer_cookie.get("Domain") == self.FAKE_HOST assert ( int(bearer_cookie["Max-Age"]) == app.config["TOKEN_COOKIES_MAX_AGE"] ) refresh_cookie = get_cookie( resp, app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME") ) assert ( refresh_cookie.get(app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME")) == new_token ) assert "HttpOnly" in refresh_cookie assert "Secure" in refresh_cookie assert refresh_cookie.get("Domain") == self.FAKE_HOST assert ( int(refresh_cookie["Max-Age"]) == app.config["TOKEN_COOKIES_MAX_AGE"] ) def test_failure_no_token(self, app, pgdb_session, faker, mocker): with app.test_request_context(): url = url_for("token.refresh_token_view", _external=True) with app.test_client() as client: resp = client.post(url) assert resp.status_code == 401 assert resp.json is None bearer_cookie = get_cookie( resp, app.config.get("DNA_BEARER_TOKEN_COOKIE_NAME") ) assert bearer_cookie is None refresh_cookie = get_cookie( resp, app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME") ) assert refresh_cookie is None @pytest.mark.parametrize( "token_source", [ "cookie", "body", ], ) def test_failure_wrong_token( self, app, pgdb_session, faker, mocker, token_source ): token = faker.pystr() mocked_service = mocker.patch( "atlas_um.tokens.services.RotateTokensService.execute" ) mocked_service.return_value = Left(None) with app.test_request_context(): url = url_for("token.refresh_token_view", _external=True) with app.test_client() as client: if token_source == "cookie": client.set_cookie( app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME"), token, domain=self.FAKE_HOST, httponly=True, ) data = {} else: data = {"refresh_token": token} resp = client.post(url, data=data) assert resp.status_code == 401 assert resp.json is None bearer_cookie = get_cookie( resp, app.config.get("DNA_BEARER_TOKEN_COOKIE_NAME") ) assert bearer_cookie is None refresh_cookie = get_cookie( resp, app.config.get("DNA_REFRESH_TOKEN_COOKIE_NAME") ) assert refresh_cookie is None