2011-02-09 12 views
7

Me pregunto cuál es la mejor y más fácil manera de autenticar al usuario de la API de datos de Google en una aplicación de escritorio.API de datos de Google: cómo hacer la autenticación para aplicaciones de escritorio

Leo a través del docs y parece que mis opciones son ClientLogin u OAuth.

Para ClientLogin, parece que tengo que implementar la interfaz de usuario para el inicio de sesión/contraseña (y cosas relacionadas como guardar esto en alguna parte, etc.). Realmente me pregunto si hay algo más de soporte allí que pueda mostrar alguna pantalla de inicio de sesión/contraseña predeterminada y use el llavero del sistema operativo para almacenar la contraseña, etc. Me pregunto por qué ese apoyo no está allí. ¿No sería ese el procedimiento estándar? Al dejar esa implementación al desarrollador (bueno, la posibilidad de dejar esa impl al desarrollador es buena, por supuesto), creo que mucha gente ha encontrado soluciones muy feas aquí (cuando solo querían hackear un pequeño script)

OAuth parece ser la mejor solución. Sin embargo, parece que falta un código y/o la mayoría del código que encontré parece ser solo relevante para las aplicaciones web. Esp., Seguí la documentación y obtuve here. Ya en la introducción, habla sobre la aplicación web. Luego, más adelante, debo especificar una URL de devolución de llamada que no tiene sentido para una aplicación de escritorio. También me pregunto qué clave de consumidor/secreto debo poner, ya que tampoco tiene sentido para una aplicación de escritorio (especialmente para una de código abierto). Busqué un poco y se dijo here (on SO) que debería usar "anónimo"/"anónimo" como la clave/secreto del consumidor; pero, ¿dónde dice eso en la documentación de Google? ¿Y cómo obtengo el token después de que el usuario se haya autenticado?

¿Hay algún código de muestra? (No con un nombre de usuario/contraseña codificada, pero con un método de autenticación completa reutilizable.)

Gracias, Albert


Mi código hasta ahora:

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) 

Sin embargo, esto no funciona . Obtengo este error:

Sorry, you've reached a login page for a domain that isn't using Google Apps. Please check the web address and try again.

No entiendo muy bien eso. Por supuesto que no uso Google Apps.


Ah, que el error proviene de google_apps_domain=None en generate_authorization_url. Deja que la distancia (es decir, justo loginurl = request_token.generate_authorization_url() y funciona hasta el momento

Mi código actual:.

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 

que abrirá la página de Google OAuth con la pista en la parte inferior:

This website has not registered with Google to establish a secure connection for authorization requests. We recommend that you deny access unless you trust the website.

Se Todavía no funciona, sin embargo. Cuando trato de acceder a los contactos (es decir, solo un client.GetContacts()), aparece este error:

gdata.client.Unauthorized: Unauthorized - Server responded with: 401, <HTML> 
<HEAD> 
<TITLE>Token invalid - AuthSub token has wrong scope</TITLE> 
</HEAD> 
<BODY BGCOLOR="#FFFFFF" TEXT="#000000"> 
<H1>Token invalid - AuthSub token has wrong scope</H1> 
<H2>Error 401</H2> 
</BODY> 
</HTML> 

Ok, parece que realmente había establecido el alcance incorrecto. Cuando uso http en lugar de https (es decir, SCOPES = [ "http://www.google.com/m8/feeds/" ]), funciona.

Pero realmente me gustaría usar https. Me pregunto cómo puedo hacer eso.


Además, otro problema con esta solución:

En la lista de acceso autorizado a mi cuenta de Google, ahora tengo un montón de tales entradas localhost:

localhost:58630 — Google Contacts [ Revoke Access ]
localhost:58559 — Google Contacts [ Revoke Access ]
localhost:58815 — Google Contacts [ Revoke Access ]
localhost:59174 — Google Contacts [ Revoke Access ]
localhost:58514 — Google Contacts [ Revoke Access ]
localhost:58533 — Google Contacts [ Revoke Access ]
localhost:58790 — Google Contacts [ Revoke Access ]
localhost:59012 — Google Contacts [ Revoke Access ]
localhost:59191 — Google Contacts [ Revoke Access ]

Me pregunto cómo Puedo evitar que haga tales entradas.

Cuando uso xoauth_displayname, muestra ese nombre en su lugar, pero aún hace varias entradas (probablemente porque la URL sigue siendo en su mayoría diferente (debido al puerto) cada vez). ¿Cómo puedo evitar eso?


Mi código actual es ahora Github.


también me pregunto, dónde, cómo y por cuánto tiempo debo almacenar el token de acceso y/o el token pedido, por lo que el usuario no se le pide siempre una y otra vez cada vez que el usuario inicia la aplicación.

Respuesta

2

OAuth también se puede usar en aplicaciones de escritorio. La clave del consumidor y el secreto 'anónimo' son perfectamente adecuados para dicha aplicación.

El usuario no se autenticará. Recibirá un token del proveedor (Google) y el usuario lo autorizará como un token para un consumidor de confianza (su aplicación), al que se puede acceder y usar su (s) servicio (s) de Google.

Aquí hay una buena biblioteca de Python para OAuth:

https://github.com/simplegeo/python-oauth2

He aquí un resumen de cómo funciona OAuth:

http://blog.doityourselfandroid.com/2010/11/07/google-oauth-overview/

He aquí un ejemplo para Java que también explica los pasos a seguir tomado para autenticación OAuth:

http://nilvec.com/implementing-client-side-oauth-on-android/

HTH.

+0

La autorización por parte del usuario - exactamente cómo se vería eso ¿me gusta? ¿Abrí un webbrowser externo y de alguna manera volví a verificar con frecuencia si el token estaba autorizado? En el código de ejemplo, realmente no veo dónde se abre el navegador web. – Albert

+0

Además, parece que gdata lib ya viene con funciones para OAuth. ¿Entonces supongo que no necesito otra lib para eso? ¿O qué proporciona python-oauth2 además de lo que ya tengo con gdata? – Albert

+0

OAuth de tres patas funciona de la siguiente manera: 1. Solicita un token y un token secret del proveedor (Google) 2.Abre un navegador web para el usuario y lo lleva a la URL de autorización del proveedor, donde el usuario puede confirmar que desea darle acceso y le devuelve un código de verificación. El sitio del proveedor puede devolverle la llamada a través de una URL que proporciona el verificador, o darle al usuario el código de verificador que necesita. 3. con el token original y el verificador, puede adquirir su token final del proveedor. – ldx

Cuestiones relacionadas