Come progettare l'autenticazione utente dalle applicazioni client?


14

Ho sviluppato un'applicazione che supporterà molti utenti. Il fatto è che non riesco a capire come autenticare il cliente / utente.

Sto costruendo un'app come http://quickblox.com/ dove darò le credenziali ai miei utenti e li useranno per creare applicazioni N in cui non possono inserire il loro nome utente e password per autenticarsi.

Supponiamo che vada come segue. (Proprio come QuickBlox)

1. L'utente crea un account sul mio sito Web.
2. L'utente può creare chiavi API N e secernere credenziali. (Per più app)
3. L'utente utilizzerà queste credenziali nelle proprie applicazioni (Android, iOS, Javascript ecc ...) per parlare con le mie API REST.
(Le API REST hanno accesso in lettura e scrittura.)

La mia preoccupazione?

Gli utenti inseriranno le proprie credenziali (chiave API e chiave di segreto) nelle applicazioni che creano, e se qualcuno ottenga queste chiavi e provi a imitare l'utente? (Decompilando APK o esaminando direttamente il codice JavaScript.

Sbaglio da qualche parte?
Sono confuso per progettare questo meccanismo utente a tre livelli.


La cosa che sembra stia cercando di fare non è possibile.
user253751

Ci sono molte applicazioni là fuori che fanno la stessa cosa. Non sono sicuro di come autenticano gli utenti.
Alok Patel,

Stai tentando di autenticare l' applicazione client o l' utente ? Molte app autenticano gli utenti. Nessuno di essi autentica le applicazioni client in modo indistruttibile.
user253751

Sì per cliente, intendo che voglio autenticare solo l'utente.
Alok Patel,

4
Oh, beh, allora nel più tipico sistema di autenticazione, devi solo inserire l'utente con il loro nome utente e password, e inviarli in modo sicuro al server che li controlla e (in modo sicuro) restituisce un token di sessione, quindi invii il token di sessione in ogni futura richiesta.
user253751

Risposte:


7

Ho progettato API REST negli ultimi anni. Ti preoccupi troppo. Recentemente un altro utente su questa scheda ha posto una domanda, in cui era preoccupato di memorizzare gli endpoint URI nel suo codice lato client JavaScript .

Le stesse regole si applicano a te come si applicano allo sviluppatore JavaScript. Se permetti alle persone esterne di integrare la tua API, la tua API ha la stessa visibilità di un normale sito Web e dovresti trattarla allo stesso modo.

Citazione dalla risposta originale:

Quando si crea un sito Web e non si desidera che gli utenti facciano qualcosa, non si implementa tale funzionalità o si proibisce a determinati utenti di utilizzarlo. Con un'API REST che dovrebbe avere endpoint pubblici è praticamente la stessa, è necessario trattarla come un sito Web pubblico.

L'API REST dovrebbe essere abbastanza solida da non consentire operazioni non valide, come l'accesso ai dati di un altro utente.

È necessario progettare i token di accesso dell'applicazione per consentire solo le operazioni che si desidera siano autorizzate. Potresti avere due tipi di token di accesso:

  • token principale : potrebbe essere utilizzato dal creatore dell'applicazione e fornire più funzionalità dalla tua API,
  • token dell'applicazione : il token che verrebbe effettivamente archiviato all'interno delle applicazioni e avrebbe solo un accesso limitato all'API, solo alle operazioni che non possono danneggiare i dati dell'utente o del programmatore dell'applicazione.

Ma cosa qualcuno decostruisce il codice sorgente, toglie i token dall'applicazione, scopre quali sono gli endpoint pubblici e abusa del tuo servizio web?

A meno che tu non stia gestendo direttamente lo sviluppo delle applicazioni che consumano la tua API, nulla impedisce davvero alle persone di abusare della tua API allo stesso modo direttamente dall'app.


Buona spiegazione finora, ho una domanda però. Diciamo che una delle mie API è stata creata per recuperare tutti i dati relativi (A + B) del mio utente . Il mio utente usa questa API nella sua app per ottenere solo la filtered data(B) del suo utente . Ora è possibile o esiste qualche soluzione alternativa per impedire a un terzo utente di rubare tutti i dati (A + B) del mio utente . Ha senso?
Alok Patel,

