API REST per il sito Web che utilizza Facebook per l'autenticazione


86

Abbiamo un sito web in cui l' unico modo per accedere e autenticarti con il sito è con Facebook (questa non è stata una mia scelta). La prima volta che accedi con Facebook, viene creato automaticamente un account per te.

Ora vogliamo creare un'applicazione per iPhone per il nostro sito e anche un'API pubblica per consentire ad altri di utilizzare il nostro servizio.

Questa domanda riguarda come autenticarsi con il nostro sito Web dall'app / API ed è suddivisa in 2 parti:

  1. Qual è il modo corretto per gestire l'autenticazione REST da un'API a un sito Web che utilizza solo Facebook OAuth come metodo di autenticazione?

    Ho letto e studiato molto sui metodi standard di autenticazione per l'API REST. Non possiamo utilizzare metodi come l' autenticazione di base su HTTPS , poiché non ci sono credenziali per un utente in quanto tale. Qualcosa di simile a questo sembra essere solo per autenticare le applicazioni utilizzando l'API.

    Attualmente, il modo migliore che posso pensare è che tu raggiunga un end-point / autorizzi sulla nostra API, reindirizza a Facebook OAuth, quindi reindirizza di nuovo al sito e fornisce un "token" che l'utente dell'API può utilizzare per l'autenticazione successiva richieste.

  2. Per un'applicazione ufficiale che creiamo, non avremmo necessariamente bisogno di utilizzare l'API pubblica allo stesso modo. Quale sarebbe quindi il modo migliore per parlare al nostro sito Web e autenticare gli utenti?

Capisco (penso) come autenticare applicazioni di terze parti che utilizzano la nostra API, utilizzando chiavi API (pubbliche) e chiavi segrete (private). Tuttavia, quando si tratta di autenticare l'utente che sta utilizzando l'app, sono piuttosto confuso su come procedere quando l'unico modo che abbiamo per autenticare un utente è Facebook.

Mi sento come se mi mancasse qualcosa di molto ovvio o non comprendessi appieno come dovrebbero funzionare le API REST pubbliche, quindi qualsiasi consiglio e aiuto sarebbe molto apprezzato.


Ho una domanda simile su stackoverflow.com/questions/30230482/… che parla di alcuni di questi
JVK

Risposte:


99

AGGIORNAMENTO: vedi sotto

Ho riflettuto molto anche su questa domanda. Non mi è ancora del tutto chiaro, ma ecco la strada che sto pensando di percorrere. Sto creando un'API REST e i miei utenti si autenticano solo con Facebook Connect.

Sul CLIENTE:

  1. Usa l'API di Facebook per accedere e ottenere un codice OAUTH2.
  2. Scambia questo codice con un token di accesso.
  3. In ogni chiamata alla mia API personalizzata includerò l'ID utente di Facebook e il token di accesso.

Sull'API (per ogni metodo che richiede l'autenticazione dell'utente):

  1. Fai una richiesta al grafico / me di Facebook utilizzando il token di accesso dall'alto.
  2. Verifica che l'ID utente di Facebook restituito corrisponda all'ID utente passato alla mia API dall'alto.
  3. Se il token di accesso è scaduto, è necessaria una comunicazione aggiuntiva.

Devo ancora provarlo. Come suona?

--- Aggiornamento: 27 luglio 2014 per rispondere alla domanda ---

Uso lo scambio di cui sopra solo una volta dopo il login. Dopo aver determinato quale utente sta effettuando l'accesso, creo il mio token di accesso e tale token viene utilizzato da quel momento in poi. Quindi il nuovo flusso assomiglia a questo ...

Sul CLIENTE:

  1. Usa l'API di Facebook per accedere e ottenere un codice OAUTH2.
  2. Scambia questo codice con un token di accesso.
  3. Richiedi un token di accesso dalla mia API, incluso il token di Facebook come parametro

Sull'API

  1. Ricevi la richiesta del token di accesso.
  2. Fai una richiesta al grafico / me di Facebook utilizzando il token di accesso di Facebook
  3. Verifica che l'utente Facebook esista e corrisponda a un utente nel mio database
  4. Crea il mio token di accesso, salvalo e restituiscilo al client per essere utilizzato da questo punto in avanti

Ehi, questa è una specie di risposta tardiva, ma la tua soluzione sembra risolvere il problema che avevo nella mia prima risposta. Ovviamente dovresti usare HTTPS per non inviare la coppia (id, token) sul filo in chiaro. Ma sembra che dovrebbe funzionare!
Olivier Lance

Penso che sia bene chiamarmi sul server e generare il tuo token di accesso, che verrà utilizzato dal client mobile.
Der_Meister

Ho scoperto che è una cattiva pratica memorizzare il segreto di FB nell'app mobile. Facebook consiglia di salvarlo solo sul tuo server. developer.facebook.com/docs/opengraph/using-actions/…
Der_Meister

Se inviamo user_id e access_token al server API ogni volta (come post / get params). Creerà un buco di sicurezza se qualcuno è in grado di intercettare la connessione?
Nathan Do

@NathanDo Usa HTTPS tra il tuo client e il server API e non dovrebbe essere un problema se qualcuno intercetta la connessione (vulnerabilità di tipo Heartbleed a parte).
dcr

15

Questa è la mia implementazione utilizzando JWT (JSON Web Tokens), sostanzialmente simile alla risposta aggiornata di Chris. Ho usato Facebook JS SDK e JWT.

