#android #python-3.x #flask #oauth-2.0 #google-oauth
#Android #python-3.x #flask #oauth-2.0 #google-oauth
Вопрос:
Я использую oauth 2.0 с гибридным потоком для входа в Google https://developers.google.com/identity/sign-in/web/server-side-flow в моем приложении для Android. Я получаю одноразовый код авторизации в приложении Android и отправляю его в свой flask api через postman. Когда я применяю flow.step2_exchange к этому одноразовому коду аутентификации в api, он выдает ошибку обмена потоками. Я проверил, что код аутентификации, который поступает в API, такой же, как и в моем приложении. Я не могу найти причину ошибки.
Мой одноразовый код аутентификации выглядит следующим образом: 4 /qXilPdy7xOVe5swCBlVRrxjuVu8zEzfcmidlooo7_ls
Фрагмент кода моего api flask:
# IMPORTS FOR THIS STEP
from oauth2client.client import flow_from_clientsecrets
from oauth2client.client import FlowExchangeError
import httplib2
import json
from flask import make_response
import requests
app = Flask(__name__)
CLIENT_ID = json.loads(
open('client_secrets.json', 'r').read())['web']['client_id']
APPLICATION_NAME = "OAUTH_SERVER"
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
# Add other requested scopes.
]
# Connect to Database and create database session
engine = create_engine('sqlite:///restaurantmenu.db')
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()
@app.route('/gconnect', methods=['POST'])
def gconnect():
request.get_data()
code = request.data.decode('utf-8')
print (code)
# Upgrade the authorization code into a credentials object
oauth_flow = flow_from_clientsecrets('client_secrets.json', scope = SCOPES)
oauth_flow.redirect_uri = 'postmessage'
try:
credentials = oauth_flow.step2_exchange(code)
if credentials is None:
print ("it is empty")
except FlowExchangeError:
response = make_response(
json.dumps('Failed to upgrade the authorization code.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
Мой client_secret.json для Api называется OAUTH_SERVER и выглядит следующим образом:
{"web":
{"client_id":"matches the one in console.apps.googleusercontent.com",
"project_id":"oauthapi",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"###########",
"redirect_uris["http://localhost:5000/gconnect","http://localhost:5000/"],
"javascript_origins":["http://localhost:5000"]}
}
Ответ №1:
Как я вижу, это из курса Udacity — Аутентификация и авторизация. Пожалуйста, проверьте, не login.html содержит правильное значение data-clientid. У меня была такая же проблема, потому что при копировании забыл изменить ее на мою.
Комментарии:
1. Вы правы, это из курса Udacity, но я адаптировал этот код для своего проекта Android. Поэтому у меня нет login.html . Я успешно вхожу в систему через свое приложение для Android, затем получаю одноразовый код аутентификации и отправляю его в api. Мое приложение и api имеют разные client_secrets (предполагается, что в случае app api). client_secret.json в моем API имеет веб-тип (api). Я проверил значение идентификатора клиента. Я также публикую формат моего client_secret JSON в моем вопросе, на случай, если с ним что-то не так.
2. Итак, чтобы убедиться, что у вас есть приложение для Android, которое является серверной частью клиента и сервера Flask (API). Почему они проходят проверку подлинности отдельно в Google? Я думаю, что мобильное приложение является клиентом, который должен обернуть логику в «login.html » и ваш серверный сервер должен иметь client_secret . Мобильное приложение не должно иметь client_secret.
3. В курсе udacity использовался один идентификатор клиента, секрет клиента, но я не могу этого сделать в моем случае, потому что веб-приложение и приложение Android имеют разные google_services json, которые нельзя обменять. А также для получения одноразового кода авторизации в приложении Android я должен предоставить идентификатор клиента внутреннего сервера в приложении. Проверьте эту ссылку developers.google.com/identity/sign-in/android/backend-auth .
4. Это ссылка из документов Google : developers.google.com/identity/sign-in/android/start
Ответ №2:
Я думаю, вам нужно изменить
# Upgrade the authorization code into a credentials object
oauth_flow = flow_from_clientsecrets('client_secrets.json', scope = SCOPES)
oauth_flow.redirect_uri = 'postmessage'
try:
credentials = oauth_flow.step2_exchange(code)
if credentials is None:
print ("it is empty")
except FlowExchangeError:
Для
try:
# Upgrade the authorization code into a credentials object
oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
oauth_flow.redirect_uri = 'postmessage'
credentials = oauth_flow.step2_exchange(code)
except FlowExchangeError:
Комментарии:
1. Он по-прежнему выдает ту же ошибку. Я взял первые две строки из «попытки», чтобы найти строку кода, выдающую ошибку.