Supponendo TLS 100% per tutte le comunicazioni, sia durante che dopo l'accesso, l'autenticazione con nome utente/password tramite l'autenticazione di base e la ricezione di un JWT in cambio è un caso d'uso valido. Questo è quasi esattamente come funziona uno dei flussi di OAuth 2 ('password grant').
L'idea è che l'utente finale sia autenticato tramite un endpoint, ad es. /login/token
utilizzando qualsiasi meccanismo che si desidera e la risposta deve contenere il JWT che deve essere restituito a tutte le richieste successive. Il JWT dovrebbe essere un JWS (vale a dire un JWT crittografato) con un campo di scadenza JWT appropriato (exp
): ciò garantisce che il client non possa manipolare il JWT o farlo vivere più a lungo di quanto dovrebbe.
Non hai bisogno di un header X-Auth-Token
sia: lo schema di autenticazione HTTP Bearer
è stato creato per questo caso esatto uso: in pratica qualsiasi bit di informazione che sentieri il nome schema Bearer
è informazione 'portatore' che dovrebbe essere convalidato. Basta impostare il Authorization
intestazione:
Authorization: Bearer <JWT value here>
Ma, detto questo, se il client REST è 'attendibile' (browser ad esempio JavaScript abilitato), non voglio fare nemmeno quello: qualsiasi valore nella risposta HTTP che è accessibile tramite JavaScript - praticamente qualsiasi valore di intestazione o valore del corpo della risposta - potrebbe essere annusato e intercettato tramite attacchi MSS XSS.
È meglio memorizzare il valore JWT in un cookie solo sicuro, http-only (cookie config: setSecure (true), setHttpOnly (true)). Ciò garantisce che il browser:
- sempre e solo di trasmettere il cookie tramite una connessione TLS e,
- mai fare il valore del cookie disposizione di codice JavaScript.
Questo approccio è quasi tutto ciò che è necessario fare per la sicurezza delle best practice. L'ultima cosa è assicurarsi di avere una protezione CSRF su ogni richiesta HTTP per garantire che i domini esterni che avviano richieste al tuo sito non possano funzionare.
Il modo più semplice per farlo è impostare un cookie sicuro solo (ma NON solo http) con un valore casuale, ad es. un UUID.
Quindi, su ogni richiesta nel server, assicurarsi che il proprio codice JavaScript legga il valore del cookie e lo imposti in un'intestazione personalizzata, ad es. X-CSRF-Token e verificare quel valore su ogni richiesta nel server. I client di dominio esterni non possono impostare intestazioni personalizzate per le richieste al tuo dominio a meno che il client esterno non ottenga l'autorizzazione tramite una richiesta di Opzioni HTTP, quindi qualsiasi tentativo di attacco CSRF (ad esempio in un IFrame, qualunque cosa) non andrà a buon fine.
Questa è la migliore protezione disponibile per i client JavaScript non attendibili sul web che conosciamo oggi. Stormpath ha scritto un articolo su these techniques e anche se sei curioso.
Infine, il Stormpath Java Servlet Plugingià fa tutto questo per voi (e molto più roba fresca, comprese le ulteriori controlli di sicurezza automatizzati), in modo da non mai a scriverlo - o peggio - mantenere da soli. Guarda il HTTP Request Authentication section e l'esempio Form/Ajax per vedere come usarlo. HTH!
Come viene inviato il token al server nelle richieste successive? (Intestazione HTTP? Cookie?). Inoltre, stai usando TLS (SSL)? –
Ciao Les, è bello vederti spuntare di nuovo! Sì, il token viene inviato come intestazione X-Auth-Token. Sto anche usando TLS. TLS è obbligatorio quando si utilizza un JWT? – Stephane
Ciao Stephane! :) Se il JWT rappresenta un'identità verificata, sì, considererei obbligatorio TLS, altrimenti è (molto) più facile per gli attacchi MITM. –