py.lib.aw_web_tools
2024-02-25
Child:4d3b509e0967
py.lib.aw_web_tools/src/aw_web_tools/jwt.py
..init
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/aw_web_tools/jwt.py Sun Feb 25 15:18:36 2024 +0300 1.3 @@ -0,0 +1,57 @@ 1.4 +# coding: utf-8 1.5 + 1.6 +import jwt 1.7 +from datetime import datetime, timedelta 1.8 +from typing import Optional 1.9 + 1.10 +JWT_HASH_ALGO = 'HS512' 1.11 + 1.12 + 1.13 +class JWTError(Exception): 1.14 + pass 1.15 + 1.16 + 1.17 +class JWTAuthError(JWTError): 1.18 + """\ 1.19 + Провалена проверка токена на допустимость по подписи времени или прочее 1.20 + """ 1.21 + 1.22 + 1.23 +class JWTHelper(object): 1.24 + def __init__(self, key: str): 1.25 + self.key = key 1.26 + 1.27 + def encode(self, data: dict, timeout: Optional[int] = None) -> str: 1.28 + if timeout is not None: 1.29 + data['exp'] = datetime.utcnow() + timedelta(seconds=timeout) 1.30 + 1.31 + return jwt.encode(data, key=self.key, algorithm=JWT_HASH_ALGO) 1.32 + 1.33 + def decode(self, token: str, check_timeout: bool = False) -> dict: 1.34 + opts = { 1.35 + 'algorithms': [JWT_HASH_ALGO, ] 1.36 + } 1.37 + 1.38 + if check_timeout: 1.39 + opts['options'] = {'require': {'exp'}} 1.40 + 1.41 + if token is None: 1.42 + raise JWTAuthError('Ключ отсутствует') 1.43 + else: 1.44 + token = token.encode('utf-8') 1.45 + 1.46 + try: 1.47 + return jwt.decode(jwt=token, key=self.key, **opts) 1.48 + 1.49 + except (jwt.InvalidIssuerError, jwt.InvalidSignatureError, jwt.ExpiredSignatureError) as e: 1.50 + raise JWTAuthError(str(e)) 1.51 + 1.52 + except jwt.PyJWTError as e: 1.53 + raise JWTError(f'{type(e).__name__}: {e}') 1.54 + 1.55 + @classmethod 1.56 + def make_fabric(cls, key: str): 1.57 + def f(): 1.58 + return cls(key=key) 1.59 + 1.60 + return f