• oidc
  • oauth
  • uwierzytelnianie
  • autoryzacja
  • jwt

Kompletny przewodnik po integracji serwera OIDC do twojego projektu

Naucz się najlepszych praktyk integracji serwera OIDC (OpenID Connect) do twojego projektu i zrozum, jak komponenty ze sobą współdziałają na scenie.

Gao
Gao
Founder

Możesz napotkać sytuację, w której potrzebujesz scentralizowanego systemu uwierzytelniania i autoryzacji, zwanego zarządzaniem dostępem do tożsamości (IAM) lub dostawcą tożsamości (IdP). Czasami ludzie dodają słowo, aby określić branżę, takie jak IAM dla Klientów i IAM dla Pracowników.

Odłóżmy te fantazyjne nazwy na chwilę. Potrzeba IAM może wynikać z rozbudowy twojej aplikacji lub planujesz od początku delegować ciężką pracę dostawcy. Niemniej jednak dochodzisz do punktu, w którym system tożsamości będzie musiał zostać wprowadzony do twojego projektu.

Biorąc pod uwagę popularność OAuth 2.0, OpenID Connect (OIDC) jest naturalnym wyborem dla wielu deweloperów. Ponieważ OIDC jest warstwą uwierzytelniania zbudowaną na OAuth 2.0, możesz poczuć się znajomo, gdy zaczniesz pracować z OIDC. Zacznijmy!

Co to jest serwer OIDC i dlaczego powinienem go zintegrować?

Serwer OIDC, lub dostawca tożsamości, to scentralizowany system, który zarządza uwierzytelnianiem i autoryzacją użytkowników. Jak omówiliśmy w Dlaczego potrzebujesz scentralizowanego systemu tożsamości dla wieloaplikacyjnego biznesu, scentralizowany system tożsamości ma wiele korzyści.

Załóżmy, że twój projekt zaczyna się od prostej aplikacji internetowej, i ma wbudowane uwierzytelnianie:

Gdy twój projekt rośnie, musisz wprowadzić wersję mobilną:

Będzie to złe doświadczenie dla użytkowników, jeśli będą musieli tworzyć konto dla każdej aplikacji. Ponieważ zaczęliście od aplikacji internetowej, pozwalasz aplikacji mobilnej komunikować się z aplikacją internetową w celu uwierzytelnienia:

Teraz wprowadzana jest nowa usługa API. Ponieważ jest to usługa dla płacących użytkowników, musisz upewnić się, że użytkownik jest uwierzytelniony i posiada autoryzację do dostępu do usługi. Aby to osiągnąć, możesz przekierować usługę przez aplikację internetową:

Albo, użyj jakiejś techniki tokenowej do uwierzytelnienia użytkownika i zweryfikuj token, rozmawiając z aplikacją webową w usłudze. Dlatego aplikacja mobilna może korzystać z usługi bezpośrednio:

Rzeczy stają się nieuporządkowane. Dlatego decydujesz się rozdzielić logikę uwierzytelniania i autoryzacji do oddzielnej usługi:

Proces refaktoryzacji może być bolesny. Możesz zauważyć, że jego złożoność wzrośnie wykładniczo, gdy dodasz więcej aplikacji i usług do projektu. Co gorsza, możesz potrzebować utrzymywać wiele metod uwierzytelniania, takie jak logowanie bez hasła, logowanie społecznościowe, SAML, itp.

Dlatego lepiej jest wprowadzić dostawcę tożsamości na początku, kiedy masz plan, aby rozbudować swój projekt.

Najlepsze praktyki dla integracji serwera OIDC

Znajdź dostawcę OIDC

Na rynku dostępnych jest wielu dostawców OIDC. Możesz wybrać jednego w oparciu o swoje wymagania i preferencje. Tak długo, jak dostawca jest zgodny z OIDC, będzie pełnił tę samą rolę w twoim projekcie.

Co oznaczają „subject”, „client” i „audience” w OIDC?

Aby uprościć koncept, możemy myśleć o subject jako podmiocie, który żąda dostępu do audience za pośrednictwem client.

Przyjrzyjmy się niektórym typowym scenariuszom:

1. Użytkownik klika przycisk logowania w aplikacji internetowej

W tradycyjnej aplikacji z renderowaniem po stronie serwera frontend i backend są połączone. Załóżmy, że aplikacja webowa obsługuje zarówno frontend, jak i backend:

  • Podmiot: Użytkownik
  • Odbiorca: Serwer OIDC
  • Klient: Aplikacja internetowa

Może wyglądać to przeciwnie do intuicji, że odbiorcą jest serwer OIDC. W rzeczywistości jest to klucz do realizacji doświadczenia SSO (Single Sign-On) dla użytkowników końcowych. Zobaczmy uproszczony diagram sekwencji dla przepływu kodu autoryzacji:

