Autenticazione API REST con protezione JWT e CSRF per SPA

8

Sto sviluppando una SPA con il back-end REST e voglio avere una semplice autenticazione basata su token. L'obiettivo di REST è di essere apolidi. Spiegherò il modello di sicurezza e cercherò di fare riferimento a tutte le fonti per le decisioni prese durante la progettazione. Vorresti un commento sull'intero setup e rispondi ad alcune domande specifiche.

Riepilogo

L'autenticazione verrà eseguita su un endpoint dedicato (ad esempio / auth / login). Le informazioni di accesso verranno passate come oggetto JSON. Le informazioni conterranno nome utente e password. All'accesso riuscito, verrà emesso un token JWT firmato. Questo token verrà utilizzato per l'accesso successivo all'API REST.

L'applicazione utilizzerà HTTPS e io controllo tutti i sottodomini.

Specifiche

JWT

  • Contiene nome utente, emesso e scadenza
  • Contiene indicazioni sull'appartenenza al ruolo all'interno di un'applicazione
  • Contiene un token CSRF (generato casualmente da un generatore pseudocasuale crittograficamente sicuro)
  • Firmato con una chiave HMAC (SHA256) disponibile solo per il server

Scadenza

Un token verrà emesso con una breve scadenza (ad esempio 30 minuti). Un token aggiornato con nuova scadenza verrà emesso ad ogni richiesta (scadenza della finestra scorrevole) con un termine ragionevole (ad esempio 8 ore). Il flusso del processo sarà il seguente:

  1. La richiesta di accesso iniziale emetterà un token con scadenza di 30 minuti
  2. La prossima richiesta controllerà se il token è scaduto. Se è scaduto, l'accesso sarà bloccato. In caso contrario, una richiesta verrà soddisfatta. A quel punto verrà effettuato un controllo sull'età del token.

    • Se l'età è entro la scadenza (meno di 8 ore), verrà generato un token aggiornato contenente un nuovo tempo di scadenza per altri 30 minuti. Rilasciato al momento rimarrà lo stesso del token originale.
    • Se l'età del token è scaduta, non verranno generati token aggiornati e l'utente dovrà accedere di nuovo.

Razionale: voglio proteggere un token con una breve scadenza se è compromesso. Inoltre, non voglio forzare l'utente a relogin spesso. Un utente malintenzionato dovrebbe richiedere un nuovo token in un lasso di tempo inferiore alla scadenza di un token. Nel caso in cui un utente malintenzionato riesca a farlo, il tempo massimo che può utilizzare per il token è definito dalla scadenza. L'utente è in grado di rimanere online per un periodo di scadenza prefissato. Per una domanda di lavoro è sufficiente una scadenza di 8 ore o un giorno. Questa implementazione è abbastanza sicura? Quali sono i possibili inconvenienti e vulnerabilità?

trasporto e archiviazione JWT

JWT sarà trasportato come cookie httpOnly al client e verrà archiviato nel repository Cookies sul browser.

Razionale: proteggere un token dall'attacco XSS che comprometterebbe il token se tenuto all'interno di localStorage / sessionStorage. Questo è un consiglio da questo articolo. Qualcosa non va con questo approccio se non l'apertura dell'implementazione a un attacco CSRF?

Protezione CSRF

L'archiviazione dei token JWT all'interno dei cookie aprirà l'implementazione a un attacco CSRF. Per mitigare questo problema, viene implementato un metodo di cookie double submit. Il token CSRF viene generato e incluso all'interno del token JWT. Questo token viene inoltre fornito all'applicazione client in un oggetto JSON di una risposta alla richiesta di accesso. L'applicazione memorizzerà CSRF in localStorage e lo invierà ad ogni richiesta all'interno di un'intestazione personalizzata.

Razionale: come da risposta a questa domanda di riferimento questo articolo , per un'efficace protezione CSRF è necessario legare crittograficamente il token CSRF con un cookie di identificazione / autenticazione di sessione. Se includo un token in una JWT, è considerato crittograficamente legato a una sessione di sicurezza?

Concettualmente, vedi qualcosa di sbagliato in questa implementazione?

    
posta Marko Vodopija 21.02.2017 - 13:10
fonte

1 risposta

3

Is this implementation safe enough? What are possible drawbacks and vulnerabilities?

Le JWT sono token Bearer auto-descriventi. I due principali svantaggi di JWT sono i token stantii e l'impossibilità di espellerli su richiesta.

Token obsoleti

Se il ruolo dell'utente cambia, non verrà riflesso nel token emesso. Dovrai emetterne uno nuovo di zecca. Idealmente, scadrebbe quello precedente, il che ci porta al prossimo problema.

Nessuna scadenza su richiesta

Le JWT non possono essere scadute su richiesta in quanto sono esse stesse apolidi. Un approccio per risolvere questo è la lista nera JWT, ma questo ucciderà l'apolidia del tuo server. Ciò significa anche che l'utente non può effettuare il logout dall'applicazione in quanto non è possibile invalidare i token su richiesta.

Informazioni sui token di breve durata. Se l'attaccante è in possesso di un token di breve durata, può semplicemente interrogare la tua API per "tenerlo in vita" per tutto il tempo che gli permetti (8 ore o 1 giorno).

Dovrai decidere se questo è abbastanza sicuro. Tutto dipende da quali trade-off sei disposto a fare.

Anything wrong with this approach other than opening the implementation to a CSRF attack?

Funziona perfettamente. Ho visto molti siti Web usarlo. Tuttavia, devi preoccuparti di CSRF. A meno che la tua API sia solo JSON. Vedi qui .

If I include a token inside a JWT, is it considered cryptographically tied to a security session?

Sì, sebbene non sia possibile ruotare efficacemente questo segreto a causa dei problemi di terminazione su richiesta che ho descritto sopra. Questo è, ancora una volta, un compromesso.

Conceptually, do you see anything wrong with this implementation?

Io, penso che quello che hai descritto sia perfettamente ragionevole. Ha i suoi svantaggi e compromessi, ma solo tu conosci l'esatto business case che devi supportare. Se nessun logout, token stantii e un token CSRF fisso per sessione sono accettabili, allora va tutto bene.

    
risposta data 31.07.2017 - 22:50
fonte

Leggi altre domande sui tag