@AlokPatel Non c'è altra soluzione alternativa che semplicemente non implementare la funzionalità. Quando lo fai, c'è sempre il rischio che qualcuno falsifichi il suo hash identitario per assomigliare a qualcun altro. A livello di programmazione il problema non può essere risolto. Come ho già detto, se non si desidera offrire alcune funzionalità, non implementarlo. Dal momento che le app probabilmente memorizzeranno l'hash di accesso al loro interno, una volta distribuita l'app, così è la tua chiave API e non è disponibile pubblicamente.
Andy,

Grazie per la spiegazione. Quindi quello che ho ottenuto finora è che le API REST sono uguali a qualsiasi sito Web che distribuiamo sono aperte come il sito Web. Se non desidero che l'utente faccia qualcosa, semplicemente non lo implemento nelle mie API REST. Quindi quello che posso fare è avere chiavi separate per le librerie client (Android, iOS, JS) che possono essere compromesse con meno funzionalità e chiavi diverse che verranno utilizzate lato server (PHP, Java, node.js) con funzionalità estesa. Spero che questo funzioni!
Alok Patel,

Puoi spiegarmi questo tuo punto? A meno che tu non stia gestendo direttamente lo sviluppo delle applicazioni che consumano la tua API
Alok Patel

@AlokPatel Quello che volevo dire è che in questo momento ti preoccupi di dare a qualcuno l'accesso all'API, che potrebbe distribuire l'accesso e iniziare ad abusare dell'API. Se non hai alcun controllo sullo sviluppo delle applicazioni che consumano la tua API, potrebbero fare lo stesso anche da sole.
Andy,

5

Il tuo problema non è tecnico tanto quanto commerciale.

Supponiamo che tu abbia la tua API, che vendi ai tuoi clienti (gli sviluppatori di app) per un importo forfettario di £ 100 all'anno, accesso illimitato.

Bene, ovviamente, posso acquistare il tuo servizio a £ 100 e venderlo a 10 persone a $ 50 ciascuno. Non lo vuoi! quindi provi a pensare a una restrizione che ti permetterà di vendere la tua API senza che sia aperta all'arbitraggio.

  • Se si limita il numero di app, un cliente può creare un'unica app che accetta connessioni da altre app e le trasmette.

  • Se limiti gli utenti, di nuovo, il cliente può nascondere gli utenti dietro la propria autenticazione e apparire come un singolo utente.

Quello che devi fare è trasferire il costo di ogni chiamata API al tuo cliente. vale a dire addebito per chiamata API o impostare una quota di chiamate all'anno.

Questo porta lo stesso problema di arbitraggio sui tuoi clienti. Li costringe a mettere in atto misure per impedire ai loro utenti di rubare le loro chiavi. In questo caso, nascondere l'API dietro l'API autenticato dall'utente.


Ho già pianificato di limitare l'utilizzo della mia API in base al numero di chiamate API, quindi il problema relativo alle attività non è al momento la mia preoccupazione, sono solo preoccupato che le chiavi vengano rubate.
Alok Patel,

Dal punto di vista aziendale, il problema è irrisolvibile. Purtroppo, non è possibile risolverlo nemmeno a livello di codice.
Andy,

1
Il problema aziendale viene risolto con l'addebito per chiamata. Se la chiave viene rubata, il cliente perde. Non tu. Basta dare al cliente un modo per annullare le chiavi rubate e dire a loro che hanno un'API intermedia per prevenire l'abuso
Ewan

2

Le altre risposte sembrano suggerire che il problema di archiviare un segreto in un'app su dispositivi consumer non è risolvibile.

Certo che lo e.

Due principi (seguiranno i dettagli di attuazione):

  1. Gli endpoint effettivi di autenticazione devono essere anonimamente aperti al pubblico.
  2. Il server deve in qualche modo essere coinvolto nell'autenticazione del client e nella fornitura di una chiave API.

Dato che, se il client effettua una richiesta all'endpoint di autenticazione con credenziali e il server lo autentica, il server può generare un token temporaneo dinamico (significato temporaneo basato sul tempo). Questo token deve essere ricordato all'interno del client e inviato con richieste successive.

