нашим OAuth2-сервером.
Но есть нюанс.
Вот код одного из классов:
https://github.com/lepture/authlib/blob/master/authlib/oauth2/rfc6749/wrappers.py#L9
def __init__(self, params):
if params.get('expires_at'):
params['expires_at'] = int(params['expires_at'])
elif params.get('expires_in'):
params['expires_at'] = int(time.time()) + \
int(params['expires_in'])
super(OAuth2Token, self).__init__(params)
Наш собственный OAuth2-сервер написан кривовато, и отдаёт поле expires_at как строку в ISO-формате, а не как unixtime.
Решение-то простое:
params['expires_at'] = int(datetime.strptime(params['expires_at'], '%Y-%m-%dT%H:%M:%S').timestamp())
Но я теперь не понимаю, как подменить исходный объект новым.
Что пробовал:
1. Сделать класс MockedOAuth2Token и попробовать подменить:
oauth2.rfc6749.wrappers.OAuth2Token = MockedOAuth2Token
Не работает
2. Переделать только __init__ и через unittest.mock запатчить.
Пробовал разными способами, тоже не работает. Ошибки больше нет, но данные пропадают по дороге, из-за чего всё бесполезно.
Есть какие-то удобные решения, кроме форка библиотеки?
Приложение на FastAPI. Ручка для начала авторизации: @router.get("/") async def login( request: Request, authorization: str = Cookie(default=None, alias="Authorization"), ): client = oauth.create_client("profile") redirect_uri = request.url_for('oauth_callback_get') return await client.authorize_redirect(request, redirect_uri) В момент нажатия юзером кнопки Allow: @router.get("/callback") async def oauth_callback_get(request: Request): OAuth2Client.token_auth_class = MockedOAuth2Token client = oauth.create_client("profile") client.token_auth_class = MockedOAuth2Token token = await client.authorize_access_token(request) # тут крашится из-за конвертации Что касается profile: oauth = OAuth() oauth.register( name="profile", client_id=config.client_id, client_secret=config.client_secret.get_secret_value(), authorize_url="https://our.corporate.domain/oauth/authorize", access_token_url="https://our.corporate.domain/oauth/token", client_kwargs={ "scope": "profile_user default groups" } )
Решил! def profile_compiance_fix(session): def _fix(resp): resp.raise_for_status() token = resp.json() token["expires_at"] = int(datetime.strptime(token["expires_at"], "%Y-%m-%dT%H:%M:%S").timestamp()) resp._content = json.dumps(token).encode('utf-8') return resp session.register_compliance_hook('access_token_response', _fix) oauth = OAuth() oauth.register( name="profile", client_id=config.client_id, client_secret=config.client_secret.get_secret_value(), authorize_url="https://our.corporate.domain/oauth/authorize", access_token_url="https://our.corporate.domain/oauth/token", compliance_fix=profile_compiance_fix, client_kwargs={ "scope": "profile_user default groups" } ) Спасибо @Tishka17 за наводку) И вот этой еле найденной странице в доке
Обсуждают сегодня