Tech Handbook Null Yard

OAuth 2.0, OpenID Connect, JWT i sesje

OAuth, OpenID Connect, JWT i sesje rozwiązują różne problemy. Najważniejsze jest rozdzielenie uwierzytelnienia od autoryzacji oraz świadomy wybór, gdzie przechowywany jest stan logowania i jak chronione są tokeny.

Aktualne praktyki OAuth opierają się na Authorization Code Flow z PKCE. Dla nowych implementacji warto czytać RFC 9700 oraz zalecenia dla aplikacji przeglądarkowych z RFC 10017 zamiast powielać starsze przykłady OAuth.

Powiązane tematy: Bezpieczeństwo aplikacji webowych, API i integracje systemów oraz HTTP, HTTPS i TLS.

1. Najpierw pojęcia

Authentication:

kim jesteś?

Authorization:

co wolno ci zrobić?

OAuth 2.0 dotyczy głównie delegowania autoryzacji.

OpenID Connect dodaje warstwę uwierzytelnienia.

JWT jest formatem tokenu.

Sesja jest sposobem utrzymywania stanu zalogowania.

To nie są zamienne pojęcia.

2. Klasyczna sesja

Flow:

login
↓
backend sprawdza dane
↓
backend tworzy session ID
↓
browser dostaje cookie
↓
kolejne requesty zawierają cookie

Serwer przechowuje stan sesji.

Przykład:

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax

Ważne flagi:

  • HttpOnly,
  • Secure,
  • SameSite.

4. Session fixation

Po poprawnym logowaniu warto wygenerować nowe session ID.

Nie należy zachowywać identyfikatora, który istniał przed uwierzytelnieniem.

5. Session expiry

Sesja powinna mieć:

  • idle timeout,
  • absolute timeout,
  • możliwość unieważnienia.

6. CSRF

Przy auth opartym na cookies przeglądarka automatycznie wysyła cookie.

To jest jeden z powodów, dla których trzeba myśleć o CSRF.

Ochrona:

  • SameSite,
  • token CSRF,
  • walidacja Origin w odpowiednich miejscach.

7. JWT

JWT wygląda zwykle:

header.payload.signature

To trzy fragmenty zakodowane Base64URL.

8. JWT nie jest szyfrowany domyślnie

Payload można odczytać.

Nie wkładaj tam sekretów.

Podpis zapewnia integralność i autentyczność, nie poufność.

9. Typowe claims

iss  issuer
sub  subject
aud  audience
exp  expiration
iat  issued at
nbf  not before

10. Weryfikacja JWT

Nie wystarczy zdekodować token.

Trzeba sprawdzić:

  • podpis,
  • algorytm,
  • issuer,
  • audience,
  • expiration,
  • inne wymagane claims.

11. Access token

Access token służy do dostępu do API.

Powinien być:

  • krótko żyjący,
  • ograniczony zakresem,
  • przeznaczony dla konkretnego resource servera.

12. Refresh token

Pozwala uzyskać nowy access token.

Jest bardziej wrażliwy, bo zwykle żyje dłużej.

Powinien być dobrze chroniony.

13. OAuth 2.0 - role

Najczęściej:

  • Resource Owner,
  • Client,
  • Authorization Server,
  • Resource Server.

14. Authorization Code Flow

Typowy flow webowy:

browser → authorization server
      ← login/consent
      ← authorization code
backend → token endpoint
backend ← access token

15. PKCE

PKCE chroni Authorization Code Flow przed przejęciem kodu.

W praktyce jest standardem szczególnie dla klientów publicznych.

Elementy:

code_verifier
code_challenge

16. Redirect URI

Redirect URI musi być kontrolowane i ściśle walidowane.

Luźne wildcardy mogą prowadzić do przejęcia kodu.

17. state

Parametr state pomaga powiązać odpowiedź z rozpoczętą sesją autoryzacji i chronić przed częścią ataków CSRF.

18. OpenID Connect

OIDC działa na OAuth 2.0 i dodaje tożsamość.

Najważniejszy element:

ID Token

19. ID Token a Access Token

ID Token:

informacja o uwierzytelnieniu użytkownika

Access Token:

dostęp do API

Nie używaj ID Token jako access tokenu do API.

20. nonce

W OIDC nonce pomaga powiązać ID Token z rozpoczętym flow i ograniczać replay.

21. Scopes

Przykłady:

openid
profile
email
read:orders
write:orders

Dawaj minimalny potrzebny zakres.

22. Client secret

Client secret jest sekretem tylko wtedy, gdy klient potrafi go faktycznie ukryć.

Aplikacja działająca w przeglądarce nie może bezpiecznie przechowywać stałego sekretu.

23. SPA

Dla aplikacji browserowych typowe podejście:

  • Authorization Code + PKCE,
  • bez client secret w frontendzie.

24. BFF

Backend for Frontend może przejąć obsługę tokenów po stronie serwera.

Browser dostaje klasyczną sesję/cookie.

To często upraszcza bezpieczeństwo frontendu.

25. Token storage

Unikaj automatycznej odpowiedzi:

wrzuć wszystko do localStorage

Ryzyko XSS jest wtedy szczególnie istotne.

Wybór storage zależy od architektury.

26. Token revocation

Tokeny powinny mieć strategię:

  • expiration,
  • revocation,
  • rotation.

27. Refresh token rotation

Po użyciu refresh tokenu serwer może wydać nowy i unieważnić poprzedni.

Pomaga wykrywać replay.

28. JWKS

Serwer może publikować klucze publiczne:

/.well-known/jwks.json

Klient wykorzystuje je do weryfikacji podpisów.

29. Discovery

OIDC:

/.well-known/openid-configuration

Dokument opisuje endpointy i możliwości dostawcy.

30. Najczęstsze błędy

  • brak weryfikacji aud,
  • akceptowanie dowolnego iss,
  • zbyt długie tokeny,
  • tokeny w URL,
  • sekrety w frontendzie,
  • brak PKCE,
  • źle walidowane redirect URI,
  • mylenie ID Token z Access Token,
  • brak rotacji refresh tokenów.

31. Kiedy sesja, kiedy token

Klasyczna aplikacja webowa:

session cookie

Rozproszone API / integracje:

access token

Nie wybieraj JWT tylko dlatego, że brzmi nowocześnie.

32. Co trzeba umieć

  • odróżnić authn od authz,
  • rozumieć cookie session,
  • rozumieć JWT,
  • znać Authorization Code + PKCE,
  • odróżnić ID Token i Access Token,
  • rozumieć scopes,
  • bezpiecznie myśleć o storage i expiration.

Oficjalne źródła

  • OAuth 2.0 - RFC 6749: https://www.rfc-editor.org/rfc/rfc6749
  • OAuth 2.0 Security BCP - RFC 9700: https://www.rfc-editor.org/rfc/rfc9700
  • OAuth 2.0 for Browser-Based Applications - RFC 10017: https://www.rfc-editor.org/rfc/rfc10017
  • PKCE - RFC 7636: https://www.rfc-editor.org/rfc/rfc7636
  • JWT - RFC 7519: https://www.rfc-editor.org/rfc/rfc7519
  • OpenID Connect Core: https://openid.net/specs/openid-connect-core-1_0.html