Avrai bisogno di un meccanismo per "aggiornare" periodicamente il token, ovvero per ottenerne uno nuovo. È sufficiente creare un endpoint REST che consenta di generare un nuovo token da uno esistente, per evitare di dover eseguire nuovamente l'autenticazione dalle credenziali.

Se stai cercando di evitare la riautenticazione dell'utente finale, questa autenticazione può essere una configurazione iniziale una tantum nell'app quando viene installata.

Questa soluzione evita semplicemente la necessità di memorizzare un token statico incorporato nel file binario dell'applicazione. Un token viene generato al volo dal server solo in risposta a un'autenticazione riuscita. Affinché un utente malintenzionato controlli la tua applicazione e cerchi di ottenere un accesso non autorizzato all'API, dovrà comunque autenticarsi come chiunque altro.


Soluzione interessante, sebbene si basi principalmente su come i clienti del PO codificheranno la loro app. Detto questo, l'approccio proposto potrebbe consentire quindi di archiviare il lato server della chiave API e, in seguito all'autenticazione riuscita dei propri utenti, potrebbe inoltrare la chiave temporanea per l'app effettiva da utilizzare. in questo modo nulla viene memorizzato nell'app stessa.
Newtopian

Questo è vero per tutte le API. Se un consumatore API non lo consuma correttamente, le cose potrebbero non funzionare. Questa dovrebbe essere una parte documentata dell'API.
Brandon,

A proposito, ci sono standard che aiutano a renderlo più facile, come OAuth.
Brandon,

0

Se si dispone di chiavi univoche per app, è possibile utilizzarle solo durante un'autenticazione della connessione iniziale, avviata dal client, dopodiché si passa a un token di autenticazione univoco per app.

Il tuo server cambia (lancia) il token per ogni app client di volta in volta (periodicamente più / meno qualche ritardo fuzzy / casuale casuale, per esempio). Il token di rotolamento è noto solo tra il server e il client autenticato.

I nuovi token vengono restituiti salvadanaio sulle risposte regolari. Ogni volta che la risposta contiene un nuovo token, l'app di ricezione deve passare a utilizzarla nelle richieste successive.

Ogni volta che lo scambio con un client non è sincronizzato (qualche errore di protocollo di qualche tipo) il tuo server richiederà una nuova autenticazione (tramite una risposta di errore alla successiva richiesta del client o appoggiato sulla risposta valida alla richiesta del client, per esempio).

L'autenticazione iniziale avviata dai client mentre viene utilizzato attivamente un token di rotolamento deve essere considerata con sospetto: potrebbe benissimo essere un tentativo di imitazione. Lo consentirei solo se lo scambio rimane inattivo per un intervallo più lungo del previsto, che potrebbe, ad esempio, essere causato da un'interruzione / riavvio del client con una nuova istanza che non ha il token di rotolamento.

Sarebbe anche meglio persistere il token sul lato client in modo che un client riavviato possa continuare da dove il suo predecessore ha lasciato - restringendo significativamente l'apertura per l'imitazione.

Tale schema renderebbe almeno abbastanza difficile l'imitazione: il client di imitazione dovrebbe prevedere esattamente la finestra quando il client autorizzato interrompe l'invio di richieste abbastanza a lungo affinché il server decida che può essere accettata una nuova autenticazione client con la chiave prescritta. Tali richieste al di fuori della finestra consentita possono essere utilizzate come rilevamento di tentativi di imitazione e possibilmente avviare alcune contromisure (lista nera IP, ecc.).


0

Da quello che so, quello che hai menzionato è l'unico modo per farlo. L'applicazione che memorizza la chiave è sicuramente un rischio, ma ci sono vari modi per aggirarla. È sempre possibile utilizzare il keystore per archiviare la chiave, anziché hardcoding, forzando così un accesso una tantum.

Inoltre, dovresti considerare di associare una chiave a un client, quindi, se qualcuno imita, dovresti avere un livello di sicurezza per controllare il client, la chiave e gli agenti utente per bloccare immediatamente la richiesta. Avere un caso d'uso per emettere nuovamente o assicurare che le chiavi non sono imitate.


Che cosa è aggirare per JavaScript? Come progettare per quello?
Alok Patel,

