py.lib
2022-08-19
Parent:84b54a8a6d4c
py.lib/webapp/jwt_util.py
. Рефакторинг имени в dataclass_utils.py * Изменение по типу модуля dataclass_utils.py в модуле config_parse_helper.py
| awgur@31 | 1 # coding: utf-8 |
| awgur@31 | 2 |
| awgur@31 | 3 import jwt |
| awgur@31 | 4 from datetime import datetime, timedelta |
| awgur@31 | 5 from typing import Optional |
| awgur@31 | 6 |
| awgur@31 | 7 JWT_HASH_ALGO = 'HS512' |
| awgur@31 | 8 |
| awgur@31 | 9 |
| awgur@31 | 10 class JWTError(Exception): |
| awgur@31 | 11 pass |
| awgur@31 | 12 |
| awgur@31 | 13 |
| awgur@31 | 14 class JWTAuthError(JWTError): |
| awgur@31 | 15 """\ |
| awgur@31 | 16 Провалена проверка токена на допустимость по подписи времени или прочее |
| awgur@31 | 17 """ |
| awgur@31 | 18 |
| awgur@31 | 19 |
| awgur@31 | 20 class JWTHelper(object): |
| awgur@31 | 21 def __init__(self, key: str): |
| awgur@31 | 22 self.key = key |
| awgur@31 | 23 |
| awgur@31 | 24 def encode(self, data: dict, timeout: Optional[int] = None) -> str: |
| awgur@31 | 25 if timeout is not None: |
| awgur@31 | 26 data['exp'] = datetime.utcnow() + timedelta(seconds=timeout) |
| awgur@31 | 27 |
| awgur@31 | 28 return jwt.encode(data, key=self.key, algorithm=JWT_HASH_ALGO) |
| awgur@31 | 29 |
| awgur@31 | 30 def decode(self, token: str, check_timeout: bool = False) -> dict: |
| awgur@31 | 31 opts = { |
| awgur@31 | 32 'algorithms': [JWT_HASH_ALGO, ] |
| awgur@31 | 33 } |
| awgur@31 | 34 |
| awgur@31 | 35 if check_timeout: |
| awgur@31 | 36 opts['options'] = {'require': {'exp'}} |
| awgur@31 | 37 |
| awgur@31 | 38 if token is None: |
| awgur@31 | 39 raise JWTAuthError('Ключ отсутствует') |
| awgur@31 | 40 else: |
| awgur@31 | 41 token = token.encode('utf-8') |
| awgur@31 | 42 |
| awgur@31 | 43 try: |
| awgur@31 | 44 return jwt.decode(jwt=token, key=self.key, **opts) |
| awgur@31 | 45 |
| awgur@31 | 46 except (jwt.InvalidIssuerError, jwt.InvalidSignatureError, jwt.ExpiredSignatureError) as e: |
| awgur@31 | 47 raise JWTAuthError(str(e)) |
| awgur@31 | 48 |
| awgur@31 | 49 except jwt.PyJWTError as e: |
| awgur@31 | 50 raise JWTError(f'{type(e).__name__}: {e}') |
| awgur@31 | 51 |
| awgur@31 | 52 @classmethod |
| awgur@31 | 53 def make_cls_fabric(cls, key: str): |
| awgur@31 | 54 def f(): |
| awgur@31 | 55 return cls(key=key) |
| awgur@31 | 56 |
| awgur@34 | 57 return f |