OAuth在Google OAuth2中抛出“缺少代码验证器”

Nat*_*and 6 python flask google-oauth2

我正在遵循此示例,以尝试使用Google API对用户进行身份验证。
这是我正在使用的相关代码,几乎与示例中的代码完全一样:

@app.route('/login/')
def login():
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        'client_secret.json',
        scopes=['https://www.googleapis.com/auth/drive.file'])
    flow.redirect_uri = 'https://localhost:5000/oauth2callback/'
    authorization_url, state = flow.authorization_url(
        access_type='offline',
    include_granted_scopes='true')
    session['state'] = state
    return redirect(authorization_url)

#called by Google's oauth 
@app.route('/oauth2callback/')
def oauth2callback():
    state = request.args['state']
    # Use the client_secret.json file to identify the application requesting
    # authorization. The client ID (from that file) and access scopes are required.
    state = session['state']
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        'client_secret.json',
        scopes=['https://www.googleapis.com/auth/drive.file'],
        state=state)
    flow.redirect_uri = url_for('oauth2callback', _external=True)

    authorization_response = request.url
    flow.fetch_token(authorization_response=authorization_response, code_verifier=False)
Run Code Online (Sandbox Code Playgroud)

当我这样做时,它给出了错误, oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Missing code verifier.

我不知道什么是代码验证程序,示例也没有提到。

如果有人认为堆栈跟踪会有所帮助,则可用

我该如何解决这个问题?任何帮助表示赞赏!

s3r*_*vac 7

这似乎是0.4.0版本中的错误google-auth-oauthlib(请参阅此上游问题;请注意,已在发布此SO问题后报告了该错误)。

您有以下选择:

  1. 解决方法是,您可以降级使用的版本:
    pip install --upgrade google-auth-oauthlib==0.3.0
    
    Run Code Online (Sandbox Code Playgroud)
  2. 实例化时传递自定义代码验证器google_auth_oauthlib.flow.Flow(),该验证器为43-128个字符的随机字符串,用于使用PKCE验证密钥交换:
    pip install --upgrade google-auth-oauthlib==0.3.0
    
    Run Code Online (Sandbox Code Playgroud) 注意:该代码适用于您的login()功能。您必须对其稍作调整才能发挥oauth2callback()功能。
  3. 等待,直到上游修复了该错误(假设它是错误)。之后,未提供时将自动生成代码验证程序。


Jer*_*her 5

根据 s3rvac 的回答,我深入研究了源代码,发现该code_verifier属性实际上可以在authorization_url()方法中自动生成!所以不需要自己生成一个。

首先,当您第一次构造 Flow 对象时,您必须启用autogenerate_code_verifier

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        'client_secret.json',
        scopes=['https://www.googleapis.com/auth/drive.file'],
        autogenerate_code_verifier=True  # <-- ADD THIS HERE
)
Run Code Online (Sandbox Code Playgroud)

然后在您的login()方法中,在调用 后flow.authorization_url(),存储flow.code_verifier在会话中:

authorization_url, state = flow.authorization_url(
        access_type='offline', 
        include_granted_scopes='true')  # code_verifier is set in this method
session['code_verifier'] = flow.code_verifier  # Get and store the code
session['state'] = state
return redirect(authorization_url)
Run Code Online (Sandbox Code Playgroud)

然后,在回调方法中,将其加载回来:

flow = google_auth_oauthlib.flow.Flow(
    oauth2_session,
    client_type='web',
    client_config=client_config,
    redirect_uri='https://localhost:5000/oauth2callback/',
    code_verifier=session.get('code_verifier')  # Load the code. Don't set autogenerate_code_verifier here, otherwise code_verifier would be overwritten.
)
Run Code Online (Sandbox Code Playgroud)

我用来Flow.from_client_config()构造 aFlow但我只添加这一行,它工作正常:

flow.code_verifier = session.get('code_verifier')
Run Code Online (Sandbox Code Playgroud)