kod jest jednorazowym kodem, który można wymienić na różne tokeny, takie jak token dostępu, ID token i refresh token. Nie szkodzi, jeśli nie rozumiesz wszystkich tych tokenów w tej chwili. Postępując dalej, zdobędziesz lepsze zrozumienie ich.

W powyższym przypadku, użytkownik nie musi logować się ponownie, gdy przełącza się do innej aplikacji, ponieważ użytkownik (podmiot) został już uwierzytelniony z serwerem OIDC (odbiorca).

2. Użytkownik korzysta z aplikacji jednostronowej

W aplikacji jednosronowej (lub aplikacji mobilnej), frontend i backend są oddzielone. Załóżmy, że backend jest usługą API:

  • Podmiot: Użytkownik
  • Odbiorca: Usługa API
  • Klient: Aplikacja jednosronowa (SPA)

Uproszczony diagram sekwencji z przepływem kodu autoryzacji:

Ponieważ usługa API jest nieinteraktywna, SPA musi użyć tokenu dostępu z usługą API jako odbiorcą (aud w tokenie).

Dlaczego serwer OIDC nadal jest odbiorcą?

Technicznie, możesz usunąć serwer OIDC z listy odbiorców. Ponieważ w większości przypadków, będziesz potrzebował informacji o użytkowniku z serwera OIDC (co wymaga, by serwer OIDC był odbiorcą), lepiej jest zawsze uwzględniać serwer OIDC na liście odbiorców, gdy zaangażowana jest interakcja z użytkownikiem.

Czy mówisz, że możemy mieć wielu odbiorców w żądaniu autoryzacji?

Dokładnie tak! Pamiętaj, że OIDC jest zbudowane na OAuth 2.0, możliwe jest wykorzystanie RFC 8707: Wskaźniki zasobów dla OAuth 2.0 w żądaniu autoryzacji, aby określić wielu odbiorców. Wymaga to wsparcia zarówno z grantu, jak i serwera OIDC. Logto obsługuje tę funkcję natywnie.

3. Komunikacja maszyna-do-maszyna

Załóżmy, że masz usługę A, która musi wywołać usługę B:

  • Podmiot: Usługa A
  • Odbiorca: Usługa B
  • Klient: Usługa A

Uproszczony diagram sekwencji z grant klienta:

Kiedy usługa B potrzebuje wywołać usługę A, role są po prostu zamieniane.

Podsumowanie

  • Podmiot: Może to być użytkownik, usługa lub jakikolwiek podmiot, który musi uzyskać dostęp do odbiorcy.
  • Klient: Może to być aplikacja internetowa, aplikacja mobilna lub jakikolwiek podmiot, który inicjuje żądanie lub działa w imieniu podmiotu.
  • Odbiorca: Może to być usługa, API lub jakikolwiek podmiot, który zapewnia dostęp do podmiotu.

Czym są tokeny dostępu, ID tokeny i refresh tokeny?

Przy pracy z OIDC możesz napotkać trzy rodzaje tokenów:

  • Token dostępu: Jest używany do uzyskania dostępu do odbiorcy. Może to być JWT (JSON Web Token) lub nieprzezroczysty token (zazwyczaj ciąg losowy).
  • ID token: Specyficzny dla OIDC token, który zawiera informacje o użytkowniku. Jest zawsze JWT. Klient może dekodować token, aby uzyskać informacje o użytkowniku.
  • Refresh token: Jest używany do uzyskania nowego zestawu tokenów, gdy token dostępu lub ID token wygasną.

Dla szczegółowego wyjaśnienia tych tokenów możesz odwołać się do Zrozumienie refresh tokenów, access tokenów i ID tokenów w protokole OIDC.

W powyższych scenariuszach 1 i 2, termin żądanie autoryzacji odnosi się do żądania uzyskania zestawu tokenów za pośrednictwem określonego grantu.

Gdy wszystko idzie dobrze, zestaw tokenów zostanie zwrócony w kroku "Wymień tokeny używając kodu". Dostępne tokeny w zestawie zależą od wielu czynników, szczególnie od parametru scope w żądaniu autoryzacji. Dla uproszczenia, założymy, że wszystkie tokeny są zwracane w zestawie. Po wygaśnięciu tokena dostępu, klient może użyć refresh tokena, aby uzyskać nowy zestaw tokenów bez interakcji z użytkownikiem.

Dla scenariusza 3, jest to prostsze, ponieważ grant klienta zwraca tylko token dostępu.

Jak obsłużyć wielu odbiorców w OIDC?

Możesz zauważyć, że tylko jeden token dostępu jest zwracany jednorazowo. Jak moglibyśmy obsłużyć przypadek, w którym klient musi uzyskać dostęp do wielu odbiorców?

Istnieją dwa powszechne rozwiązania:

