OAuth выдает «недостающий код проверки» в Google OAuth2 - PullRequest
6 голосов
/ 12 июня 2019

Я следую этому примеру в попытке аутентифицировать моих пользователей с помощью 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)

Когда я делаю это, выдается ошибка: oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Missing code verifier.

Я не знаю, что такое верификатор кода, и примеры не упоминали его.

Трассировка стека доступна, если кто-то думает, что это поможет

Как я могу решить эту проблему?Любая помощь приветствуется!

Ответы [ 2 ]

5 голосов
/ 12 июня 2019

Похоже, что это ошибка в версии 0.4.0 google-auth-oauthlib (см. эту восходящую проблему ; обратите внимание, что об этом было сообщено после публикации этого вопроса SO).

У вас есть следующие опции:

  1. В качестве обходного пути вы можете понизить используемую версию:
    pip install --upgrade google-auth-oauthlib==0.3.0
    
  2. Передать пользовательский верификатор кода при создании экземпляра google_auth_oauthlib.flow.Flow(), что должно быть случайная строка из 43-128 символов, используемая для проверки обмена ключами с использованием PKCE :
    oauth2_session, client_config = google_auth_oauthlib.helpers.session_from_client_secrets_file(
        'client_secret.json',
        scopes=['https://www.googleapis.com/auth/drive.file']),
    )
    flow = google_auth_oauthlib.flow.Flow(
        oauth2_session,
        client_type='web',
        client_config=client_config,
        redirect_uri='https://localhost:5000/oauth2callback/',
        code_verifier='<random string>'
    )
    
    Примечание: код предназначен для вашей функции login().Вам нужно будет немного настроить его для работы в вашей функции oauth2callback().
  3. Подождите, пока ошибка не будет исправлена ​​в апстриме (при условии, что это ошибка).После этого верификатор кода будет сгенерирован автоматически, если он не предоставлен.
0 голосов
/ 22 июля 2019

Основываясь на ответе s3rvac, я немного покопался в исходном коде и обнаружил, что свойство code_verifier фактически автоматически генерируется в методе authorization_url()!Так что вам не нужно создавать его самостоятельно.

В вашем методе 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)

Затем вметод обратного вызова, просто загрузите его обратно:

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
)

Я использую Flow.from_client_config() для создания Flow, но я просто добавляю эту строку, и она отлично работает:

flow.code_verifier = session.get('code_verifier')
...