Presumo che tu stia parlando della creazione di un'applicazione ibrida. In tal caso, allora dovresti essere in grado di creare un plug-in per memorizzare le chiavi. Se hai intenzione di ospitare l'applicazione e parlare della soluzione Web mobile, pensa al rendering della pagina utilizzando un contenitore e puoi fare affidamento su un token di sessione suggerito in precedenza
Arun

No non è il caso. Vorrei essere il terzo provider API principale, i miei utenti useranno il mio servizio API nelle loro applicazioni. Può essere Android, iOS, JavaScript ecc ...
Alok Patel

0

Se dipendi dal dare token di autorizzazione ai tuoi clienti per inserire le loro app, sarà sempre teoricamente possibile per qualcuno di decodificare l'app ed estrarle. Per evitare ciò, è necessario un meccanismo che non richiederebbe un segreto all'interno dell'app client. È difficile. Posso suggerire alcune opzioni a cui pensare però.

Hai un problema una volta che hai dato le credenziali, non hai alcun controllo su come sono archiviate in modo sicuro. Inoltre, se richiedi all'utente di inviarti le credenziali, qualcuno può MITM la tua connessione e rubare i token direttamente senza preoccuparsi di decodificare l'app.

Un modo per rendere più difficile l'estrazione del token di autorizzazione è quello di offuscarlo. Questo aumenta il livello, ma non lo rende impossibile, e per farlo dovresti mantenere il controllo del segreto. È possibile implementare una libreria che contiene informazioni segrete ed è specifica per ciascun cliente. Potresti usare la libreria per comunicare con i tuoi server e potresti non dover nemmeno dire al tuo utente le informazioni segrete, potrebbe essere semplicemente incorporato nella libreria. Questo non risolve il problema di qualcuno che decodifica la tua biblioteca, ma ti mette in controllo del livello di offuscamento. Uno svantaggio è che una volta che una persona ha interrotto l'offuscamento nella libreria, può attaccare qualsiasi libreria del tuo, a meno che tu non scriva un codice che rende ogni libreria significativamente diversa. Ciò introduce una propria serie di problemi.

Questo potrebbe discostarsi leggermente dall'ambito della tua domanda, ma è legato alla sicurezza del tuo token, quindi lo menzionerò. Per evitare il banale furto del token sul filo, probabilmente non si desidera inviare direttamente il token, ma è possibile firmare il traffico utilizzando una funzione HMAC. È possibile verificare la validità del messaggio calcolando l'HMAC del messaggio sul server e confrontandolo con l'HMAC inviato dal client. Utilizzeresti il ​​token come chiave della funzione HMAC in modo che solo qualcuno che conosca il token possa firmare il traffico. Questo è meglio per la sicurezza del tuo token perché non lo invii mai direttamente al server, quindi non può essere intercettato e rubato direttamente. Per ulteriori informazioni su HMACS, consultare questa domanda: /security/20129/how-and-when-do-i-use-hmac/20301

Nessuna soluzione di sicurezza sarà inespugnabile, devi decidere quanto ti costerà implementare rispetto alla probabilità e al costo di essere compromesso.


Non riesco a creare una libreria e inserirci dei segreti, questi saranno diversi per ciascuno dei miei utenti.
Alok Patel

Per chiarire, stavo suggerendo che potresti creare una libreria personalizzata per ciascuno dei tuoi utenti e nascondere i loro segreti individuali all'interno della libreria. Dovresti scrivere un sistema per generare automaticamente le librerie su richiesta per ogni nuovo utente che potrebbe essere più lavoro di quello che vuoi fare.
ThePragmatist

0

Citando te stesso:

Non riesco a capire come autenticare il client / utente ... in cui non possono inserire il loro nome utente e password per autenticarsi.

Ora è un po 'una contraddizione, no? ;)

Come altri hanno detto, non puoi. Se un'app utilizza una chiave API, è possibile decompilarla come dici per ottenere le chiavi e usarla anche.

Oltre a richiedere un'ulteriore autenticazione dell'utente corretta, è possibile limitare solo il danno:

  • whitelisting / blacklist IP
  • strozzamento
  • rilevamento "attività insolite" e la sua fonte
  • rinnovo chiave facile
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.