JWT (JSON Web Token) automatinis atnaujinimas

Norėčiau įdiegti JWT pagrįstą autentifikavimą mūsų naujame REST API. Tačiau nuo galiojimo pabaigos datos yra nustatyta, ar jis gali būti automatiškai atnaujinamas? Aš nenoriu, kad vartotojai kas X minučių registruotųsi, jei per šį laikotarpį aktyviai naudosis programa. Tai būtų didžiulis UX avarijos atvejis.

Tačiau atnaujinimas sukuria naują raktą (ir senas galioja iki jo galiojimo pabaigos datos). Ir po to, kai kiekvienas prašymas generuoja naują ženklą, man atrodo kvailas. Skamba kaip saugumo problema, kai tuo pačiu metu naudojamas daugiau nei vienas simbolis. Žinoma, galiu panaikinti senąjį naudodamas juodąjį sąrašą, bet turėsiu saugoti žetonų. Ir vienas iš JWT privalumų nėra saugojimas.

Radau, kaip tai išsprendė Auth0. Jie naudoja ne tik JWT simbolį, bet ir atnaujinimo raktą: https://docs.auth0.com/refresh-token

Bet vėl, norėdami tai įgyvendinti (be Auth0), turėsiu saugoti atnaujinimo žetonus ir juos palikti. Kokia yra reali nauda? Kodėl neturite tik vieno žetono (o ne JWT) ir išsaugote galiojimo datą serveryje?

Ar yra kitų galimybių? Ar JWT netinka šiam scenarijui?

403
04 нояб. paprašė maryo lapkričio 4 d. 2014-11-04 18:41 '14 at 18:41 2014-11-04 18:41
@ 10 atsakymų

Dirbu Auth0, ir dalyvavau rengiant atnaujinimo žetonų funkciją.

Viskas priklauso nuo taikymo tipo, ir čia yra mūsų rekomenduojamas metodas.

Žiniatinklio programos

Geras šablonas yra atnaujinti raktą prieš pasibaigiant jo galiojimui.

Nustatykite žymeklio galiojimo laikotarpį vieną savaitę ir atnaujinkite simbolį kiekvieną kartą, kai vartotojas atidaro žiniatinklio programą ir kas valandą. Jei vartotojas daugiau nei savaitę neatveria programos, jie turės vėl prisijungti, o tai yra priimtina UX žiniatinklio programa.

Jei norite atnaujinti raktą, jūsų API reikalauja naujo galinio taško, kuris gauna galiojantį, bet nebegaliojantį JWT, ir grąžina tą patį pasirašytą JWT su nauju galiojimo laiko lauku. Tada žiniatinklio programa išsaugos tokenį kažkur.

Mobiliosios / vietinės programos

Dauguma įterptųjų programų registruojamos vieną kartą ir tik vieną kartą.

Idėja yra ta, kad atnaujinimo raktas niekada nebegalioja ir visada gali būti pakeistas į galiojantį JWT.

Problema, susijusi su simboliu, kuris niekada nesibaigia, yra tai, kad ji niekada nereiškia. Ką darysite, jei prarasite savo telefoną? Taigi vartotojas turi kažkaip identifikuoti vartotoją, o programa turi suteikti galimybę atsisakyti prieigos. Mes nusprendėme naudoti, pavyzdžiui, įrenginio pavadinimą. „maryo iPad“. Tada vartotojas gali eiti į programą ir atšaukti prieigą prie „maryo iPad“.

Kitas būdas yra atšaukti atnaujinimo raktą tam tikriems įvykiams. Įdomus įvykis yra slaptažodžio keitimas.

Mes tikime, kad JWT netinka šiems naudojimo atvejams, todėl mes naudojame atsitiktinai sugeneruotą eilutę ir laikome jį mūsų pusėje.

465
10 нояб. Atsakymą pateikė José F. Romaniello . 2014-11-10 02:45 '14, 02:45 am 2014-11-10 02:45

