Django Rest TokenAuthentication fara expiration time, cat de riscant e?

Salut,
Pentru un proiect personal am ales Backend - Django Rest Framework si Frontend - Angular

Pentru autentificare nu am implementat JWT, am lasat TokenAuthentication default, apoi am vazut ca nu exista si token expiration time pentru el.

Daca nu dai logout ca si user, tokenul nu expira si cand repornesti browserul ramai autentificat. E problematic daca mai multi utilizatori folosesc acelasi browser.

Site-ul nu implica CC store sau alte date sensibile pentru utilizator.

Voi implementa JWT, dar sunt curios TokenAuthentication fara expiration time, cat de riscant e?

Mersi

Intrebarea e retorica :sunglasses:

1 Like

Ti-ai raspuns singur la intrebare mai sus

Nu ma pricep, dar am luat-o pe common sense

Nu faceți decât să răspândiți o gândire dogmatică, nu oferiți un răspuns real. De ce e întrebarea retorică? Cum și-a răspuns singur? De ce este common sense?

Eu nu am folosit niciodată JWT, habar n-am cum trebuie folosit sau care este best practice, dar pentru mine common sense spune că nu-i o problemă, deoarece:

  • Nu contează dacă tokenul expiră după o lună sau după zece;
  • Dacă userul schimbă parola, se invalidează toate tokens existente

Deci?

2 Likes

s-ar putea sa fie de fapt un api-token standard si sa nu se schimbe daca nu ii faci o resetare explicita (banuiesc ca de asta nici nu are expiration time).
era o vreme cand erau suficiente :slight_smile:
acum… daca e suficient pentru cazul de fata… presupun ca depinde de scopul si nivelul de securitate dorit.

Depinde cum stochezi si cum accesezi acest token in FE, daca il tii in memorie - iti permiti asta pentru ca e un SPA, teoretic nu ai nevoie de refresh, s-ar putea sa fii cat de cat in siguranta si iti rezolva si problema autentificarii cu mai multi utilizatori in taburi diferite.

Oricum nu e o practica grozava sa emiti tokeni care nu expira.

Fiind prima data cand implementez autentificare pentru SPA backend + frontend, scopul intrebarii este sa aflu care sunt riscurile de securitate si diferite pareri, in nici un caz nu este o intrebare retorica.

Am pornit de la autentificarea default in Django Rest si mai tarziu am observat ca token-ul, nu expira.

Fiind un framework cunoscut si folosind ultima varianta am considerat ca daca ei lasa asa default, nu ar trebui sa fie un risc major de securitate.

Dar totusi vreau sa aflu mai multe pareri pentru a ma hotara daca sa implementez sau nu autentificarea cu JWT.

Nu ar fi complicat avand pachet pentru asta, dar totusi vreau sa inteleg care sunt riscurile in cazul in care las asa.

Eu nu am folosit niciodată JWT, habar n-am cum trebuie folosit sau care este best practice, dar pentru mine common sense spune că nu-i o problemă, deoarece:

  • Nu contează dacă tokenul expiră după o lună sau după zece;
  • Dacă userul schimbă parola, se invalidează toate tokens existente

In backend am pus

        # Set the new password
        user.set_password(serializer.validated_data['new_password'])
        user.save()

        # Invalidate existing auth tokens if any
        Token.objects.filter(user=user).delete()

        return Response({'detail': 'Parola a fost schimbata cu succes.'}, status=status.HTTP_200_OK)

Totusi vechiul authToken ramane salvat in Local storage si trebuie sa obtina un token nou.

M-am gandit la varianta ca in front-end dupa isi schimba parola sa il deloghez automat → se sterge authToken din Local storage si sa il redirectionez catre pagina de login.

Altfel ar fi obligat sa se logheze din nou si sa obtina noul authToken in Local storage.

Totusi nu mi se pare user friendly aceasta varianta.

Am urmatoarele 2 intrebari:

  1. Voi cum ati proceda in acest caz? L-ati deloga din cont sau ati alege alta varianta?

  2. Care sunt riscurile de securitate in afara cazului in care daca userul nu s-a delogat si alt user are access la browser, implicit la aplicatie?

Mersi

1 Like

Uite eu aici am o nedumerire. Ok, este salvat local, dar nu ai o pereche și pe server? Când schimbi pass sau logout, nu poți șterge și cheia de pe server?

(De fapt, logica pentru expirare nu este implementată pe server?)

