API данных Google: как выполнить аутентификацию для настольных приложений

Мне интересно, как лучше / проще всего аутентифицировать пользователя для API данных Google в настольном приложении.

Я прочитал документы , и мне кажется, что мой варианты: ClientLogin или OAuth.

Что касается ClientLogin, мне кажется, что я должен сам реализовать пользовательский интерфейс для входа / пароля (и связанных вещей, таких как сохранение где-нибудь и т. д.). Мне действительно интересно, есть ли там еще какая-то поддержка, которая может вызвать экран входа / пароля по умолчанию и использовать связку ключей ОС для хранения пароля и т. Д. Интересно, почему такой поддержки нет? Разве это не стандартная процедура? Оставив эту реализацию разработчику (ну, конечно, возможность оставить это разработчику - это хорошо), Я предполагаю, что многие люди придумали здесь очень уродливые решения (когда они просто хотели собрать небольшой скрипт).

OAuth кажется лучшим решением. Тем не менее, похоже, что какой-то код отсутствует, и / или большая часть кода, который я нашел, кажется актуальным только для веб-приложений. Например, я следил за документацией и получил здесь . Уже во введении говорится о веб-приложении. Позже мне нужно указать URL-адрес обратного вызова, который не имеет смысла для настольного приложения. Также мне интересно, какой ключ / секрет потребителя я должен указать, поскольку это также не имеет смысла для настольного приложения (особенно для приложения с открытым исходным кодом). Я немного поискал, и здесь (на SO) было сказано , что я должен использовать «анонимный» / «анонимный» в качестве ключа / секрета потребителя; а где это написано в документации гугла? И как мне получить токен после аутентификации пользователя?

Есть ли какой-нибудь образец кода? (Не с жестко заданным именем пользователя и паролем, а с многоразовым методом полной аутентификации.)

Спасибо, Альберт


Мой код на данный момент:

import gdata.gauth
import gdata.contacts.client

CONSUMER_KEY = 'anonymous'
CONSUMER_SECRET = 'anonymous'
SCOPES = [ "https://www.google.com/m8/feeds/" ] # contacts

client = gdata.contacts.client.ContactsClient(source='Test app')

import BaseHTTPServer
import SocketServer

Handler = BaseHTTPServer.BaseHTTPRequestHandler
httpd = BaseHTTPServer.HTTPServer(("", 0), Handler)
_,port = httpd.server_address

oauth_callback_url = 'http://localhost:%d/get_access_token' % port
request_token = client.GetOAuthToken(
    SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)

loginurl = request_token.generate_authorization_url(google_apps_domain=None)
loginurl = str(loginurl)
import webbrowser
webbrowser.open(loginurl)

Однако это не работает. Я получаю эту ошибку:

Извините, вы достигли страницы входа в домен, который не использует Google Apps. Проверьте веб-адрес и повторите попытку.

Я не совсем понимаю. Конечно, я не использую Google Apps.


А, эта ошибка возникла из-за google_apps_domain = None в generate_authorization_url . Оставьте это (то есть просто loginurl = request_token.generate_authorization_url () , и он работает пока.

Мой текущий код:

import gdata.gauth
import gdata.contacts.client

CONSUMER_KEY = 'anonymous'
CONSUMER_SECRET = 'anonymous'
SCOPES = [ "https://www.google.com/m8/feeds/" ] # contacts

client = gdata.contacts.client.ContactsClient(source='Test app')

import BaseHTTPServer
import SocketServer

httpd_access_token_callback = None
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path.startswith("/get_access_token?"):
            global httpd_access_token_callback
            httpd_access_token_callback = self.path
        self.send_response(200)
    def log_message(self, format, *args): pass
httpd = BaseHTTPServer.HTTPServer(("", 0), Handler)
_,port = httpd.server_address

oauth_callback_url = 'http://localhost:%d/get_access_token' % port
request_token = client.GetOAuthToken(
    SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)

loginurl = request_token.generate_authorization_url()
loginurl = str(loginurl)
print "opening oauth login page ..."
import webbrowser; webbrowser.open(loginurl)

print "waiting for redirect callback ..."
while httpd_access_token_callback == None:
    httpd.handle_request()

print "done"

request_token = gdata.gauth.AuthorizeRequestToken(request_token, httpd_access_token_callback)

# Upgrade the token and save in the user's datastore
access_token = client.GetAccessToken(request_token)
client.auth_token = access_token

Это откроет страницу Google OAuth с подсказкой внизу:

Этот веб-сайт не зарегистрирован в Google для установления безопасного соединения для запросов авторизации. Мы рекомендуем вам отказать в доступе, если вы не доверяете этому веб-сайту.

Однако он по-прежнему не работает. Когда я пытаюсь получить доступ к контактам (то есть просто к client.GetContacts () ), я получаю следующую ошибку:

gdata.client.Unauthorized: Unauthorized - Server responded with: 401, 

Token invalid - AuthSub token has wrong scope


Token invalid - AuthSub token has wrong scope

Error 401


Хорошо, похоже, что я действительно установил неправильную область. Когда я использую http вместо https (т.е. SCOPES = ["http://www.google.com/m8/feeds/"] ), он работает.

Но я бы очень хотел использовать https. Интересно, как я могу это сделать.


Также есть еще одна проблема с этим решением:

В списке авторизованного доступа к моей учетной записи Google теперь есть несколько таких записей localhost:

localhost: 58630 - Google Контакты [Отменить доступ]
Когда я использую http вместо https (т.е. SCOPES = ["http://www.google.com/m8/feeds/"] ), он работает.

Но я бы очень хотел использовать https. Интересно, как я могу это сделать.


Также есть еще одна проблема с этим решением:

В списке авторизованного доступа к моей учетной записи Google теперь есть несколько таких записей localhost:

localhost: 58630 - Google Контакты [Отменить доступ]
Когда я использую http вместо https (т.е. SCOPES = ["http://www.google.com/m8/feeds/"] ), он работает.

Но я бы очень хотел использовать https. Интересно, как я могу это сделать.


Также есть еще одна проблема с этим решением:

В списке авторизованного доступа к моей учетной записи Google теперь есть несколько таких записей localhost:

localhost: 58630 - Google Контакты [Отменить доступ]
localhost: 58559 - Контакты Google [Отменить доступ]
localhost: 58815 - Контакты Google [Отменить доступ]
localhost: 59174 - Google Контакты [Отменить доступ]
localhost: 58514 - Контакты Google [Отменить доступ]
localhost: 58533 - Контакты Google [Отменить доступ]
localhost: 58790 - Google Контакты [Отменить доступ]
localhost: 59012 - Контакты Google [Отменить доступ]
localhost: 59191 - Контакты Google [Отменить доступ]

Интересно, как я могу избежать таких записей.

Когда я использую xoauth_displayname , вместо этого отображается это имя, но все же выполняется несколько записей (возможно, потому, что URL-адрес по-прежнему в основном различается (из-за порта) каждый раз). Как мне этого избежать?


Мой текущий код теперь на Github .


Мне также интересно, где, как и как долго мне следует хранить токен доступа и / или токен запроса, чтобы что пользователя не спрашивают всегда снова и снова каждый раз, когда пользователь запускает приложение.

8
задан Community 23 May 2017 в 11:46
поделиться