python - 在 authlib 中,authorize_access_token 是否需要显式传递 client_id 和 client_secret?
问题描述
我正在使用具有非常标准的 OAuth2 流程的 authlib。
import pickle
import json
import os.path
from requests.models import Response
from authlib.integrations.flask_client import OAuth, OAuthError
class BaseApi(object):
def __init__(self, oauth_client, config_directory, token_file=''):
self.oauth_client = oauth_client
if token_file:
self.token_file = token_file
else:
self.token_file = os.path.join(config_directory, 'token.pickle')
@property
def token(self):
try:
print ("Token: %s" % self.__token)
return self.__token
except AttributeError:
if os.path.exists(self.token_file):
with open(self.token_file, 'rb') as f:
self.__token = pickle.load(f)
print ("Pickled Token: %s" % self.token)
return self.__token
@token.setter
def token(self, new_token):
self.__token = new_token
# The authorizaiton flow sends us to the OAuth provider
# with a redirect back to our app
def login(self, state=None):
return self.oauth_client.authorize_redirect(self.auth_callback, state=state)
# Our authorized endpoint.
def authorized(self,request):
# Get the access token!
token = self.oauth_client.authorize_access_token(client_id=self.oauth_client.client_id,
client_secret=self.oauth_client.client_secret)
#if resp is None or resp.get('access_token') is None:
# return 'Access denied: error=%s resp=%s' % (
# request.args,
# resp
# )
self.token = token
这都是在不同模块中的子类:
from __future__ import print_function
import json
from backend.oauth_base import BaseApi, OAuth, load_credentials_file
from urllib.parse import urlparse
from backend import app, url_for # This is the flask app
from flask import request, redirect, jsonify
import requests
import os
config_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config')
class BasecampApi(BaseApi):
def __init__(self):
oauth = OAuth(app)
credentials = load_credentials_file(os.path.join(config_directory,
'credentials.json'))
oauth.register(
name='basecamp',
client_id=credentials['client_id'],
client_secret=credentials['client_secret'],
api_base_url='https://3.basecampapi.com/',
request_token_url=None,
request_token_params={'type': 'web_server'},
access_token_url='https://launchpad.37signals.com/authorization/token',
access_token_params={'type': 'web_server'},
authorize_url='https://launchpad.37signals.com/authorization/new',
authorize_params={'type': 'web_server'}
)
oauth_client = oauth.create_client('basecamp')
super().__init__(oauth_client, config_directory)
这里的一切都有效,但我对为什么需要在授权访问令牌中显式传递 client_id 和 client_secret 感到困惑。
token = self.oauth_client.authorize_access_token()
导致 basecamp API 抛出一个错误,抱怨缺少 clien_id(然后是 client_secret)。
这与文档不同(我承认这很令人困惑)。这是预期的行为吗?
解决方案
默认token_endpoint_auth_method
值为client_secret_basic
,它将在 HTTP 授权标头中发送客户端凭据。但是,根据您的描述,似乎提供程序需要client_id
和client_secret
在有效载荷中,应该是client_secret_post
. 考虑将以下内容添加client_kwargs
到您的.register
:
client_kwargs = {
'token_endpoint_auth_method': 'client_secret_post',
}
推荐阅读
- python - Django试图为几个不同的列表视图重用相同的网页
- c# - 如何修复此类错误“从对象类型 anystore.bLL.loginBLL 到已知托管提供程序本机类型不存在映射”。好吧,我检查了很多次
- ios - 反应原生连接到 ios 上的经典蓝牙设备
- javascript - 带有 CSS 和 jQuery 的简单灯箱
- python - Python,将 Json-Data 放入变量中
- javascript - redux-toolkit-> 'A non-serializable value was detected in an action' 同时将工作代码转换为 redux-toolkit
- linux - 如何在 docker 容器中传输正在运行的 wordpress
- php - 警告 pg_execute():查询失败:错误:索引行大小 2728 超出索引“index_name”的最大值 2717
- django - 如何在同一服务器上为不同的客户端制作网站的多个副本 - django
- python-3.x - Python - 在子进程调用中格式化字符串时出错