Skip to content

Commit bd98453

Browse files
feat(auth): add request authentication helper
1 parent f0854d4 commit bd98453

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

server/auth.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,19 @@ def extract_bearer_token(auth_header: str | None) -> str | None:
4949
return None
5050
token = auth_header.removeprefix("Bearer ").strip()
5151
return token or None
52+
53+
54+
def authenticate_request(
55+
auth_header: str | None,
56+
required_role: str | None = None,
57+
) -> dict[str, Any]:
58+
"""Validate a bearer token header and optionally enforce a role."""
59+
token = extract_bearer_token(auth_header)
60+
if token is None:
61+
raise PermissionError("Missing or invalid bearer token")
62+
63+
payload = decode_access_token(token)
64+
if required_role and payload.get("role") != required_role:
65+
raise PermissionError(f"Role '{required_role}' is required")
66+
67+
return payload

server/tests/test_auth.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from server.auth import (
44
ROLE_ADMIN,
55
ROLE_USER,
6+
authenticate_request,
67
create_access_token,
78
decode_access_token,
89
extract_bearer_token,
@@ -50,3 +51,30 @@ def test_user_role_token_supported():
5051
token = create_access_token("bob", ROLE_USER, expires_hours=1)
5152
payload = decode_access_token(token)
5253
assert payload["role"] == ROLE_USER
54+
55+
56+
def test_authenticate_request_accepts_valid_bearer_token():
57+
token = create_access_token("alice", ROLE_ADMIN, expires_hours=1)
58+
59+
payload = authenticate_request(f"Bearer {token}")
60+
61+
assert payload["sub"] == "alice"
62+
assert payload["role"] == ROLE_ADMIN
63+
64+
65+
def test_authenticate_request_rejects_missing_bearer_token():
66+
try:
67+
authenticate_request(None)
68+
assert False, "Expected PermissionError"
69+
except PermissionError as exc:
70+
assert "Missing or invalid bearer token" in str(exc)
71+
72+
73+
def test_authenticate_request_enforces_required_role():
74+
token = create_access_token("bob", ROLE_USER, expires_hours=1)
75+
76+
try:
77+
authenticate_request(f"Bearer {token}", required_role=ROLE_ADMIN)
78+
assert False, "Expected PermissionError"
79+
except PermissionError as exc:
80+
assert "Role 'admin' is required" in str(exc)

0 commit comments

Comments
 (0)