tba-concrete-dpop-confirmation-binding 0.4.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ from hmac import compare_digest
4
+ from typing import Any, Mapping
5
+
6
+ from tba_contracts_identity.resource_server import (
7
+ AccessTokenClaims,
8
+ TokenValidationError,
9
+ )
10
+ from tba_bases_proof_of_possession import (
11
+ ConfirmationBindingValidatorBase,
12
+ ProofOfPossessionDomainBase,
13
+ )
14
+ from tba_contracts_security_trust import (
15
+ CapabilityMap,
16
+ DPoPBinding,
17
+ VerificationResult,
18
+ VerifyRequest,
19
+ )
20
+
21
+
22
+ def _cnf_from(value: AccessTokenClaims | Mapping[str, Any]) -> Mapping[str, Any]:
23
+ return value.cnf if isinstance(value, AccessTokenClaims) else value
24
+
25
+
26
+ class DpopBindingValidator(ProofOfPossessionDomainBase):
27
+ """Compare a DPoP JWK thumbprint with the corresponding cnf member."""
28
+
29
+ confirmation_member = "jkt"
30
+
31
+ def supports(self) -> CapabilityMap:
32
+ return CapabilityMap(
33
+ ops={"verify": ("dpop",)},
34
+ modes=("dpop",),
35
+ features=("cnf-binding", "proof-of-possession"),
36
+ )
37
+
38
+ def validate_confirmation(
39
+ self, cnf: Mapping[str, Any], binding: DPoPBinding | None
40
+ ) -> bool:
41
+ expected = str(cnf.get(self.confirmation_member) or "").strip()
42
+ presented = str(getattr(binding, "jwk_thumbprint", "") or "").strip()
43
+ return (
44
+ binding is not None
45
+ and bool(expected)
46
+ and compare_digest(presented, expected)
47
+ )
48
+
49
+ async def verify(self, request: VerifyRequest) -> VerificationResult:
50
+ binding = request.context.get("binding")
51
+ cnf = request.context.get("cnf", {})
52
+ if not isinstance(cnf, Mapping):
53
+ return VerificationResult(
54
+ valid=False, reason="DPoP cnf context must be a mapping"
55
+ )
56
+ if not isinstance(binding, DPoPBinding):
57
+ return VerificationResult(valid=False, reason="missing DPoP binding")
58
+ valid = self.validate_confirmation(cnf, binding)
59
+ return VerificationResult(
60
+ valid=valid,
61
+ reason=None if valid else "DPoP binding mismatch",
62
+ claims=binding.confirmation_claim,
63
+ meta={"method": "dpop"},
64
+ )
65
+
66
+
67
+ class DpopCnfBindingValidator(ConfirmationBindingValidatorBase):
68
+ """Validate DPoP confirmation material on access-token claims."""
69
+
70
+ def __init__(
71
+ self,
72
+ confirmation_member: str = "jkt",
73
+ *,
74
+ provider: DpopBindingValidator | None = None,
75
+ ) -> None:
76
+ self.provider = provider or DpopBindingValidator()
77
+ self.provider.confirmation_member = confirmation_member
78
+
79
+ def supports(self) -> CapabilityMap:
80
+ return CapabilityMap(ops={"confirmation-binding": ("dpop",)}, modes=("dpop",))
81
+
82
+ @property
83
+ def confirmation_member(self) -> str:
84
+ return self.provider.confirmation_member
85
+
86
+ def validate_confirmation(
87
+ self, cnf: Mapping[str, Any], binding: DPoPBinding | None
88
+ ) -> bool:
89
+ return self.provider.validate_confirmation(cnf, binding)
90
+
91
+ def validate(
92
+ self,
93
+ claims: AccessTokenClaims | Mapping[str, Any],
94
+ binding: DPoPBinding | None,
95
+ ) -> bool:
96
+ if not self.validate_confirmation(_cnf_from(claims), binding):
97
+ raise TokenValidationError("DPoP binding mismatch")
98
+ return True
99
+
100
+
101
+ __all__ = ["DpopBindingValidator", "DpopCnfBindingValidator"]
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: tba-concrete-dpop-confirmation-binding
3
+ Version: 0.4.0.dev2
4
+ Summary: Deterministic DPoP confirmation binding validation.
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.10,<3.15
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: tba-bases-proof-of-possession (==0.4.0.dev2)
14
+ Requires-Dist: tba-contracts-identity (==0.4.0.dev2)
15
+ Requires-Dist: tba-contracts-security-trust (==0.1.0)
@@ -0,0 +1,5 @@
1
+ tba_concrete_dpop_confirmation_binding/__init__.py,sha256=HPAf-UXLiQkKc70X0b7YqaKlutP_K0Fjt3S9JIVcCys,3313
2
+ tba_concrete_dpop_confirmation_binding/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
+ tba_concrete_dpop_confirmation_binding-0.4.0.dev2.dist-info/METADATA,sha256=18SZWUedujcGlHOUOHGVobd3Oj-142vjIqv15x47AsY,679
4
+ tba_concrete_dpop_confirmation_binding-0.4.0.dev2.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
5
+ tba_concrete_dpop_confirmation_binding-0.4.0.dev2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.5.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any