2010-07-28 8 views
30

Sto costruendo un webservice e vorrei utilizzare le credenziali dell'account Google dell'utente.Credenziali del servizio Web - Account Manager OpenID/Android?

Il servizio viene eseguito su GAE e avrà un client Web e un client nativo Android.

Questo è il mio primo tentativo di qualcosa di simile e ho letto su OpenID e la libreria di accountManager di Android.

Non sono ancora sicuro di quali sono le mie opzioni in termini di archiviazione degli utenti nel mio archivio dati. Quale identificatore dovrei usare? È possibile utilizzare OpenID su un'applicazione Android nativa?

Qualsiasi aiuto e/o suggerimento sarebbe apprezzato. Grazie.

risposta

30

Abbiamo avuto una requisiti simili sul ultimo progetto: GAE backend con GWT frontend e Android/client iPhone. Inoltre, non volevamo memorizzare le credenziali dell'utente.

Quindi abbiamo scelto di utilizzare OpenID, che purtroppo è uno standard Web e non funziona bene con i dispositivi mobili, ma è fattibile.

Sul lato GAE abbiamo semplicemente abilitato l'accesso federato che ci ha dato OpenID.

Sui dispositivi mobili, quando l'utente deve effettuare il login, presentiamo loro una lista di autenticatori OpenID (Google, Yahoo, ecc.). Quindi apriamo un browser nativo (non browser incorporato) e indirizziamo l'utente al sito di autenticazione OpenID scelto. Il vantaggio è che il browser dell'utente di solito ha già un nome utente/password, quindi questo passaggio richiede solo all'utente di premere un pulsante.

Questo è tutto piuttosto semplice. Ora ecco la parte difficile: Dopo che l'utente ha confermato l'accesso, OpenID reindirizza nuovamente al nostro URL di ritorno GAE (è necessario fornire questo URL quando viene effettuata una richiesta). Su questo URL creiamo un URL personalizzato, ad esempio:

yourappname://usrname#XXXYYYZZZ 

dove XXXYYYZZZZ è auth token. Otteniamo questo token dalla pagina di ritorno in cui è memorizzato come cookie ACSID: abbiamo usato alcuni JSP per leggere questo cookie e inserirlo in un URL personalizzato superiore.

Poi registriamo le nostre applicazioni Android e iPhone per gestire i yourappname:// URL, in modo che quando l'utente cliskc questo link, la nostra applicazione viene richiamato e il collegamento è passato a esso. Estraiamo il nome utente e il token da questo link e lo usiamo nelle richieste REST al backend GAE.

Se avete altre domande avrei volentieri aggiornare questo post.

Aggiornamento:

Il cookie di sessione utente su AppEngine di produzione si chiama ACSID, mentre sul server di sviluppo AppEngine è chiamato dev_appserver_login.

+0

+1 - molto dettagliato! Cosa mostra il testo dell'URL personalizzato? "Fare clic qui per tornare all'applicazione"? O qualcosa di simile? –

+0

Può mostrare quello che ti piace. Ho usato il link "Continua .." che sembra un pulsante. Con qualche javascript potresti avviare l'app automaticamente, senza che l'utente debba fare clic sul link: non l'hai provato, avrebbe dovuto essere testato. –

0
+0

L'esempio collegato non utilizza OpenID o Xauth, quindi non può essere utilizzato su GAE per l'autenticazione con gli account Google esistenti. Come posso vedere utilizza il proprio schema di autenticazione: semplice POST con nome utente/password come parametri di intestazione. –

+0

sebbene @peterKnego abbia un punto riguardante la seconda raccomandazione, il primo collegamento è in realtà abbastanza utile. ma sono d'accordo sul fatto che si debba prestare maggiore attenzione alla formulazione di una risposta adeguata, fmo. ma fai attenzione a non essere downvoted in futuro. –

12

ho trascorso circa una settimana per trovare un modo adeguato e moderno alla ricerca di questo - senza browser web e utilizzando account manager di Android.

