Pattern di accesso API REST


181

Sto creando un API REST, seguendo da vicino i suggerimenti di apigee, usando nomi non verbi, versione di API inserita nell'URL, due percorsi di API per raccolta, OTTIENI POST PUT ELIMINA utilizzo, ecc.

Sto lavorando sul sistema di accesso, ma non sono sicuro del modo REST corretto per accedere agli utenti. Non sto lavorando sulla sicurezza a questo punto, solo il modello o il flusso di accesso. (Più avanti aggiungeremo 2 step oAuth, con un HMAC, ecc.)

Possibili opzioni

  • UN POST a qualcosa del genere https://api...com/v1/login.json
  • MESSA A qualcosa di simile https://api...com/v1/users.json
  • Qualcosa di cui non ho pensato ...

Qual è lo stile REST corretto per l'accesso degli utenti?


9
Questo è il formato di risposta. .json dice al server di rispondere con json, .xml dice al server di rispondere con il formato xml. Piuttosto quello che lo rende un parametro opzionale dietro il?. blog.apigee.com/detail/…
Scott Roepnack il

28
Non ho mai visto la negoziazione dei contenuti sull'URL, solo nelle intestazioni. Sull'URL significa che perdi i vantaggi della memorizzazione nella cache e altro ancora.
Oded,

10
@ScottRoepnack allora dovresti considerare l' Acceptintestazione HTTP.
Alessandro Vendruscolo,

2
@Oded Se avessi usato Acceptun'intestazione, avresti anche un Vary: Accept, quindi la cache non sarebbe influenzata. Conneg in estensione è stato discusso in precedenza ; Concordo con la risposta di Shonzilla, comunque.
cmbuckley,

2
@Oded - Non capisco. perché dovresti perdere il vantaggio della memorizzazione nella cache se specifichi il tipo di contenuto nell'URL (come suffisso .json nel percorso della query o come parametro di query type = json)? E chi sei "tu" in questo caso? Chi è la persona che perde i vantaggi della memorizzazione nella cache? mi sembra che i risultati di qualsiasi query possano essere memorizzati nella cache indipendentemente da ciò che si trova nel percorso della query o nei parametri.
Cheeso,

Risposte:


138

Principled Design of the Modern Web Architecture di Roy T. Fielding e Richard N. Taylor , ovvero la sequenza di lavori di tutta la terminologia REST, contiene la definizione di interazione client-server:

Tutte le interazioni REST sono apolidi . In altre parole, ogni richiesta contiene tutte le informazioni necessarie affinché un connettore comprenda la richiesta, indipendentemente dalle richieste che potrebbero averla preceduta .

Questa restrizione svolge quattro funzioni, la prima e la terza sono importanti in questo caso particolare:

  • 1 ° : elimina qualsiasi necessità che i connettori mantengano lo stato dell'applicazione tra le richieste , riducendo così il consumo di risorse fisiche e migliorando la scalabilità;
  • 3 ° : consente a un intermediario di visualizzare e comprendere una richiesta in modo isolato , che può essere necessario quando i servizi vengono riorganizzati dinamicamente;

E ora torniamo al tuo caso di sicurezza. Ogni singola richiesta dovrebbe contenere tutte le informazioni richieste e l'autorizzazione / autenticazione non fa eccezione. Come raggiungere questo obiettivo? Invia letteralmente tutte le informazioni richieste via cavo con ogni richiesta.

Uno degli esempi su come archiviare questo è il codice di autenticazione dei messaggi basato su hash o HMAC . In pratica questo significa aggiungere un codice hash del messaggio corrente ad ogni richiesta. Codice hash calcolato dalla funzione hash crittografica in combinazione con una chiave crittografica segreta . La funzione hash crittografica è predefinita o fa parte della concezione REST di codice su richiesta (ad esempio JavaScript). La chiave crittografica segreta deve essere fornita dal server al client come risorsa e il client la utilizza per calcolare il codice hash per ogni richiesta.

Ci sono molti esempi di implementazioni HMAC , ma vorrei che tu prestassi attenzione ai seguenti tre:

Come funziona in pratica

Se il client conosce la chiave segreta, è pronto per operare con le risorse. Altrimenti verrà temporaneamente reindirizzato (codice di stato 307 Reindirizzamento temporaneo) per autorizzare e ottenere la chiave segreta, quindi reindirizzato alla risorsa originale. In questo caso non è necessario sapere in anticipo (ovvero hardcode da qualche parte) qual è l'URL per autorizzare il client ed è possibile modificare questo schema con il tempo.

Spero che questa volontà ti aiuti a trovare la soluzione giusta!


23
Un MAC ha lo scopo di dimostrare l'autenticità dei messaggi e proteggere contro la manomissione - non ha nulla a che fare con l'autenticazione dell'utente
yrk,

1
Aggiunto uno degli esempi, come gestire l'autenticazione utente / client senza conoscere in anticipo " URL di accesso "
Akim

Ecco altri due bei articoli con esempi di autenticazione apolidi per i servizi REST: blog.jdriven.com/2014/10/… technicalrex.com/2015/02/20/…
Vladimir Rozhkov,

