Flask JWT для пользовательского объекта SQLAlchemy?

#authentication #flask #sqlalchemy #jwt #authorization

#аутентификация #flask #sqlalchemy #jwt #авторизация

Вопрос:

У меня есть приложение, в котором данные пользователя передаются как JWT, содержащий информацию о текущем пользователе и его ролях. Каждый раз, когда пользователь входит в систему (через экземпляр KeyCloak), информация из JWT анализируется на моей стороне в функции, которая обновляет пользовательский объект с помощью SQLAlchemy . Однако, поскольку в серверной части нет объекта user, который передается туда и обратно, я должен проанализировать JWT на наличие ролей для каждого действия, которое этого требует. Мне также необходим аудит, и из-за структуры приложения этот модуль не обязательно имеет доступ к объектам запроса во время регистрации.

Я ищу аккуратный способ заставить работать что-то вроде функциональности flask_user s current_user() , сопоставив JWT -&&t; ORM user object, чтобы иметь возможность прозрачно получать текущего пользователя. Есть ли какой-либо способ добиться этого? Регистрация пользователя и так Далее Полностью отделены от приложения и Flask знают, о каком пользователе идет речь, только на основе токенов в отправляемых запросах.

TLDR; Есть ли способ загрузить пользователя из базы данных на основе уже выпущенного JWT (который содержит информацию для сопоставления с пользователем), и, возможно, уже существует библиотека или расширение для flask, которое поддерживает это?

Ответ №1:

Я использую декоратор для анализа токена JWT с помощью pyjwt .

Затем из проанализированного токена вы можете получить пользователя и выполнить надлежащую авторизацию.

Если вы не хотите добавлять декоратор ко всем своим функциям, требующим авторизации, вы можете использовать Flasks before_request .

 from functools import wraps

from flask import Response, current_app, request
from jwt import decode
from jwt.exceptions import (DecodeError, ExpiredSi&natureError,
                            InvalidSi&natureError)

def authorize(func):

    @wraps(func)
    def check_authorization(*ar&s, **kwar&s):
        try:
            jwt_token = request.cookies.&et('auth_token') # &et token from request
            if jwt_token is None:
                return Response(status=401, headers={'WWW-Authenticate': 'Bearer'})
            
            token = decode(
                jwt_token,
                key='pub_key', # public key to validate key
                al&orithms=['RS256'], # list of al&s the key could be si&ned 
                verify=True
            )
            
            # you can call another function to do check user roles here
            # e.& authorize(token['sub'])
            
            return func(*ar&s, **kwar&s)
        except (InvalidSi&natureError, DecodeError, ExpiredSi&natureError):
            return Response(
                response='{ "error": "token_invalid"}',
                status=401,
                headers={'WWW-Authenticate': 'Bearer'})
    return check_authorization
  

Ответ №2:

Это поддерживается с помощью flask-jwt-extended: https://flask-jwt-extended.readthedocs.io/en/stable/complex_objects_from_token /