5. JSON Web Tokens
5. JSON Web Tokens
Je kan de volgende zaken doen om verder te oefenen op het hoofdstuk rond testen.
Voorbereiding
Download de startbestanden.
Startbestanden
Voer de compose uit op je Docker container, je pnpm install, Prisma migration en seed script, Prisma generate, ... (zie README.md).
Deze oefeningen bouwen verder op het eindresultaat van de theorie. Het databankschema is hetzelfde. De hulpfuncties uit de theorie zijn al beschikbaar.
API route om een nieuwe account te registreren
Breid je API uit zodat een nieuwe user zich kan registreren. Je kan onder 'auth' een nieuw segment aanmaken voor deze route. Kies de juiste methode voor je request.
De request neemt een e-mail adres, username en passwoord binnen, en gebruikt de DAL methode createUser(...) om de gebruiker aan te maken.
Maak, net zoals in de login route, een JWT token aan en geef dat terug.
Vervang de session cookies met een JWT-token
Je combineert hier de logica van les 4 en les 5 om de session token te vervangen door een JWT token die in een secure HTTP cookie bewaard wordt. De logica moet toegepast worden en werken voor zowel de API routes als de UI van de website.
Gebruik asymmetrische keys voor je token.
In de startbestanden worden API routes beveiligd met een JWT token en de UI met een sessie (les 4 + 5). Je zal beiden moeten aanpassen om een JWT token met sessie te combineren.
Voor alle read acties gaan we niet meer naar de DB en gebruiken we enkel de JWT token. Voor andere acties controleren we de geldigheid van de token nog WEL in de databank
JWT uitbreiden
Breid de JWT token uit met de info van de sessie (inclusief user dus gebruik model SessionWithProfile).
Gebruik de vervaltermijn van de sessie als vervaltermijn voor de JWT token. Je zal de datum moeten omzetten naar een Unix Time. AI en/of het internet kunnen je daarmee helpen. Er bestaan uiteraard ook libraries die dit kunnen.
Utils uitbreiden
Pas de jwtUtils en sessionUtils aan om tot volgend resultaat te komen:
- Neem de nieuwe velden mee in de JWT token bij het aanmaken
- Bij het ophalen van de cookie (in getSessionFromCookie()) haal je de JWT token op. Deze moet je valideren. De token bevat alle info om de SessionWithProfile te maken.
- Zorg ervoor dat de methode een boolean binnen krijgt die bepaalt of je een DB check moet doen of niet. Zet die standaard op true om het refractor werk te beperken.
- Indien false geef je de SessionWithProfile terug uit de token.
- Indien true ga je zoeken of de sessie nog bestaat in de DB en nog geldig is. getSessionProfile(...) uit de dal controleert de datum al voor je.
- In beide gevallen moet de token valid zijn. Als de token niet valid is, ga je niet naar de DB.
- Zorg ervoor dat de methode een boolean binnen krijgt die bepaalt of je een DB check moet doen of niet. Zet die standaard op true om het refractor werk te beperken.
- Pas nu de methodes verder aan zodat de SessionProfile en de nieuwe boolean doorgegeven worden. Je zal ook enkele dal methodes moeten uitbreiden zodat deze een SessionProfile terug geven. Haal getSessionId() weg, deze wordt niet meer gebruikt.
Proxy functies
In de proxy functies ga je niet naar de database. Haal hier dus je sessie op uit de JWT token (die valid moet zijn) en ga NIET naar de databank.
De sessionManagementProxy zal je sessie verlengen indien nodig. Ook hier moet een JWT token teruggegeven worden in een cookie. Hier moet je uiteraard wel naar de DB om de sessie te updaten.
serverFunctions en serverActions
Als je de opgave goed gevolgd heb, dan zijn er enkel aanpassingen nodig in src/serverFunctions/users.ts. Deze komen zo dadelijk aan bod. De rest gebruikt rechtstreeks of onrechtstreeks getSessionProfileFromCookie(...), die standaard naar de DB gaat. De serverFunctions en serverActions bevatten geen reads.
API routes
Zorg dat je voor alle read acties enkel de JWT token controleert en daar de sessie uit haalt, en voor alle andere acties zowel de token controleert als de DB aanspreekt om de sessie op te halen (gebruik de juiste versie van getSessionProfileFromCookie(...)).
De login en registratie routes moeten uiteraard werken volledig zonder dat je eerst moet inloggen.
Aanpassen login/registratie
Zorg dat bij registeren en succesvol inloggen:
- Een sessie wordt aangemaakt
- Een JWT token wordt aangemaakt met de info van de sessie
- De JWT token wordt bewaard in een HTTP cookie
- In geval van de API de token wordt teruggegeven
Denk eraan dat dit (op het laatste item na) zowel vanuit de API als vanuit de UI moet gebeuren.
Hoe testen?
Gebruik Postman om de API routes te controleren, gebruik de UI van je applicatie om de serverFunctions en serverActions te controleren.
Zet een logging regel in src/dal/users/getSessionProfile(...) die duidelijk maakt dat de applicatie de DB heeft gevraagd om de sessie op te halen. Zo kan je in je logs makkelijk zien of hij nu wel of niet in de DB gaan zoeken is.