Ecco la mia implementazione.

  1. Cliente: utilizza l'SDK JS di Facebook per accedere e ottenere il token di accesso.

  2. Cliente: Richiedi JWT dalla mia API chiamando l' /verify-access-tokenendpoint.

  3. MyAPI: riceve il token di accesso, verificalo chiamando l' /meendpoint dell'API di Facebook.

  4. MyAPI: se il token di accesso è valido, trova l'utente dal database, accede all'utente se esiste. Crea un JWT con i campi obbligatori come payload, imposta una scadenza, firma con la chiave segreta e rispedisci al client.

  5. Cliente: memorizza il JWT nella memoria locale.

  6. Cliente: invia il token (il JWT dal passaggio 5) insieme alla richiesta per la successiva chiamata API.

  7. MyAPI: convalida il token con la chiave segreta, se il token è valido, scambia il token con uno nuovo, invialo al client insieme alla risposta API. (Nessuna chiamata API esterna per la verifica del token qui dopo) [se il token non è valido / scaduto, richiedere al client di autenticarsi di nuovo e ripetere da 1]

  8. Il client sostituisce il token memorizzato con quello nuovo e lo utilizza per la successiva chiamata API. Una volta raggiunta la scadenza del token, il token scade revocando l'accesso all'API.

Ogni token viene utilizzato una volta.

Leggi altre risposte su sicurezza e JWT

Quanto è sicuro JWT

Se riesci a decodificare JWT, come sono sicuri?

Token Web JSON (JWT) come token di identificazione e autenticazione dell'utente


3
Immagino che il numero 3 dovrebbe essere piuttosto /debug_token, quindi puoi verificare che il token sia effettivamente per la tua applicazione.
Peppe LG

2
Non richiedere access_tokennel client. Usa il "flusso di lavoro del codice". Passare codea MyApi e fare un altro viaggio di andata a Facebook per lo scambio codecon access_token. Questo è spiegato in modo più approfondito qui: developers.facebook.com/docs/facebook-login/security
omikron

5

Sto cercando di rispondere alla stessa domanda e di recente ho letto molte letture ...

Non avrò "la" risposta ma le cose stanno diventando un po 'più chiare per me. Hai letto i commenti nell'articolo che hai citato ? Li ho trovati davvero interessanti e utili.

Di conseguenza, e alla luce di come le cose si sono evolute da quando è stato scritto il primo articolo, ecco cosa penso che farò:

  • HTTPS ovunque: questo ti consente di dimenticare HMAC, firma, nonce, ...

  • Usa OAuth2:

    • Quando le richieste di autenticazione provengono dalle mie app / dal mio sito Web, utilizza questo "trucco" (o una sua variazione) descritto in una risposta all'articolo menzionato prima.

    • Nel mio caso ho due tipologie di utenti: quelli con le classiche credenziali di login / password e quelli che si sono registrati con Facebook Connect.
      Quindi fornirei un modulo di accesso regolare con un pulsante "Accedi con Facebook". Se l'utente accede con le sue credenziali "classiche", le invierei semplicemente al mio endpoint OAuth2 con l'estensione grant_type=password.
      Se sceglie di accedere tramite Facebook, penso che sarebbe un processo in due fasi:

      • Innanzitutto, utilizza l'SDK iOS di Facebook per aprire una sessione FBS
      • Quando ciò è fatto e l'app viene restituita al controllo, dovrebbe esserci un modo per ottenere un ID Facebook per quell'utente. Invierei questo ID da solo al mio endpoint OAuth2 con una concessione di estensione intesa dal mio server come "utilizzo di un ID utente FB".

Tieni presente che sto ancora facendo ricerche su tutte queste cose, quindi potrebbe non essere una risposta perfetta ... forse nemmeno corretta! Ma penso che sarebbe un buon punto di partenza. L'idea di utilizzare una "concessione di estensione" per l'autenticazione di Facebook potrebbe comportare la necessità di registrarla per fare le cose correttamente? Non sono molto sicuro.

Ad ogni modo, spero di essere stato in grado di aiutarti anche un po ', e che almeno possa iniziare una discussione per trovare la migliore soluzione a questo problema :)

Aggiornamento
L'accesso a Facebook non è una soluzione come indicato nei commenti: chiunque potrebbe inviare un ID utente arbitrario e accedere come questo utente sull'API.

Che ne dici di farlo in questo modo:

  • Mostra un modulo di accesso con un pulsante "Accesso Facebook"
  • Se viene scelto questo metodo di accesso, agisci come l'SDK di Facebook: apri una pagina web dal tuo server di autenticazione, che avvierà il login di Facebook.
  • Una volta che l'utente ha effettuato l'accesso, Facebook utilizzerà il tuo URL di reindirizzamento per confermare; fare in modo che l'URL punti a un altro endpoint del server di autenticazione (possibilmente con un parametro aggiuntivo che indica che la chiamata proviene da un'app?)
  • Quando viene raggiunto l'endpoint di autenticazione, l'autenticazione può identificare in modo sicuro l'utente, conservare il suo ID utente FB / sessione FB e restituire un token di accesso alla tua app utilizzando uno schema URL personalizzato, proprio come farebbe l'SDK di Facebook

Sembra migliore?


1
Grazie per la risposta! Avevo pensato alla maggior parte di ciò che hai detto, ma la preoccupazione principale che avevo con l'utilizzo dell'SDK iOS di FB e quindi l'invio dell'ID utente di Facebook era che non sarebbe stato facile inviare qualsiasi ID che desideri al tuo endpoint API e affermare di essere un altro utente? Qui è dove di solito finisco per rimanere bloccato ..
Adam

Infatti! È stato stupido da parte mia non pensarci ... Quindi la soluzione deve passare attraverso il tuo server di autenticazione in qualche modo ...
Olivier Lance

Ho aggiornato la mia risposta con un'altra idea di soluzione ... ma mi sono appena reso conto che l'avevi menzionata nella tua domanda originale! Non riesco a vedere nient'altro al momento ...
Olivier Lance
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.