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