Tuo atveju, kai jūs pats tvarkote auth (pvz., Nenaudojate paslaugų teikėjo, pvz., Auth0), gali būti:

  • Išleiskite JWT žymą su santykinai trumpu, pavyzdžiui, 15 minučių.
  • Paraiška tikrina žetono galiojimo datą prieš bet kokį sandorį, kuriam reikalingas ženklas (ženklas turi galiojimo datą). Jei žyma baigėsi, ji pirmiausia prašo API atnaujinti raktą (tai daroma skaidriai UX).
  • API gauna simbolių atnaujinimo užklausą, bet pirmiausia patikrina naudotojo duomenų bazę, kad nustatytų, ar šiam naudotojo profiliui nustatyta „reagento“ vėliava (raktas gali turėti vartotojo ID). Jei vėliava yra, ženklas atnaujinamas, priešingu atveju išduodamas naujas raktas.
  • Pakartokite.
border=0

„Reauth“ vėliava duomenų bazėje bus nustatyta, jei, pavyzdžiui, naudotojas iš naujo nustatys savo slaptažodį. Vėliau, kai vartotojas bus prisijungęs, vėliavėlė ištrinama.

Be to, tarkime, kad turite politiką, pagal kurią vartotojas turi prisijungti bent kartą per 72 valandas. Tokiu atveju API ženklo atnaujinimo logika taip pat patikrins vartotojo paskutinę prisijungimo datą į vartotojo duomenų bazę ir išjungs / įgalins tokį atnaujinimą šiuo pagrindu.

58
20 февр. Atsakymą IanB pateikė vasario 20 d. 2015-02-20 05:05 '15, 5:05 2015-02-20 05:05

Alternatyvus sprendimas atšaukti JWT be papildomos saugomos atminties backend yra įdiegti naują stulpelį jwt_version naudotojų lentelėje. Jei vartotojas nori atsijungti arba atleisti esamus žetonus, jie tiesiog padidina jwt_version lauką.

Kuriant naują JWT, koduokite jwt_version į JWT naudingąją apkrovą, nebūtinai iš anksto padidinant vertę, jei naujas JWT turėtų pakeisti visus kitus.

Tikrinant JWT, laukas jwt_version lyginamas su user_id , o autorizacija teikiama tik tada, kai ji atitinka.

11
31 мая '17 в 12:19 2017-05-31 12:19 atsakymą pateikė Ollie Bennett gegužės 31 d., 17 val. 12:19

Nusileidžiau perkeliant mūsų programas į HTML5 naudodamas „RESTful apis“. Sprendimas, kurį pateikiau, buvo:

  • Sėkmingai prisijungus, klientas gauna simbolį, kurio sesijos laikas yra 30 minučių (arba nepriklausomai nuo įprastos sesijos laiko serverio pusėje).
  • Kliento pusės laikmatis sukurtas tam, kad skambintų paslaugai, kad jis atnaujintų žetonų galiojimo laiką. Naujasis raktas pakeis esamus būsimus iššūkius.

Kaip matote, tai sumažina atnaujinimo žetonų užklausų dažnumą. Jei vartotojas uždaro naršyklę / taikomąją programą prieš pradedant žetonų skambutį, ankstesnis ženklas baigsis laiku ir naudotojas turės vėl prisijungti.

Sudėtingesnė strategija gali būti įgyvendinta, kad būtų galima naudotojo neveiklumą (pavyzdžiui, nepaisyti atviro naršyklės skirtuko). Tokiu atveju pakartotinis žetonų pakvietimas turi apimti numatomą galiojimo laiką, kuris neturėtų viršyti nurodyto seanso laiko. Programai reikės vadovautis naujausia vartotojo sąveika.

Man nepatinka idėja nustatyti ilgą laiką, todėl šis požiūris gali veikti prastai su vietinėmis programomis, kurioms reikia retesnio autentiškumo.

11
21 мая '15 в 6:00 2015-05-21 06:00 Atsakymą pateikia „ coolersport“ gegužės 21 d., 15 val. 6:00 2015-05-21 06:00

Geras klausimas ir pats klausimas - daug informacijos.

