Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/jwt/jwk_set_cache.py: 39%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

23 statements  

1import time 

2from typing import Any, Optional, Union 

3 

4from .api_jwk import PyJWKSet, PyJWTSetWithTimestamp 

5from .exceptions import PyJWKSetError 

6 

7 

8class JWKSetCache: 

9 def __init__(self, lifespan: float) -> None: 

10 self.jwk_set_with_timestamp: Optional[PyJWTSetWithTimestamp] = None 

11 self.lifespan = lifespan 

12 

13 def put(self, jwk_set: Optional[Union[PyJWKSet, dict[str, Any]]]) -> None: 

14 """Cache *jwk_set*, or clear the cache when it is ``None``. 

15 

16 Accepts either an already-parsed ``PyJWKSet`` or the raw JWKS 

17 payload it is parsed from, and always stores it parsed so that 

18 reads never have to parse the keys again. 

19 

20 :raises PyJWKSetError: If *jwk_set* is neither a ``PyJWKSet`` nor a 

21 JWKS payload containing usable keys. 

22 """ 

23 if jwk_set is None: 

24 # clear cache 

25 self.jwk_set_with_timestamp = None 

26 return 

27 

28 if not isinstance(jwk_set, PyJWKSet): 

29 if not isinstance(jwk_set, dict): 

30 raise PyJWKSetError("Invalid JWK Set value") 

31 jwk_set = PyJWKSet.from_dict(jwk_set) 

32 

33 self.jwk_set_with_timestamp = PyJWTSetWithTimestamp(jwk_set) 

34 

35 def get(self) -> Optional[PyJWKSet]: 

36 if self.jwk_set_with_timestamp is None or self.is_expired(): 

37 return None 

38 

39 return self.jwk_set_with_timestamp.get_jwk_set() 

40 

41 def is_expired(self) -> bool: 

42 return ( 

43 self.jwk_set_with_timestamp is not None 

44 and self.lifespan > -1 

45 and time.monotonic() 

46 > self.jwk_set_with_timestamp.get_timestamp() + self.lifespan 

47 )