Din cîte știu practica recomandată este să emiți o pereche te tocăni ( jwt, refresh). Apoi din FE verifici tocănul la fiecare 30 sau 60 de secunde și în cazul în care a expirat emiți altă pereche. JWT-ul expiră după 4 ore. Altă practică e să-i ții în cookie în loc de local storage.

Sper să ajute.

Jwt expira atunci cand scrie pe el ca expira. Daca vrei sa il anulezi din be trebuie sa il scrii in bd si sa il verifici cu fiecare request, ceea ce invalideaza unul din cele mai mari beneficii ale jwt vs cookie session

2 Likes

Exact, efectiv transformi in “sesiune” pentru ca ai un punct central in care stochezi tokenii, aia e toata smecheria cu tokenii ca ii poti valida oriunde fara sa ii stochezi si citesti dintr-o BD centralizata.

Timpul scurt de viata al tokenilor este dat tocmai pentru ca nu ai cum sa ii invalidezi intr-un mod simplu.

1 Like

Așa e implementarea în firebase, token care expiră rapid după 15 minute și un token de refresh care e folosit doar la generarea unui nou token de acces cu expirare rapidă.

La ei librăria se ocupă de refresh automat doar ca e o operațiune asincrona si complică codul de acces.

1 Like

Functionalitatea este in felul urmator:

Pe baza email si parola, te autentifici in backend si primesti raspuns un token pentru user. Tokenul respectiv se salveaza in front-end in Local storage.

Cand vrei sa apelezi rute din backend pentru acel user, de ex contul meu, anunturile tale etc pentru acele rute adaugi la request in header, Authorization Token d6ea98c5afefdf2fb4963806c95568a76ed4aca9, unde tokenul e cel salvat in local storage dupa ce te-ai logat.

Backendul verifica acel Token in tabela Tokens pentru acel user si daca e corect intoarce response.

Cand te deloghezi din front end, apelezi functia logout, aceasta sterge AuthToken din Local storage si la randul ei apeleaza functia logout din backend care sterge tokenul pentru user din tabela de Tokens.

Daca user-ul din front va face apeluri catre backend unde e nevoie de token va trebui sa se logheze din nou si astfel se obina un nou Auth token cu care sa faca request.

Pana cum tokenul se sterge la logout in front-end din Local Storage si in Back-end din tabela de Tokens.

Tu ai spus.

  • Nu contează dacă tokenul expiră după o lună sau după zece;
  • Dacă userul schimbă parola, se invalidează toate tokens existente

Cazul in care userul e logat in cont, exista Auth token in local storage si userul navigheaza catre url sa isi schimbe parola si face un apel catre backend ruta change-password.

In Backend am 2 variante:

a) doar ii schimb parola, caz in care functionarea nu se schimba cu nimic, tokenul e in continuare salvat in Local storage pentru Front end si exista si in tabela de tokens din Backend

b) Poate ca ar fi o masura de siguranta, daca de ex user-ul a fost logat pe mai multe device-uri si Auth token e salvat in local storage, cand schimb parola din backend sa sterg si tokenul din tabela de Tokens.

Nu stiu daca tu te-ai referit la acest aspect la punctul 2.

ceva gen

# Set the new password
user.set_password(serializer.validated_data['new_password'])
user.save()

# Invalidate existing auth tokens if any
Token.objects.filter(user=user).delete()

In acest caz in backend tokenul nu mai exista, dar a ramas cel din Front-end din local storage dar care nu mai e bun.

Userul din front ca sa faca requests are nevoie de un nou token pe care il obtine doar daca se autentifica.

Ca sa rezolv problema aceasta vad 2 variante:

a). cand schimba parola in front-end sa ii sterg si tokenul din Local storage si s ail redirectionez inapoi la pagina de login, ca sa se autentifice si astfel sa obtina un nou token.
Dar nu mi se pare user friendly.

b). Sa fac asta cumva in paralel, la schimbarea parolei, sa ii sterg tokenul vechi din Local storage si sa ii obtin un nou token de autentificare din backend, dar fara sa il oblig sa se autentifice.

Sa fac asta in spate cumva, trebuie sa vad cum as putea.

Sper sa se fi inteles functionalitatea :slight_smile:

Am 2 Intrebari:

  1. In functionalitatea prezentata sunt riscuri majore de securitate daca merg pe varianta asta cu token care nu expira?

Nu salvez CC sau alte date sensibile, dar totusi as vrea sa fie safe autentificarea.