Straipsnyje „ Atnaujinti žetonų: kada juos naudoti ir kaip jie sąveikauja su JWT“ pateikiama gera idėja šiam scenarijui. Kai kurie punktai: -

  • Atnaujinimo žetonai turi informaciją, reikalingą norint gauti naują prieigos raktą.
  • Atnaujinimo žetonai taip pat gali baigtis, tačiau jie yra gana ilgaamžiai.
  • Atnaujinimo žymekliams paprastai taikomi griežti saugojimo reikalavimai, kad jie nebūtų nutekėję.
  • Jie taip pat gali būti įtraukti į autorizacijos serverio juodąjį sąrašą.

Taip pat žiūrėkite į auth0 / angular-jwt angularjs

Žiniatinklio API. Perskaitykite „ Enable OAuth Update Tokens“ „AngularJS“ programoje naudojant „ASP.NET Web API 2“ ir „Owin“

8
26 авг. Lijo atsakymas, pateiktas rugpjūčio 26 d 2016-08-26 20:50 '16 at 8:50 pm 2016-08-26 20:50

jwt-autorefresh

Jei naudojate mazgo (React / Redux / Universal JS), galite įdiegti „ npm i -S jwt-autorefresh .

Ši biblioteka planuoja atnaujinti naudotojo JWT žetonus, apskaičiuotus prieš kelias sekundes, kol baigsis prieigos raktas (pagal „exp“ koduotą reikalavimą). Ji turi platų testų rinkinį ir išbando nemažai sąlygų, kad bet kokia keista veikla būtų pridedama aprašomoji informacija apie neteisingus konfigūracijas iš jūsų aplinkos.

Visiškas pavyzdžio įgyvendinimas

6
27 мая '16 в 10:43 2016-05-27 10:43 atsakė cchamberlainui gegužės 27 d. 16, 10:43 2016-05-27 10:43

Tai iš tikrųjų įgyvendinau PHP naudodamas „Guzzle“ klientą, kad sukurtumėte kliento biblioteką „api“, tačiau ši koncepcija turėtų veikti kitose platformose.

Iš esmės aš išduodu du ženklus - trumpą (5 minutes) vieną ir ilgą, kuris baigiasi per savaitę. Tarpinė programinė įranga naudojama kliento bibliotekoje, kad būtų bandoma atnaujinti trumpą raktą, jei jis gauna 401 atsakymą į tam tikrą užklausą. Tada jis vėl išbandys pradinį prašymą ir, jei jis galės atnaujinti, gaus teisingą atsakymą, skaidriai vartotojui. Jei jis nepavyksta, jis tiesiog išsiųs vartotojui 401.

Jei sutrumpintas simbolis pasibaigė, bet vis dar yra autentiškas, o ilgas ženklas yra galiojantis ir autentiškas, jis atnaujins trumpą žymą naudodamasis specialiu paslaugos galiniu tašku, kuris tikrina ilgą žymą (tai yra vienintelis dalykas, kurį galite naudoti). Tada jis naudos trumpą žymą, kad gautų naują ilgą žetoną, tokiu būdu padidindamas jį dar vieną savaitę kiekvieną kartą, kai jis atnaujina trumpąjį simbolį.

Šis metodas taip pat leidžia mums atšaukti prieigą ne ilgiau kaip 5 minutes, o tai yra priimtina mūsų naudojimui, nereikalaujant juodojo žetonų sąrašo.

Vėlyvas redagavimas: perskaičius šiuos mėnesius po to, kai mano galva buvo šviežia, turiu atkreipti dėmesį į tai, kad galite atšaukti prieigą atnaujinant trumpą simbolį, nes jis leidžia brangiau skambinti (pavyzdžiui, skambinti į duomenų bazę, kad pamatytumėte, ar vartotojas buvo užblokuotas) nemokant už tai kiekvieną kartą, kai buvo prašoma paslaugos.

6
14 дек. Atsakymą pateikė BytePorter 14 d. 2016-12-14 00:00 '16 at 0:00 2016-12-14 00:00

