JWT jest to standard uwierzytelniania oparty o tokeny (RFC 7519) [1]. Zakłada on stworzenie specjalnego obiektu, który jest przesyłany do i z serwera. Protokół HTTPS jest bezstanowy, nie wymaga przechowywania informacji o użytkownikach na serwerze przez czas trwania żądań. Token JWT jest dodawany do danych w zapytaniach, mając na celu autoryzacje lub uwierzytelnienie na serwerze. Po stronie klienta są zapisywane w np. pamięci (w przypadku przeglądarki) localStorage.
Azure Active Directory jest to usługa umożliwiająca zarządzanie tożsamościami dla aplikacji internetowych i nie tylko. Korzysta ona z protokołu uwierzytelnienia OAuth 2.0. Można ją wykorzystać do uwierzytelnienia użytkowników na różnych platformach, np. w aplikacjach mobilnych lub internetowych. Po zalogowaniu użytkownika może zwrócić token JWT. Umożliwia aplikacji uwierzytelnienie użytkownika i dostęp do danych znajdujących się w aplikacji. [2] Jest to przykład użycia istniejącego dostawcy w celu zdobycia tokenu JWT. Jest to przydatne w przypadku pracy w aplikacjach dla firm korzystających z tego rozwiązania lub innych dostawców jak np. Google, Facebook.
Na rys. 1 przedstawiony jest diagram sekwencyjny, pokazujący tworzenie i użycie tokenu JWT. Użytkownik wypełnia formularz logowania w aplikacji, następnie są wysyłane dane do serwera. Serwer sprawdza, czy są podane prawidłowe dane do autentykacji, tworzy token, który jest wysyłany w odpowiedzi do użytkownika. Aplikacja klienta przechwytuje token, zapisuje w pamięci (np. Cookies lub LocalStorage). Przy kolejnych akcjach użytkownika token jest dołączany, aby uwierzytelnić operacje.
Token jest to obiekt, który został podzielony na trzy części:
- nagłówek (Header) – obiekt JSON, zakodowany formatem base64; zawiera informacje takie jak typ tokenu oraz nazwa algorytmu,
- zawartość (Payload) – obiekt JSON, również zakodowany formatem base64; zawarte są tutaj atrybuty użytkownika, np. identyfikator użytkownika, adres email, rola; zawartość ta nie powinna zawierać informacji poufnych, gdyż nie są one szyfrowane,
- podpis (Signature) – służy do weryfikacji po stronie serwera czy token zawiera poprawne informacje; jest to cyfrowa sygnatura generowana przez połączenie nagłówka i zawartości i zakodowana przez klucz prywatny znany tylko przez serwer.
Gdyby użytkownik atakujący system chciał zmienić zawartość tokenu, musiałby także wygenerować podpis ponownie – w tym momencie jest to już nie możliwe, gdyż klucz jest dostępny tylko na serwerze, niedostępny po stronie klienta.
Ważniejsze atrybuty, które warto znać i powinny być dołączona do zawartości:
- jti – unikalny identyfikator JWT,
- iss – zleceniodawca, który wydaje token,
- sub – identyfikuje podmiot, musi być unikalny,
- aud – identyfikuje odbiorców, dla których jest przeznaczony,
- exp – określa czas wygaśnięcia tokenu.
Stworzona została klasa AccountsService, która zawiera w sobie metody pozwalające na rejestrację, logowanie i odświeżenie tokenu użytkownika. Na rys. 2 pokazano metodę, która ilustruje, w jaki sposób użytkownik może być uwierzytelniany oraz jak tworzy się token JWT.
Dodanie konfiguracji JWT do projektu:
- modyfikacja klasy Startup – na rys. 3 jest kod, który zostaje dodany w celu konfiguracji autentykacji przez JWT dopisany do metody ConfigureServices; zostaje dołączona klasa reprezentująca użytkownika, schemat tokenu JWT oraz walidacja jego parametrów; wymagane jest także włączenie autentykacji w metodzie Configure pokazane na rys. 4,
- dodanie dodatkowych informacji do tworzenia tokenu JWT – na rys. 5 jest przykładowa konfiguracja pliku JSON projektu.
Klasa użytkownika dziedziczy po IdentityUser. Jest to implementacja paczki ASP .NET Core Identity. Zawiera podstawowe właściwości, takie jak identyfikator użytkownika, adres email oraz hasło. W przypadku korzystania Entity Framework Core należy dodać paczkę nuget Microsoft.AspNetCore.Identity.EntityFrameworkCore.
Dla uproszczenia przykładu ustawienia zostały zapisane w pliku appsettings.json. Docelowo należy jednak skorzystać z bardziej bezpiecznych rozwiązań. Można wykorzystać Azure Key Vault [3]dla przypadku wspomnianego na początku artykułu lub w usersecrets.json[4].
Metody w kontrolerach wymagające uwierzytelnienia muszą zostać opatrzone atrybutem Authorize. W przypadku tokenu JWT trzeba dodać jeszcze konfigurację schematu w atrybucie. Przykład takiego użycia atrybutu na całym kontrolerze jest pokazany na rys. 6.
Uwierzytelnianie za pomocą tokenów JWT zostało stworzone z myślą o aplikacjach mobilnych i SPA. Jest to proste w obsłudze rozwiązanie, wymagające jednak sporej konfiguracji. Elastyczność polityki autoryzacji w ASP .NET Core pozwala na integrację dodatkowych, zewnętrznych dostawców.
[1] https://tools.ietf.org/html/rfc7519
[2] https://docs.microsoft.com/pl-pl/azure/active-directory/develop/v1-protocols-oauth-code
[3] https://docs.microsoft.com/pl-pl/azure/key-vault/basic-concepts
[4] https://docs.microsoft.com/pl-pl/aspnet/core/security/app-secrets?view=aspnetcore-2.2&tabs=windows
Zostaw komentarz