Pot adauga JWT chiar daca am facut autentificarea in varianta de mai sus, dar ma intereseaza mai mult sa inteleg procesul si riscurile.

Am inceput astfel, datorita faptului ca Django rest e foarte cunoscut si daca ar fi fost un risc major de securitate presuspun ca nu ar fi lasat tokenul asa default.

Ca alternativa, pot folosi JWT caz in care nici nu mai fac apeluri catre db sau un pachet mai complex de autentificare GitHub - jazzband/django-rest-knox: Authentication Module for django rest auth care are si expiration time pentru token.

  1. Cat de important e atunci cand userul schimba parola sa ii invalidez/sterg tokenul existent?
    Sunt si alte motive in afara de cel expus de mine?

Mersi

2 Likes

Daca un utilizator se autentifica de 1 mil de ori, ramai cu 1 mil de tokens in baza de date care nu dispar niciodata? DoS banal.

Apoi, cu cat e mai longeviv un token, cu atat cresc sansele de a-l gasi cu brute force (cu toate ca la asa tokens lungi, nu e un risc prea mare).

1 Like

Exista un singur tok / user indiferent de cate ori te autentifici.

Pe login primesti acelasi tok din backend chiar daca accesezi url-ul din front-end de 1 milion de ori. Tokenul se sterge la logout sau la change password si atunci esti obligat sa te autentifici din nou in frontend ca sa primesti noul token.

Nu ar avea nici un sens sa creezi un token nou la fiecare autentificare.

Este vorba despre:

Fondul discutiei era ca acel token nu expira si ramane valabil infinit time, pana la logout si ce riscuri de securitate implica.

1 Like

Folosesti session cookie dar in loc sa folosesti httponly si secure tu il salvezi in local storage… o tampenie venita de la niste pseudo programatori js

Mersi de idee! Intr-adevar, in tutoriale unde m-am uitat se salveaza in local storage pentru ca e mai accesibil pe partea de client sau se foloseste JWT.

Cu HTTP-only cookies as seta sa expire peste 1 zi si as rezolva problema cu expiration time pentru token + previn XSS attacks.

Pe de alta parte, HTTP-only cookies nu mai pot fi accesibile pe partea de client side si ar trebui de fiecare data cand am nevoie sa verific daca user-ul e autentificat sa fac un request catre server.

Probabil din acest motiv se foloseste local storage.

Daca ai multi users logati in acelasi timp si la fiecare requests verifici serverul sa vezi daca userul e autentificat, mai fezabil ar fi sa folosesti JWT.

Si revin la intrebarea initiala, cat de atat de riscanta e abordarea cu local storage si token care nu expira?

Probabil o sa implementez si eu JWT pana la urma.

Durata de viata a cookieului + durata de viata a sesiunii pot fi diferite. In acelasi timp politica schimbare a id-ului iarasi este separata.

Request la server faci oricum. La login salvezi in local storage salvezi ca userul este logat si ce alte detalii mai ai nevoie pe FE si pasteezi asta pana un request din BE intoarce 401 cand ii spui userului: ne pare rau dar trebuie sa te loghezi.

Asta e o nonproblema. Cu fiecare request pe care il faci la BE acel server va trebui sa verifice oricum ca userul este autentificat…

Este mai riscant cat de mult conteaza ce fel de date salvezi si care pot fi pagubele.
Pe langa asta nu ai inteles problema initial. Daca vrei sa ai posibilitatea sa anulezi un JWT atunci trebuie pe astea anulate sa le salvezi in BD si la fiecare request sa verifici daca e expirat si atunci ai pierdut avantajul ala ca nu se salveaza in db etc.

Mersi pentru info!
Scopul proiectului este pentru a invata in primul rand!

Cred ca pentru aplicatia mea voi folosi si e suficient JWT pentru autentificare, am si librarie dedicata si sa salvez token in HTTP-only cookie.

Intr-adevar, pentru date sensibile e mai bine de folosit HTTP-only cookie si nu local storage, local storage doar in cazul in care ai prea multa informatie si cookie te limiteaza, ceea ce la mine nu e cazul. JWT authentication: Best practices and when to use it - LogRocket Blog

Nu vreau sa fac asta, nu vad de ce sa ma complic in cazul meu.

2 Likes

Daca vrei sa inveti atunci incepe sa inveti studiind bunele practici in autentificare si nu invata gresit pentru ca daca pornesti asa exista riscul sa devina obisnuinta. Nu inteleg de ce nu vrei sa expire tokenul sau care e problema mai exact ?