1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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}"
)
|