Python oauth2请求oauthlib类型错误:prepare_request_uri()为关键字参数获取了多个值';范围';

Python oauth2请求oauthlib类型错误:prepare_request_uri()为关键字参数获取了多个值';范围';,python,flask,oauth-2.0,Python,Flask,Oauth 2.0,servicem8 api()有一个参数范围作为oauth身份验证的一部分。虽然当我包含这个值时,我似乎得到了这个错误 TypeError:prepare\u request\u uri()为关键字参数“scope”获取了多个值 # This information is obtained upon registration of a new GitHub OAuth # application here: https://github.com/settings/applications/new

servicem8 api()有一个参数范围作为oauth身份验证的一部分。虽然当我包含这个值时,我似乎得到了这个错误

TypeError:prepare\u request\u uri()为关键字参数“scope”获取了多个值

# This information is obtained upon registration of a new GitHub OAuth
# application here: https://github.com/settings/applications/new
client_id = "ID"
client_secret = "SECRET"
authorization_base_url = 'https://www.servicem8.com/oauth/authorize'
token_url = 'https://www.servicem8.com/oauth/access_token'
grant_type = 'authorization_code'
scope = ['manage_inventory', 'manage_job_materials']
duration = 'permanent'
response_type = 'code'

@app.route("/")
def demo():
    redirect_uri = url_for('.callback', _external = True)
    state = str(uuid4())

    """Step 1: User Authorization.

    Redirect the user/resource owner to the OAuth provider (i.e. ServiceM8)
    using an URL with a few key OAuth parameters.
    """
    servicem8_client = OAuth2Session(client_id)
    authorization_url, state = servicem8_client.authorization_url(authorization_base_url, redirect_uri = redirect_uri, scope = scope)

    # State is used to prevent CSRF, keep this for later.
    session['oauth_state'] = state
    return redirect(authorization_url)
这是使用oauthlib请求时包含额外参数的方式吗?有没有办法避免这种冲突


完整的要点是:

通过将这些参数移动到构造函数而不是authorization\u url方法来修复它

    servicem8_client = OAuth2Session(client_id, redirect_uri = redirect_uri, scope = scope)
    authorization_url, state = servicem8_client.authorization_url(authorization_base_url, Response_type = response_type)
完整示例

from requests_oauthlib import OAuth2Session
from flask import Flask, request, redirect, session, url_for
from flask.json import jsonify
import os
from uuid import uuid4
#from urlparse import urlparse, urljoin
app = Flask(__name__)


# This information is obtained upon registration of a new GitHub OAuth
# application here: https://github.com/settings/applications/new
client_id = "ID"
client_secret = "SECRET"
authorization_base_url = 'https://www.servicem8.com/oauth/authorize'
token_url = 'https://www.servicem8.com/oauth/access_token'
grant_type = 'authorization_code'
scope = ['manage_inventory', 'manage_job_materials']
duration = 'permanent'
response_type = 'code'

@app.route("/")
def demo():
    redirect_uri = url_for('.callback', _external = True)
    state = str(uuid4())

    """Step 1: User Authorization.

    Redirect the user/resource owner to the OAuth provider (i.e. ServiceM8)
    using an URL with a few key OAuth parameters.
    """
    servicem8_client = OAuth2Session(client_id, redirect_uri = redirect_uri, scope = scope)
    authorization_url, state = servicem8_client.authorization_url(authorization_base_url, Response_type = response_type)

    # State is used to prevent CSRF, keep this for later.
    session['oauth_state'] = state
    return redirect(authorization_url)


# Step 2: User authorization, this happens on the provider.

@app.route("/callback", methods=["GET"])
def callback():
    code = request.args.get('code')

    """ Step 3: Retrieving an access token.

    The user has been redirected back from the provider to your registered
    callback URL. With this redirection comes an authorization code included
    in the redirect URL. We will use that to obtain an access token.

            if (oauth.refresh_token != null)
            {
                body.Add(new KeyValuePair<string, string>("grant_type", "refresh_token"));
                body.Add(new KeyValuePair<string, string>("refresh_token", oauth.refresh_token));
            }
            else
            {
                body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
                body.Add(new KeyValuePair<string, string>("code", code));
            }
            body.Add(new KeyValuePair<string, string>("redirect_uri", redirect_uri));
            body.Add(new KeyValuePair<string, string>("state", state));
            body.Add(new KeyValuePair<string, string>("client_id", client_id));
            body.Add(new KeyValuePair<string, string>("client_secret", client_secret));
    """
    servicem8_client = OAuth2Session(client_id, state=session['oauth_state'])

    token = servicem8_client.fetch_token(token_url, client_secret=client_secret, code = code,
                               authorization_response=request.url)

    # At this point you can fetch protected resources but lets save
    # the token and show how this is done from a persisted token
    # in /profile.
    session['oauth_token'] = token

    return redirect(url_for('.profile'))

