Coverage for backend/django/authentication/token_helpers.py: 94%

27 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-05-13 02:47 +0000

1"""Testing-only helpers for synthetic proxy JWTs. 

2 

3These helpers generate unsigned-trust test tokens (HS256 with a hardcoded 

4development secret) used by local/debug middleware and test suites. 

5 

6Do not use this module for production authentication or authorization flows. 

7Production token handling must rely on real upstream tokens and signature 

8verification against trusted keys. 

9""" 

10 

11from __future__ import annotations 

12 

13import os 

14from collections.abc import Iterable 

15from typing import Any 

16 

17import jwt 

18from django.conf import settings 

19 

20_BASE_ACCESS_TOKEN_CLAIMS = { 

21 "exp": 1756268489, 

22 "iat": 1756268189, 

23 "auth_time": 1756268189, 

24 "jti": "f7cf0ea7-6e22-4f37-be16-32399127e500", 

25 "iss": "http://issuer.com", 

26 "aud": ["platform"], 

27 "sub": "a60d7a1e-7d65-4b8d-92a9-1c0dcc1fe44f", 

28 "typ": "Bearer", 

29 "azp": "platform", 

30 "sid": "70d7f166-facb-4c09-ad27-bc3f6ee897ce", 

31 "acr": "1", 

32 "allowed-origins": ["*"], 

33 "email_verified": True, 

34 "name": "John Smith", 

35 "preferred_username": "example@email.com", 

36 "given_name": "John", 

37 "family_name": "Smith", 

38 "email": "example@email.com", 

39} 

40 

41 

42def _ensure_not_production_mode() -> None: 

43 if "UNDER_PYTEST" not in os.environ and not settings.DEBUG: 

44 raise RuntimeError( 

45 "Synthetic access-token test helpers are disabled when UNDER_PYTEST is False and debug is not enabled." 

46 ) 

47 

48 

49def build_proxy_access_token( 

50 scopes: Iterable[str] | None = None, 

51 *, 

52 extra_claims: dict[str, Any] | None = None, 

53) -> str: 

54 """Build a synthetic proxy-style JWT for tests/debug only. 

55 

56 Warning: 

57 This function is not safe for production use. 

58 It uses a static signing secret and produces tokens intended only for 

59 local test execution and debug middleware defaults. 

60 """ 

61 _ensure_not_production_mode() 

62 

63 scope_values = ["openid", "profile", "email", *(scopes or [])] 

64 normalized_scopes = [item for item in dict.fromkeys(scope_values) if item] 

65 

66 payload = dict(_BASE_ACCESS_TOKEN_CLAIMS) 

67 payload["scope"] = " ".join(normalized_scopes) 

68 

69 if extra_claims: 

70 payload.update(extra_claims) 

71 

72 return jwt.encode(payload, "secret", algorithm="HS256") 

73 

74 

75def build_human_user_access_token() -> str: 

76 """Return a synthetic token with the configured HumanUser scope. 

77 

78 Testing/debug only. Not for production authentication. 

79 """ 

80 return build_proxy_access_token(scopes=[settings.AUTH_GENERAL_SCOPE_KEY]) 

81 

82 

83def build_excel_client_access_token() -> str: 

84 """Return a synthetic token with the configured ExcelClient scope. 

85 

86 Testing/debug only. Not for production authentication. 

87 """ 

88 return build_proxy_access_token(scopes=[settings.AUTH_EXCEL_SCOPE_KEY]) 

89 

90 

91# Backward-compatible aliases for existing imports. 

92def build_general_access_token() -> str: 

93 return build_human_user_access_token() 

94 

95 

96def build_delegated_access_token() -> str: 

97 return build_excel_client_access_token()