Implementacja prostego klienta SDK OIDC
Logto oferuje różnorodne SDKi dla różnych platform. Oprócz naszych oficjalnych SDKi, zachęcamy programistów z społeczności do tworzenia własnych, przyjaznych dla użytkownika SDKi. Ten artykuł pomoże Ci zbudować podstawowe SDK klienta dla OIDC.
Wprowadzenie
Logto dostarcza naszym programistom i grupom biznesowym kompleksowe rozwiązanie do zarządzania tożsamością klienta i dostępem (CIAM). Oferujemy szeroką gamę gotowych do użycia SDKi dla różnych platform i frameworków aplikacji. W połączeniu z naszą usługą chmurową Logto, możesz bez problemów ustalić wysoce bezpieczny przepływ uwierzytelniania użytkownika dla swojej aplikacji w kilka minut. Jako firma, która powstała z społeczności programistów, Logto ceni i docenia zaangażowanie naszej społeczności. Oprócz oficjalnie opracowanych SDKi Logto, nieustannie zachęcamy i serdecznie zapraszamy programistów z społeczności do przyczyniania się swoją wiedzą specjalistyczną poprzez tworzenie bardziej zróżnicowanych i przyjaznych dla użytkownika SDKi, spełniających unikalne potrzeby różnych platform i frameworków. W tym artykule pokrótce pokażemy, jak krok po kroku zaimplementować standardowe SDK autoryzacyjne OIDC.
Kontekst
Przepływ OpenID Connect (OIDC) to protokół uwierzytelniania, który opiera się na frameworku OAuth 2.0 aby zapewnić weryfikację tożsamości i funkcje jednokrotnego logowania. Umożliwia użytkownikom uwierzytelnienie się w aplikacji i uzyskanie autoryzacji do dalszego dostępu do jakichkolwiek prywatnych zasobów w bezpieczny sposób. Więcej szczegółów można znaleźć w specyfikacji OIDC.
Workflow
Standardowy przepływ kodu autoryzacji obejmuje następujące kroki:
Przepływ uwierzytelniania
- Użytkownik inicjuje żądanie logowania: Anonimowy użytkownik przychodzi do Twojej aplikacji z publicznego wejścia. Próbuje się uwierzytelniać i możliwe, że dalej żąda dostępu do chronionego zasobu na aplikacji lub usłudze stron trzecich.
- Uwierzytelnianie użytkownika: Aplikacja klienta generuje URI uwierzytelniania i wysyła żądanie do serwera autoryzacji, który przekierowuje użytkownika do swojej strony logowania. Użytkownik korzysta ze strony logowania za pomocą szerokiego zakresu metod logowania i jest uwierzytelniany przez serwer autoryzacji.
- Obsługa powrotu po logowaniu: Po udanej uwierzytelnieniu, użytkownik zostanie przekierowany z powrotem do Twojej aplikacji z przyznanym
authorization_code
. Tenauthorization_code
zawiera wszystkie istotne uprawnienia związane ze statusem uwierzytelnienia i żądanymi danymi autoryzacji. - Wymiana tokenów: Żądanie wymiany tokenów za pomocą
authorization_code
wydobytego z powyższego adresu przekierowania. W rezultacie:id_token
: Cyfrowo podpisany JWT, który zawiera informacje o tożsamości uwierzytelnionego użytkownika.access_token
: Niewystępującyaccess_token
, który może być używany do dostępu do punktu końcowego podstawowych informacji o użytkowniku.refresh_token
: Token poświadczeń pozwalający użytkownikowi na ciągłą wymianęaccess_token
.
Przepływ autoryzacji
- Dostęp do informacji o użytkowniku: Aby uzyskać więcej informacji o użytkowniku, aplikacja może wysłać dodatkowe żądania do punktu końcowego UserInfo, wykorzystując niewystępujący
access_token
uzyskany z początkowego przepływu wymiany tokenów. Umożliwia to pobranie dodatkowych szczegółów o użytkowniku, takich jak jego adres e-mail czy zdjęcie profilowe. - Udzielanie dostępu do chronionego zasobu: Jeżeli jest to konieczne, aplikacja może wysyłać dodatkowe żądania do punktu końcowego wymiany tokenów, wykorzystując
refresh_token
w połączeniu z parametramiresource
iscope
, aby uzyskać dedykowanyaccess_token
umożliwiający użytkownikowi dostęp do docelowego zasobu. Proces ten skutkuje wydaniemaccess_token
w formacie JWT, zawierającego wszystkie niezbędne informacje do uzyskania dostępu do chronionego zasobu.
Implementacja
Będziemy podążać za kilkoma strategiami projektowania w naszym SDK JavaScript @logto/client, aby pokazać proces implementacji prostego SDK dla własnej aplikacji klienta. Pamiętaj, że struktura kodu może różnić się w zależności od używanego frameworka klienta. Możesz swobodnie wybrać dowolne z oficjalnych SDKi Logto jako przykład dla swojego własnego projektu SDK.
Podgląd
Konstruktor
Konstruktor powinien przyjąć logtoConfig jako swój parametr wejściowy. Dostarcza on wszystkie niezbędne konfiguracje, które będziesz potrzebował do nawiązania połączenia uwierzytelniania za pomocą tego SDK.
Zależnie od platformy lub frameworka, którego używasz do SDK, możesz przekazać do konstruktora trwałą instancję lokalnego magazynu. Ta instancja magazynu będzie służyć do przechowywania wszystkich tokenów i sekretów związanych z autoryzacją.
Inicjacja uwierzytelnienia użytkownika
Zanim wygeneruje się URL żądania uwierzytelniania, konieczne jest wykonanie kilku kroków przygotowawczych, aby zapewnić bezpieczny proces.
Pobieranie konfiguracji OIDC z serwera autoryzacji
Zdefiniuj prywatną metodę getOidcConfigs
, aby pobrać konfiguracje OIDC z punktu końcowego odkrycia serwera autoryzacji. Odpowiedź konfiguracji OIDC zawiera wszystkie informacje o metadanych, których klient może używać do interakcji z serwerem autoryzacji, w tym lokalizacje punktów końcowych i możliwości serwera. (Więcej szczegółów można znaleźć w OAuth OAuth Authorization Server Metadata Specs).
Generator PKCE
Prywatność klucza dla wymiany kodów (PKCE) przepływ walidacji jest niezbędny dla wszystkich publicznych przepływów wymiany kodów autoryzacji klienta. Zmniejsza ono ryzyko ataku przechwycenia kodu autoryzacji. Dlatego code_challenge
i code_verifier
są wymagane dla wszystkich żądań autoryzacji aplikacji klienckich (np. natywnych i SPA).
Metody implementacji mogą się różnić w zależności od języków i frameworków, których używasz. Proszę odnieść się do specyfikacji code_challenge i code_verifier dla szczegółowych definicji.
Generowanie parametru stanu
W przepływie autoryzacji, parametr stanu to losowo generowana wartość, która jest uwzględniana w żądaniu autoryzacji wysyłanym przez klienta. Działa on jako środek zabezpieczający przed atakami typu cross-site request forgery (CSRF).
Przechowywanie tymczasowych informacji o sesji
Jest kilka parametrów, które muszą być zachowane w magazynie do walidacji po tym, jak użytkownik zostanie uwierzytelniony i przekierowany z powrotem na stronę klienta. Zaimplementujemy metodę ustawiania tych tymczasowych parametrów w magazynie.
Zaloguj się
Podsumujmy wszystko, co do tej pory zimplementowano, i zdefiniujmy metodę generującą URL logowania użytkownika i przekierowującą użytkownika do serwera autoryzacji, aby się uwierzytelnial.
Obsługa powrotu po logowaniu użytkownika
W poprzednim rozdziale utworzyliśmy metodę logowania, która generuje URL do uwierzytelniania użytkownika. Ten URL zawiera wszystkie wymagane parametry potrzebne do zainicjowania przepływu uwierzytelniania z aplikacji klienta. Metoda przekierowuje użytkownika na stronę logowania serwera autoryzacji do uwierzytelniania. Po udanym logowaniu, użytkownik końcowy zostanie przekierowany z powrotem do podanej wcześniej lokalizacji redirect_uri. Wszystkie niezbędne parametry będą zawarte w redirect_uri, aby zakończyć następujące przepływy wymiany tokenów.
Wyodrębnianie i weryfikacja adresu URL powrotu
Etapa walidacji jest niezwykle ważna, aby zapobiec jakimkolwiek formom sfałszowanych ataków na autoryzację zwrotną. Adres URL callback MUST musi być dokładnie sprawdzony przed wysłaniem dalszego żądania wymiany kodu do serwera autoryzacji. Na początek trzeba odzyskać dane signInSession, które przechowaliśmy w magazynie aplikacji.
Następnie należy zweryfikować parametry adresu URL zwrotnego, zanim wyśle się żądanie wymiany tokena.
- Użyć wcześniej przechowywanego
redirectUri
, aby sprawdzić, czycallbackUri
jest taka sama, jak ta, którą wysłaliśmy do serwera autoryzacji. - Użyć wcześniej przechowywanego
state
, aby sprawdzić, czy zwrócony stan jest taki sam, jak ten, który wysłaliśmy do serwera autoryzacji. - Sprawdzić, czy serwer autoryzacji zwrócił jakiś błąd
- Sprawdzić, czy istnieje zwrócony
authorization_code
Wyślij żądanie wymiany kodu
Jako ostatni etap przepływu uwierzytelniania użytkownika, użyjemy zwróconego authorization_code
, aby wysłać żądanie wymiany tokenów i uzyskać wymagane tokeny autoryzacyjne. Więcej szczegółów na temat definicji parametrów żądania można znaleźć w specyfikacji wymiany tokenów.
- code:
authorization_code
, który otrzymaliśmy z URI powrotu - clientId: identyfikator aplikacji
- redirectUri: Ta sama wartość jest używana podczas generowania adresu URL logowania dla użytkownika.
- codeVerifier: PKCE code verifier. Podobnie jak w przypadku redirectUri, serwer autoryzacji porówna tę wartość z tym, co wcześniej wysłaliśmy, zapewniając walidację nadchodzącego żądania wymiany tokena.
Obsługa powrotu po logowaniu
Podsumowując wszystko, co mamy. Zbudujmy za pomocą handleSignInCallback:
W rezultacie żądanie wymiany tokenów zwróci następujące tokeny:
id_token
: OIDC idToken, JSON Web Token (JWT), który zawiera informacje o tożsamości uwierzytelnionego użytkownika. id_token może być również używany jako pojedyncze źródło prawdy (SSOT) statusu uwierzytelnienia użytkownika.access_token
: Domyślny kod autoryzacji zwracany przez serwer autoryzacji. Może być używany do wywołania punktu końcowego informacji o użytkowniku i pobrania informacji o uwierzytelnionym użytkowniku.refresh_token
: (jeżeli zakres offline_access jest obecny w żądaniu autoryzacji): Ten refresh token pozwala aplikacji klienta na uzyskanie nowego access_token, bez potrzeby ponownego uwierzytelniania użytkownika, co daje długoterminowy dostęp do zasobów.expires_in
: Czas trwania, w sekundach, przez który access_token jest ważny, zanim wygaśnie.
Weryfikacja id_token
Weryfikacja i ekstrakcja roszczeń z id_token
to kluczowy krok w procesie uwierzytelniania, aby zapewnić autentyczność i integralność tokena. Oto kluczowe kroki związane z weryfikacją idToken
.
- Weryfikacja podpisu:
id_token
jest cyfrowo podpisany przez serwer autoryzacji za pomocą jego prywatnego klucza. Aplikacja klienta musi zweryfikować podpis za pomocą publicznego klucza serwera autoryzacji. Zapewnia to, że token nie został naruszony i został faktycznie wydany przez prawowitego serwera autoryzacji. - Weryfikacja wystawcy**:** Sprawdzić, czy roszczenie "iss" (issuer) w
id_token
odpowiada oczekiwanej wartości, wskazując, że token został wydany przez poprawny serwer autoryzacji. - Weryfikacja odbiorcy: Upewnić się, że roszczenie "aud" (audience) w
id_token
odpowiada identyfikatorowi klienta aplikacji klienta, zapewniając, że token jest przeznaczony dla klienta - Sprawdzenie wygaśnięcia: Zweryfikować, czy roszczenie "iat" (wystawione o) w
id_token
nie przeszło teraźniejszego czasu, zapewniając, że token jest nadal ważny. Ponieważ są koszty transakcji sieciowych, musimy ustawić tolerancję czasu wydania podczas walidacji żądanej roszczenia tokena iat.
Zwrócony id_token to standardowy JSON Web Token (JWT). W zależności od używanego frameworku, znajdziesz różne wygodne wtyczki do walidacji tokenu JWT, które pomogą w dekodowaniu i walidacji tokenu. W tym przykładzie, będziemy wykorzystywać jose w naszym SDK JavaScript, aby ułatwić walidację i dekodowanie tokenu.
Pobierz informacje o użytkowniku
Po udanym uwierzytelnieniu użytkownika, podstawowe informacje o użytkowniku mogą być pobrane z OIDC id_token
wydanego przez serwer autoryzacji. Jednak ze względu na kwestie wydajności, zawartość tokena JWT jest ograniczona. Aby uzyskać bardziej szczegółowe informacje o profilu użytkownika, serwery autoryzacji zgodne z OIDC oferują gotowy do użycia punkt końcowy informacji o użytkowniku. Ten punkt końcowy pozwala na pobranie dodatkowych danych profilu użytkownika, poprzez żądanie konkretnych zakresów profilu użytkownika.
Podczas wywoływania punktu końcowego wymiany tokenów bez wskazywania konkretnego zasobu API, serwer autoryzacji domyślnie wyda access_token
typu opaque. Ten access_token
może być używany tylko do dostępu do punktu końcowego informacji o użytkowniku, co pozwala na pobranie podstawowych danych profilu użytkownika.
Pobierz token dostępu do autoryzacji chronionych zasobów
W większości przypadków aplikacja kliencka nie tylko wymaga uwierzytelniania użytkownika, ale także wymaga autoryzacji użytkownika do dostępu do pewnych chronionych zasobów lub punktów końcowych API. Tutaj, użyjemy refresh_token
uzyskanego podczas logowania, aby uzyskać access_token(s)
specjalnie przyznane do zarządzania konkretnymi zasobami. To pozwala nam na dostęp do tych chronionych API.
Podsumowanie
Przedstawiliśmy podstawowe implementacje metod dla procesu autentykacji i autoryzacji użytkowników w aplikacjach po stronie klienta. W zależności od konkretnego scenariusza, możesz organizować i optymalizować logikę SDK odpowiednio. Proszę zauważyć, że mogą wystąpić różnice ze względu na różne platformy i ramy.
Aby uzyskać dodatkowe informacje, przejrzyj pakiety SDK oferowane przez Logto. Zachęcamy więcej użytkowników do dołączenia do rozwoju i zaangażowania się w dyskusje z nami. Twoje opinie i wkład są dla nas bardzo cenne, gdy kontynuujemy ulepszanie i rozwijanie możliwości SDK.
Dodatek
Zarezerwowane zakresy
Zarezerwowane zakresy Logto, które musisz podać podczas początkowego żądania autoryzacji. Są to zakresy podstawowe, zarezerwowane przez OIDC lub Logto, aby zrealizować udany przepływ autoryzacji.
Nazwa zakresu | Opis |
---|---|
openid | Wymagane do przyznania id_token po udanej autoryzacji. |
offline-access | Wymagane do przyznania refresh_token , który pozwala aplikacji klienta na wymianę i odnowienie access_token poza ekranem. |
profile | Wymagane do uzyskania dostępu do podstawowych informacji o użytkowniku |
Konfiguracja Logto
Nazwa właściwości | Typ | Wymagane | Opis | Wartość domyślna |
---|---|---|---|---|
appId | string | true | Unikalny identyfikator aplikacji. Generowany przez serwer autoryzacji, aby zidentyfikować aplikację klienta. | |
appSecret | string | Sekret aplikacji jest używany, wraz z identyfikatorem aplikacji, do weryfikacji tożsamości osoby żądającej. Jest wymagany dla poufnych klientów, takich jak aplikacje internetowe Go lub Next.js, i opcjonalny dla publicznych klientów, takich jak aplikacje natywne lub jednostronicowe aplikacje (SPA) | ||
endpoint | string | true | Twój punkt końcowy głównego serwera autoryzacji. Ta właściwość będzie szeroko używana do generowania żądań autoryzacji.endpoint. | |
scopes | lista stringów | Wskazuje na wszystkie niezbędne zakresy zasobów, które użytkownik może potrzebować, aby zostały mu przyznane, aby uzyskać dostęp do jakichkolwiek chronionych zasobów. | [reservedScopes] | |
resources | lista stringów | Wszystkie wskaźniki chronionych zasobów, o dostęp do których użytkownik może wystąpić |