|
6 | 6 | import pytest |
7 | 7 | from joserfc import jwk as jose_jwk |
8 | 8 | from joserfc import jwt |
| 9 | +from joserfc.jws import JWSRegistry |
| 10 | +from joserfc.registry import HeaderParameter |
9 | 11 | from pytest_httpx import HTTPXMock |
10 | 12 |
|
11 | 13 | from fastmcp import FastMCP |
@@ -182,6 +184,73 @@ def test_create_token_with_scopes(self, rsa_key_pair: RSAKeyPair): |
182 | 184 | # We'll validate the scopes in the BearerToken tests |
183 | 185 |
|
184 | 186 |
|
| 187 | +class TestJWTVerifierHeaders: |
| 188 | + async def test_non_critical_private_header_is_allowed( |
| 189 | + self, rsa_key_pair: RSAKeyPair |
| 190 | + ): |
| 191 | + signing_key = jose_jwk.import_key( |
| 192 | + rsa_key_pair.private_key.get_secret_value(), |
| 193 | + "RSA", |
| 194 | + ) |
| 195 | + token = jwt.encode( |
| 196 | + { |
| 197 | + "alg": "RS256", |
| 198 | + "cat": "cl_example", |
| 199 | + }, |
| 200 | + { |
| 201 | + "sub": "test-user", |
| 202 | + "iss": "https://test.example.com", |
| 203 | + "exp": int(time.time()) + 3600, |
| 204 | + }, |
| 205 | + signing_key, |
| 206 | + algorithms=["RS256"], |
| 207 | + registry=JWSRegistry(strict_check_header=False), |
| 208 | + ) |
| 209 | + verifier = JWTVerifier( |
| 210 | + public_key=rsa_key_pair.public_key, |
| 211 | + issuer="https://test.example.com", |
| 212 | + ) |
| 213 | + |
| 214 | + access_token = await verifier.verify_token(token) |
| 215 | + |
| 216 | + assert access_token is not None |
| 217 | + assert access_token.client_id == "test-user" |
| 218 | + |
| 219 | + async def test_critical_private_header_is_rejected(self, rsa_key_pair: RSAKeyPair): |
| 220 | + signing_key = jose_jwk.import_key( |
| 221 | + rsa_key_pair.private_key.get_secret_value(), |
| 222 | + "RSA", |
| 223 | + ) |
| 224 | + token = jwt.encode( |
| 225 | + { |
| 226 | + "alg": "RS256", |
| 227 | + "crit": ["cat"], |
| 228 | + "cat": "cl_example", |
| 229 | + }, |
| 230 | + { |
| 231 | + "sub": "test-user", |
| 232 | + "iss": "https://test.example.com", |
| 233 | + "exp": int(time.time()) + 3600, |
| 234 | + }, |
| 235 | + signing_key, |
| 236 | + algorithms=["RS256"], |
| 237 | + registry=JWSRegistry( |
| 238 | + header_registry={ |
| 239 | + "cat": HeaderParameter("Custom private header", "str") |
| 240 | + }, |
| 241 | + strict_check_header=False, |
| 242 | + ), |
| 243 | + ) |
| 244 | + verifier = JWTVerifier( |
| 245 | + public_key=rsa_key_pair.public_key, |
| 246 | + issuer="https://test.example.com", |
| 247 | + ) |
| 248 | + |
| 249 | + access_token = await verifier.verify_token(token) |
| 250 | + |
| 251 | + assert access_token is None |
| 252 | + |
| 253 | + |
185 | 254 | class TestSymmetricKeyJWT: |
186 | 255 | """Tests for JWT verification using symmetric keys (HMAC algorithms).""" |
187 | 256 |
|
|
0 commit comments