diff options
| author | Claude Sonnet 4.6 | 2026-06-15 17:37:00 +0000 |
|---|---|---|
| committer | Frederick Muriuki Muriithi | 2026-06-15 12:59:34 -0500 |
| commit | 3ac89fabe4070b4c1343f93f4e2bca9d0e612cbc (patch) | |
| tree | 228c8b39505955d2a7771b7785bf4f005452a538 | |
| parent | b34a606fbffcf3c2baf1ceb234f6990928d82564 (diff) | |
| download | gn-integration-tests-3ac89fabe4070b4c1343f93f4e2bca9d0e612cbc.tar.gz | |
tests: add TestTokenGrant auth-flow tests
Test that POST /auth/token with valid admin credentials returns 200, includes an access_token, sets token_type to bearer, and grants at least the requested scopes.
| -rw-r--r-- | tests/test_gn_auth_auth_flow.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/tests/test_gn_auth_auth_flow.py b/tests/test_gn_auth_auth_flow.py new file mode 100644 index 0000000..ab26f10 --- /dev/null +++ b/tests/test_gn_auth_auth_flow.py @@ -0,0 +1,79 @@ +""" +Auth-flow integration tests for gn-auth. + +Require live credentials set up by the CI test-session lifecycle +(create-test-users / create-test-oauth2-client). Run with: + + pytest -m "gn_auth and auth_flow" + +Environment variables: + + GN_TEST_EMAIL admin test-user email + GN_TEST_PASSWORD admin test-user password + GN_TEST_BASIC_EMAIL unprivileged test-user email + GN_TEST_BASIC_PASSWORD unprivileged test-user password + GN_OAUTH2_CLIENT_ID OAuth2 client UUID + GN_OAUTH2_CLIENT_SECRET OAuth2 client secret +""" + +import pytest + +pytestmark = [pytest.mark.gn_auth, pytest.mark.auth_flow] + + +# --------------------------------------------------------------------------- +# POST /auth/token — password grant with valid credentials +# --------------------------------------------------------------------------- + +class TestTokenGrant: + """Password grant with valid admin credentials issues a usable token.""" + + def _post_token(self, gn_auth_url, http, oauth2_credentials, + scope="profile group resource"): + email, password, client_id, client_secret = oauth2_credentials + return http.post( + f"{gn_auth_url}/auth/token", + json={ + "grant_type": "password", + "username": email, + "password": password, + "scope": scope, + "client_id": client_id, + "client_secret": client_secret, + }, + timeout=30, + ) + + def test_valid_credentials_return_200( + self, gn_auth_url, http, oauth2_credentials): + resp = self._post_token(gn_auth_url, http, oauth2_credentials) + assert resp.status_code == 200, ( + f"Expected 200 from token endpoint, got {resp.status_code}: {resp.text}" + ) + + def test_response_contains_access_token( + self, gn_auth_url, http, oauth2_credentials): + resp = self._post_token(gn_auth_url, http, oauth2_credentials) + data = resp.json() + assert "access_token" in data, ( + f"Token response missing 'access_token': {data}" + ) + + def test_token_type_is_bearer( + self, gn_auth_url, http, oauth2_credentials): + resp = self._post_token(gn_auth_url, http, oauth2_credentials) + token_type = resp.json().get("token_type", "") + assert token_type.lower() == "bearer", ( + f"Expected token_type 'bearer', got: {token_type!r}" + ) + + def test_granted_scope_covers_requested( + self, gn_auth_url, http, oauth2_credentials): + requested = {"profile", "group", "resource"} + resp = self._post_token(gn_auth_url, http, oauth2_credentials) + data = resp.json() + assert "scope" in data, f"Token response missing 'scope': {data}" + granted = set(data["scope"].split()) + assert requested <= granted, ( + f"Requested scopes {requested} not all in granted scopes {granted}" + ) |