41

TL; DR Login per ogni richiesta non è un componente richiesto per implementare la sicurezza API, lo è l'autenticazione.

È difficile rispondere alla tua domanda di accesso senza parlare di sicurezza in generale. Con alcuni schemi di autenticazione, non esiste un login tradizionale.

REST non impone alcuna regola di sicurezza, ma l'implementazione più comune in pratica è OAuth con autenticazione a 3 vie (come hai menzionato nella tua domanda). Non esiste alcun accesso di per sé, almeno non con ogni richiesta API. Con l'autenticazione a 3 vie, usi solo i token.

  1. L'utente approva il client API e concede l'autorizzazione a effettuare richieste sotto forma di token di lunga durata
  2. Il client Api ottiene un token di breve durata utilizzando quello di lunga durata.
  3. Il client Api invia il token di breve durata con ogni richiesta.

Questo schema offre all'utente la possibilità di revocare l'accesso in qualsiasi momento. Praticamente tutte le API RESTful disponibili al pubblico che ho visto usano OAuth per implementare questo.

Non penso che dovresti inquadrare il tuo problema (e la tua domanda) in termini di accesso, ma piuttosto penso a proteggere l'API in generale.

Per ulteriori informazioni sull'autenticazione delle API REST in generale, puoi consultare le seguenti risorse:


Sì, OAuth! Risposta molto semplice, dovrebbe essere la risposta accettata, imho.
Levite,

26

Una parte importante della filosofia REST è quella di sfruttare il maggior numero possibile di funzionalità standard del protocollo HTTP durante la progettazione dell'API. Applicando tale filosofia all'autenticazione, client e server utilizzerebbero le funzioni standard di autenticazione HTTP nell'API.

Le schermate di accesso sono ottime per i casi d'uso di utenti umani: visita una schermata di accesso, inserisci utente / password, imposta un cookie, il client fornisce quel cookie in tutte le richieste future. Non ci si può aspettare che gli esseri umani che utilizzano browser web forniscano un ID utente e una password per ogni singola richiesta HTTP.

Ma per un'API REST, una schermata di accesso e i cookie di sessione non sono strettamente necessari, poiché ogni richiesta può includere credenziali senza influire su un utente umano; e se il cliente non collabora in qualsiasi momento, si 401può dare una risposta "non autorizzata". RFC 2617 descrive il supporto per l'autenticazione in HTTP.

TLS (HTTPS) sarebbe anche un'opzione e consentirebbe l'autenticazione del client al server (e viceversa) in ogni richiesta verificando la chiave pubblica dell'altra parte. Inoltre, questo protegge il canale per un bonus. Naturalmente, è necessario uno scambio di coppia di chiavi prima della comunicazione. (Nota, si tratta in particolare di identificare / autenticare l'utente con TLS. Proteggere il canale usando TLS / Diffie-Hellman è sempre una buona idea, anche se non si identifica l'utente con la sua chiave pubblica.)

Un esempio: supponiamo che un token OAuth siano le credenziali di accesso complete. Una volta che il client ha il token OAuth, può essere fornito come ID utente nell'autenticazione HTTP standard con ogni richiesta. Il server potrebbe verificare il token al primo utilizzo e memorizzare nella cache il risultato del controllo con un time-to-live che viene rinnovato con ogni richiesta. Qualsiasi richiesta che richiede l'autenticazione ritorna 401se non fornita.


1
"poiché ogni richiesta può includere credenziali senza influire su un utente umano" sono state inventate l'autenticazione a 3 vie e OAuth perché la cosa tra virgolette non è buona. Se si forniscono le credenziali con ogni richiesta senza un meccanismo sul server per revocarle, ciò non sarebbe sicuro se utilizzato senza SSL.
Slavo,

1
Ogni volta che esiste un concetto di utenti, qualcosa deve passare dal client al server per identificare quale utente. Un token OAuth può certamente servire come "credenziali" qui, anziché una combinazione utente / password effettiva. Assicurare il canale con TLS è sicuramente sempre una buona cosa, ma è quasi un punto. Anche se si utilizza un cookie, una sorta di token viene comunque inviata al server con ogni richiesta, solo con un'intestazione di cookie anziché un'intestazione di autenticazione.
wberry,

E se non stai usando TLS o OAuth per qualsiasi motivo, inviare un utente / password ogni volta è davvero peggio che inviarlo solo una volta? Se l'attaccante può ottenere l'utente / la password, è probabile che anche l'attaccante ottenga il cookie di sessione.
wberry,

La differenza tra un cookie e un'intestazione di autenticazione come credenziali è che i cookie sono sempre associati a un determinato dominio. Ciò significa che quando l'API riceve un cookie, sa da dove proviene (è stato scritto dallo stesso dominio in precedenza). Con un'intestazione, non lo sai mai e devi implementare controlli specifici per questo. In generale, sono d'accordo, sono entrambe credenziali, ma penso che il passaggio delle credenziali non sia il login. Il login è l'azione attiva di apertura della porta. Nel caso dell'autenticazione a 3 vie, solo la prima approvazione del client sarebbe login.
Slavo,
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.