Określ resource w żądaniu wymiany kodu

Kiedy klient wymienia kod na tokeny, może określić parametr resource w żądaniu. Serwer OIDC zwróci token dostępu dla określonego odbiorcy, jeśli to stosowne.

Oto przykład nie-normatywny:

Następnie serwer OIDC zwróci token dostępu dla odbiorcy API_SERVICE, jeśli jest to stosowne.

Użycie refresh tokena do uzyskania nowego tokenu dostępu

Z RFC 8707, klient może nawet określić wielu odbiorców, używając parametru resource wiele razy. Teraz, jeśli refresh token jest dostępny w klientach, klient może określić odbiorcę w parametrze resource podczas odświeżania tokenu.

Oto przykład nie-normatywny:

Ma to taki sam efekt jak poprzednie rozwiązanie. Tymczasem inne udzielone publiczności są nadal dostępne w przyszłych żądaniach tokenu.

Grant klienta

Możesz również użyć parametru resource w grancie klienta, aby określić odbiorcę. Nie ma problemu z wieloma odbiorcami w tym grancie, ponieważ zawsze możesz zażądać nowego tokenu dostępu dla innego odbiorcy, po prostu wysyłając kolejne żądanie tokenu.

Zabezpiecz swoją usługę API

„Usługa API” w scenariuszu 2 i „Usługa B” w scenariuszu 3 mają jedną wspólną cechę: muszą zweryfikować token dostępu, aby określić, czy żądanie jest autoryzowane. W zależności od formatu tokenu dostępu proces walidacji może się różnić.

  • Token nieprzezroczysty: Usługa API musi wywołać serwer OIDC, aby zweryfikować token. Punkt introspekcji jest zwykle zapewniany przez serwer OIDC do tego celu.
  • JWT: Usługa API może lokalnie zweryfikować token, sprawdzając podpis i roszczenia w tokenie. Serwer OIDC zwykle udostępnia Zbiór kluczws JSON Web Key Set (JWKS) (jwks_uri) dla usługi API, aby uzyskać klucz publiczny do weryfikacji podpisu.

Jeśli nie znasz się na JWT, możesz odwołać się do Co to jest JSON Web Token (JWT)?. W rzeczywistości, zwykle nie ma potrzeby weryfikacji podpisu i potwierdzania roszczeń ręcznie, ponieważ istnieje wiele bibliotek, które mogą to zrobić za ciebie, takie jak jose dla Node.js i przeglądarek internetowych.

Potwierdzanie roszczeń

Oprócz weryfikacji podpisu JWT, usługa API powinna zawsze sprawdzać roszczenia w tokenie:

  • iss: Wydawca tokenu. Powinien pasować do adresu URL wydawcy serwera OIDC.
  • aud: Odbiorca tokenu. Powinien pasować do wartości odbiorcy usługi API (zwykle do prawidłowego URI).
  • exp: Data wygaśnięcia tokenu. Usługa API powinna odrzucić token, jeśli jest przeterminowany.
  • scope: Zakresy (uprawnienia) tokenu. Usługa API powinna sprawdzić, czy wymagany zakres jest obecny w tokenie.

Inne roszczenia, takie jak sub (podmiot) i iat ( wydany) też są ważne w niektórych przypadkach. Jeśli masz dodatkowe środki bezpieczeństwa, sprawdź roszczenia odpowiednio.

Autoryzacja

Pozostało nierozwiązane pytanie: Jak możemy ustalić, czy dana scope (czyli uprawnienie) może zostać udzielona podmiotowi?

Jedno pytanie prowadzi do całkiem nowego świata autoryzacji, który wykracza poza obszar tego artykułu. W skrócie, istnieją niektóre powszechne podejścia, takie jak RBAC (Role-Based Access Control) i ABAC (Attribute-Based Access Control). Oto niektóre zasoby, aby zacząć:

Noty końcowe

Wprowadzanie serwera OIDC do twojego projektu to duży krok. Może znacznie poprawić bezpieczeństwo i skalowalność twojego projektu. Jednak może to zająć trochę czasu, aby zrozumieć koncepcje i interakcje między komponentami.

Wybór dobrego dostawcy OIDC, który spełnia twoje wymagania i preferencje, może znacznie zmniejszyć złożoność procesu integracji, ponieważ dostawca zazwyczaj oferuje cały pakiet, w tym serwer OIDC, mechanizmy autoryzacji, SDK i funkcje przedsiębiorstwa, które mogą być potrzebne w przyszłości.

Mam nadzieję, że ten przewodnik pomoże ci zrozumieć podstawy integracji serwera OIDC. Jeśli szukasz jednego, by zacząć, mogę egoistycznie polecić Logto, nasze infrastrukturalne rozwiązanie tożsamościowe dla deweloperów.