@app.route("/profile", methods=["GET"])
def profile():
    """Fetching a protected resource using an OAuth 2 token.
    """
    servicem8_client = OAuth2Session(client_id, token=session['oauth_token'])
    return jsonify(servicem8_client.get('https://api.servicem8.com/api_1.0/JobMaterial.json').json())


if __name__ == "__main__":


    # This allows us to use a plain HTTP callback
    os.environ['DEBUG'] = "1"
    os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

    app.secret_key = os.urandom(24)
    app.run(debug=True)
来自请求\u oauthlib导入OAuth2Session
从flask导入flask、请求、重定向、会话、url\u
从flask.json导入jsonify
导入操作系统
从uuid导入uuid4
#从URLPRASE导入URLPRASE,urljoin
app=烧瓶(名称)
#此信息是在注册新的GitHub OAuth时获得的
#申请表格:https://github.com/settings/applications/new
客户_id=“id”
客户_secret=“secret”
授权\u基础\u url=https://www.servicem8.com/oauth/authorize'
令牌https://www.servicem8.com/oauth/access_token'
授权类型='授权代码'
范围=['管理库存','管理作业材料']
持续时间='永久'
响应类型='代码'
@附件路线(“/”)
def demo():
重定向('.callback',外部=True)的url
state=str(uuid4())
“”“第1步:用户授权。
将用户/资源所有者重定向到OAuth提供程序(即ServiceM8)
使用带有几个关键OAuth参数的URL。
"""
servicem8_客户端=OAuth2Session(客户端id,重定向uri=redirect_uri,作用域=scope)
授权\ url,状态=服务M8 \客户端。授权\ url(授权\基础\ url,响应\类型=响应\类型)
#状态用于防止CSRF,请稍后保存。
会话['oauth_state']=状态
返回重定向(授权\ url)
#步骤2:用户授权,这发生在提供者上。
@app.route(“/callback”,方法=[“GET”])
def callback():
code=request.args.get('code')
“”“步骤3:检索访问令牌。
用户已从提供商重定向回您的注册服务器
回调URL。此重定向包含一个授权代码
在重定向URL中。我们将使用它来获取访问令牌。
if(oauth.refresh\u令牌!=null)
{
添加(新的KeyValuePair(“授权类型”、“刷新令牌”);
添加(新的KeyValuePair(“刷新令牌”,oauth.refresh\u令牌));
}
其他的
{
添加(新的KeyValuePair(“授权类型”、“授权代码”);
添加(新的KeyValuePair(“code”,code));
}
添加(新的KeyValuePair(“redirect_-uri”,redirect_-uri));
添加(新的KeyValuePair(“state”,state));
添加(新的KeyValuePair(“客户端id”,客户端id));
添加(新的KeyValuePair(“client_secret”,client_secret));
"""
servicem8_客户端=OAuth2Session(客户端id,状态=会话['oauth_状态])
token=servicem8\u client.fetch\u token(token\u url,client\u secret=client\u secret,code=code,
授权(响应=request.url)
#此时,您可以获取受保护的资源,但让我们保存
#标记,并显示如何从持久化标记执行此操作
#在/profile中。
会话['oauth_令牌']=令牌
返回重定向(url_用于('.profile'))
@app.route(“/profile”,方法=[“GET”])
def配置文件():
“”“正在使用OAuth 2令牌获取受保护的资源。
"""
servicem8_客户端=OAuth2Session(客户端id,令牌=会话['oauth_令牌])
返回jsonify(servicem8_client.get('https://api.servicem8.com/api_1.0/JobMaterial.json').json())
如果名称=“\uuuuu main\uuuuuuuu”:
#这允许我们使用普通的HTTP回调
os.environ['DEBUG']=“1”
os.environ['OAUTHLIB\u unsecure\u TRANSPORT']=“1”
app.secret_key=os.uradom(24)
app.run(debug=True)

您如何克服回调页面上的安全连接失败错误?