Autenticazione
L'autenticazione sarà basata sulla firma. La firma verrà generata utilizzando:
HMAC_SHA256(SHA1(secret_key) + '#' + request_data + '#' + utc_timestamp)
Anche utc_timestamp verrà incluso nell'intestazione X-Timestamp o nell'URL utilizzando il parametro _timestamp . Il request_data conterrà tutti i parametri (URL e POST) e le intestazioni relative alle API. Tutti questi dati saranno in minuscolo, ordinati e uniti usando = e & .
Generalmente, l'API REST supporterà tre schemi di autenticazione:
-
Chiavi API basate: la firma includerà la chiave segreta speciale associata alla particolare chiave API. Utilizzerà l'intestazione
X-API-Keyo il parametro_api_keyURL e l'intestazioneX-API-Signatureo il parametro_signatureURL. -
Credenziali utente in base: la firma utilizzerà la password come chiave segreta. Utilizzerà l'intestazione
X-API-Signatureo il parametro_signatureURL e il parametrostaff_nameURL. -
Sessione in base: la firma utilizzerà la password dell'utente o un codice appositamente creato (ulteriori dettagli di seguito) ... utilizzerà l'intestazione
X-Session-Signatureoppure il parametro_session_signatureURL e l'intestazioneX-Session-IDo il parametro_session_idURL.
Tieni presente che la specifica consente di utilizzare Credenziali utente e Sessione contemporaneamente (ovvero, le intestazioni e i parametri non sono in conflitto).
Sessione
Disclaimer: Sì, lo so - le sessioni non sono RESTful, poiché sono stateful ... Tuttavia, il nostro prodotto richiede sessioni per alcune funzionalità e, per ragioni di semplicità, vogliamo mantenere una API / protocollo - quindi non sto cercando di entrare in un dibattito RESTful. Preferisco pensare che una sessione sia solo una risorsa, che devi mantenere mentre lavori con l'API.
La sessione sarà solo una risorsa: /api/v1/session .
Quindi, la procedura standard:
-
Per creare una sessione un'applicazione client dovrà inviare una richiesta POST utilizzando l'autenticazione credenziali dello staff , che è stata descritta sopra:
POST /api/v1/session&staff_name=s-andy. -
Il server risponderà con
201 Createde invierà l'ID di sessione nel corpo della risposta. -
Successivamente l'applicazione client utilizzerà questo ID di sessione e la password dello staff per accedere all'API.
Dopo aver ottenuto una richiesta con un particolare ID di sessione, il server aggiornerà l'ultima volta in cui è avvenuta l'accesso alla risorsa di sessione appropriata.
Ma i nostri utenti avranno anche un'opzione per usare l'autenticazione a due fattori. Nell'interfaccia utente dopo aver effettuato l'accesso a tali utenti verrà richiesto di inserire il codice di verifica , che arriverà ai propri dispositivi mobili. Quando ho progettato l'autenticazione ho pensato che sarebbe stato fantastico avere un "segreto" speciale invece della password dell'utente per la sessione. Poi mi sono reso conto: perché non utilizzare questo codice di verifica ?
Quindi il flusso per l'autenticazione a due fattori sarà:
-
Un'applicazione client invia una richiesta POST utilizzando le credenziali dello staff .
-
Il server avvia il codice di verifica generazione e consegna e restituisce
202 Acceptedcon l'id di sessione, ma la sessione non è ancora stata verificata. -
Entro 30 secondi l'applicazione client invia qualsiasi richiesta utilizzando l'id di sessione nell'intestazione
X-Session-IDo nel parametro_session_idURL e il codice di verifica come segreto per generare la firma. -
Avendo ottenuto tale richiesta il server aggiorna la sessione facendola verificare e salva il codice di verifica (alias password unica) come chiave segreta per questa sessione.
-
Successivamente l'applicazione client utilizzerà l' id di sessione e il codice di verifica (come chiave segreta) per accedere all'API.
-
Quando la sessione scade e, pertanto, viene eliminata o quando l'utente elimina la sessione (cioè esegue la disconnessione), l'ID della sessione e la "password unica" diventano inutilizzabili.
Volevo utilizzare questa comunità di esperti come cassa di risonanza per questa idea di autenticazione a due fattori; riesci a vedere le insidie che non posso?