Se si desidera utilizzare account Google e AccountManager di identificare l'utente è possibile:

  1. ottenere il suo token per Google Contacts (auth tipo di token è "CP") attraverso AccountManager su sfondo filo :

    public String getUserToken(Activity activity) 
    { 
        AccountManager accountManager = AccountManager.get(activity); 
        AccountManagerFuture<Bundle> amf = accountManager.getAuthTokenByFeatures("com.google", "cp", null, activity, Bundle.EMPTY, Bundle.EMPTY, null, null); 
    
        Bundle bundle = null; 
        try { 
         bundle = amf.getResult(); 
         String name = (String) bundle.get(AccountManager.KEY_ACCOUNT_NAME); 
         String type = (String) bundle.get(AccountManager.KEY_ACCOUNT_TYPE); 
         String token = bundle.getString(AccountManager.KEY_AUTHTOKEN); 
         return token; 
        } catch (OperationCanceledException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } catch (AuthenticatorException e) { 
         e.printStackTrace(); 
        } 
        return null; 
    } 
    
  2. Passo ricevuto UserToken al server tramite assicurato canale.

  3. Convalida il token al server di Google utilizzando la libreria GData (Google Data API library):

    public String getUserId(String token) 
    { 
        ContactsService contactsService = new ContactsService("Taxi"); 
        contactsService.setUserToken(token); 
    
        IFeed feed = null; 
        try { 
         feed = contactsService.getFeed(new URL("https://www.google.com/m8/feeds/contacts/default/full?max-results=10000"), ContactFeed.class); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } catch (ServiceException e) { 
         e.printStackTrace(); 
        } catch (NullPointerException e) { 
         e.printStackTrace(); 
        } 
    
        if (feed == null) 
         return null; 
    
        String externalId = feed.getId(); 
        IPerson person = feed.getAuthors().get(0); 
        String email = person.getEmail(); 
        String name = person.getName(); 
        String nameLang = person.getNameLang(); 
    
        return externalId; 
    } 
    
  4. Google token può scadono (di solito dopo un'ora), quindi se non siete riusciti a validare il token al server , è necessario inviare una risposta al client, invalidare il token e ottenerne uno nuovo. Utilizzare account manager per invalidare il token:

    public void invalidateUserToken(Context context, String token) 
    { 
        AccountManager accountManager = AccountManager.get(context); 
        accountManager.invalidateAuthToken("com.google", token); 
    } 
    
+0

è possibile fare lo stesso (ottenere il token da utilizzare) per i messaggi di posta elettronica su gmail e per Facebook? In tal caso, puoi rispondere al prossimo post: http://stackoverflow.com/questions/11532257/use-syncadapter-to-sync-with-local-gmail-and-facebook-app-data –

+0

Ma ciò non risolvo il problema dal momento che vuole autenticare l'utente sul proprio webservice con un database, credo, quindi se vuole autenticare sul suo webservice dovrebbe inviare il token e il suo ID google sul webservice e il webservice dovrebbe inviare il token su Google Server che invia una risposta con l'ID google che puoi confrontare con l'ID google che l'utente ha inviato, non è giusto? Come si fa a farlo ? – Karly

+1

Ho provato questa soluzione e funziona benissimo se hai solo bisogno di una email autenticata dal tuo utente. Il lato positivo è che puoi fare tutto nella tua app senza un browser web. Il rovescio della medaglia è che devi chiedere il permesso di modificare i contatti degli utenti, che alcuni potrebbero essere riluttanti a fare. Qualcuno sa di un modo per _giusta_ chiedere l'autenticazione senza chiedere _authorization_? – thomas88wp

3

Penso this post sul blog fa esattamente quello che vuoi. Ha funzionato per me. Entrambe le soluzioni pubblicate qui sono valide e intelligenti, ma penso che faccia esattamente come chiedeva il richiedente.

In sostanza, si ottiene un authToken che utilizza l'ambito "ah" e lo si passa alla pagina Web corretta per ottenere il cookie ACSID che consente di accedere a qualsiasi pagina AppEngine che utilizza UserService per l'autenticazione.