Kaip apie šį požiūrį:

  • Kiekvienam kliento prašymui serveris lygina galiojimo laiko simbolį su (dabartiniu laiku - lastAccessTime)
  • Jei expirationTime <(dabartinis laikas yra lastAccessedTime) , jis pakeičia paskutinį paskutinį prieigą prie dabartinio laiko.
  • Jei naršyklė neaktyvi ilgiau nei galiojimo laiko laikotarpis arba jei naršyklės >expirationTime> (dabartinis laikas yra lastAccessedTime) , tuomet serveris gali baigtis simboliu ir paprašyti vartotojo prisijungti dar kartą.

Tokiu atveju nereikia papildomo parametro, kad atnaujintume žymą. Dėkojame visiems pašarams.

2
11 мая '16 в 0:31 2016-05-11 00:31 atsakymas pateikiamas sjaiswal gegužės 11 d., 16 val. 0:31 2016-05-11 00:31

Aš išsprendžiau šią problemą, pridėdamas žymenų duomenų kintamąjį:

 softexp - I set this to 5 mins (300 seconds) 

expiresIn parinktį norimu laiku, kol vartotojas yra priverstas vėl prisijungti. Kasykla yra 30 minučių. Tai turi būti didesnė už softexp .

Kai kliento pusės programa siunčia užklausą į serverio API (kai reikalingas simbolis, pvz., Kliento sąrašo puslapis), serveris patikrina, ar tokie expiresIn lieka ar ne, remiantis pradine jo galiojimo verte ( expiresIn ). Jei tai negalioja, serveris atsakys pvz., ši klaida apibrėžta. INVALID_TOKEN .

Jei expiredIn vis dar galioja, atsižvelgiant į galiojimo pabaigos vertę, tačiau ji jau viršijo softexp reikšmę, serveris, pavyzdžiui, atsakys į atskirą būseną. EXPIRED_TOKEN :

 (Math.floor(Date.now() / 1000) > decoded.softexp) 

Kliento pusėje, jei jis gavo „ EXPIRED_TOKEN atsakymą, jis turėtų automatiškai atnaujinti raktą, EXPIRED_TOKEN serveriui atnaujinimo užklausą. Jis yra skaidrus vartotojui ir automatiškai rūpinasi kliento programa.

Atnaujinimo metodas serveryje turėtų patikrinti, ar raktas galioja:

 jwt.verify(token, secret, (err, decoded) => {}) 

Serveris atsisakys atnaujinti žetonų, jei jis nebaigė pirmiau minėto metodo.

2
05 авг. atsakė James A 05 rug. 2017-08-05 00:29 '17 - 0:29 2017-08-05 00:29

Toliau pateikiami nurodymai, kaip atšaukti JWT prieigos raktą:

1) Kai prisijungiate, atsiųskite klientui 2 raktus (prieigos raktą, atnaujinimo raktą).
2) Prieigos raktas turės mažesnį galiojimo laiką, o naujinimas bus ilgas.
3) Klientas (Priekinis galas) išsaugos atnaujinimo raktą savo vietinėje atmintyje ir prieigos raktą slapukuose.
4) Klientas naudos prieigos raktą, kad paskambintų API. Bet kai jis pasibaigia, iš vietos saugyklos pasirinkite atnaujinimo raktą ir skambinkite api autentifikavimo serveriu, kad gautumėte naują žymą.
5) Jūsų autentifikavimo serveryje bus atidaryta API, kuri priims atnaujinimo raktą, patikrins jo galiojimą ir grąžins naują prieigos raktą.
6) Pasibaigus atnaujinimo raktui, naudotojas atsijungs.

Praneškite, jei jums reikia daugiau informacijos, taip pat galiu pasidalinti kodu („Java + Spring“ įkrovos programa).

0
26 янв. Bhupinder Singh atsakė į 26 Jan 2019-01-26 15:26 '19, 15:26 pm 2019-01-26 15:26

Kiti klausimai apie žymės arba Užduoti klausimą