Skip to main content
Authentication iki adımdan oluşur: token edinimi (SPA ↔ Keycloak) ve token doğrulama (API). Token üretimi tamamen Keycloak’a aittir; API simetrik anahtar tutmaz, JWKS üzerinden RS256 imzayı doğrular.

1. Token edinimi — SPA → Keycloak (Authorization Code + PKCE)

Her iki SPA da (Website, Admin) public client’tır ve keycloak-js ile Authorization Code + PKCE (S256) akışını kullanır. Client’lar PublicClient: true, StandardFlowEnabled: true, PkceRequired: true olarak provision edilir; DirectAccessGrantsEnabled: false. Backend-driven bir varyant da mevcuttur (KeycloakOAuthClient, src/DiyanetCleanArchitecture.Infrastructure.Services.OAuth/Keycloak/KeycloakOAuthClient.cs): PKCE code_verifier’ı Redis’te keycloak_pkce_{state} anahtarıyla 10 dakika saklar, callback’te tek kullanımlık olarak okuyup siler.

2. API tarafında JWT doğrulama

Her scheme BuildingBlocks.Keycloak/DependencyInjection.csConfigureScheme ile yapılandırılır. Önemli noktalar:
MapInboundClaims = false kritiktir. Açık kalırsa .NET, sub claim’ini uzun-form ClaimTypes.NameIdentifier URI’sine yeniden adlandırır; UserContextClaimsTransformation FindFirstValue("sub") ile boş döner → account_status="Unknown"ActiveAccountRequirement fail → her yerde 403.

Issuer: internal vs public

Docker dev’de API Keycloak’a iç ağ üzerinden (http://diyanet-keycloak:8080) ulaşır ama tarayıcı http://localhost:8080’i görür. Token’ın iss claim’i public URL’i taşır. Bu yüzden hem internal hem public issuer kabul edilir:
KeycloakSchemeOptions (BuildingBlocks.Keycloak/KeycloakOptions.cs) URL’leri BaseUrl (internal) ve PublicBaseUrl (browser) üzerinden hesaplar:
Audience: client ID ve Keycloak’ın standart account audience’ı kabul edilir.

3. Token kaynak önceliği — OnMessageReceived

API token’ı üç kaynaktan, şu öncelikle okur:
Cookie adları scheme başına farklıdır: vatandaş kc_vatandas_token, personel kc_personel_token (appsettings.Development.jsonKeycloak:*:CookieName).
Query string access_token yalnızca /hubs ve /files yollarında kabul edilir — çünkü EventSource (SSE) ve dosya <img>/indirme istekleri özel header taşıyamaz. Diğer yollarda query token yok sayılır.

Hata teşhisi

OnAuthenticationFailed her başarısız doğrulamada response header’a teşhis bilgisi yazar (curl -v / DevTools’tan görünür):
OnChallenge ise default 401’i bastırıp RFC 7807 application/problem+json döner; scheme, detail ve traceId alanlarıyla hangi scheme’in neden reddettiği görünür.

4. Vatandaş portali — OTP / TOTP (özet)

Vatandaş portalinde Keycloak SSO dışında telefon/e-posta OTP ve TOTP ile challenge token tabanlı bir akış da vardır. Kullanıcı oluşturma → OtpCode.Generate() → domain event ile SMS/e-posta gönderimi → doğrulama → oturum başlatma adımlarını izler. Challenge token kısa ömürlüdür (Jwt:OTPChallenge, Expires: 1 dk).
Bu akışın uçtan uca anlatımı için bkz. OTP doğrulama playbook’u.

5. Refresh token rotation

Refresh davranışı iki yerde tanımlıdır:
  • Keycloak client (provisioning): RefreshTokenRotationEnabled: true. Vatandaş client’ı RefreshTokenLifespanSeconds: 3600, personel client’ı 1800.
  • Uygulamanın kendi backoffice refresh token’ı (appsettingsJwt:RefreshToken:Backoffice): RotationEnabled: true, ReuseDetectionEnabled: true, Expires: 43200 (30 gün), TrustedDeviceExpires: 129600 (90 gün).
Rotation’da her kullanımda yeni refresh token verilir; eski token reuse edilirse reuse-detection devreye girer. Domain tarafında RefreshTokenInfo value object’i token’ı SHA256 hash’ler — plaintext saklanmaz.

6. Token version invalidasyonu

TokenVersionMiddleware (SeedWork/Middlewares/TokenVersionMiddleware.cs) bir feature flag’e bağlıdır (appsettingsSecurity:TokenVersionValidation, dev’de true):
Middleware app.UseAuthentication() ile app.UseAuthorization() arasında çalışır (app.UseTokenVersionValidation()). Rol/izin değişiminde User.TokenVersion artırılır; eski token’lar bir sonraki istekte 401 alır. Bu, “izni geri al → anında etkili olsun” senaryosunu token süresini beklemeden çözer.

İlgili

Authorization

Permission policy ve handler’lar.

OTP Flow

Vatandaş OTP/TOTP challenge akışı.

Client Yapılandırması

PKCE, redirect URI, web origins.

Sorun Giderme

Issuer mismatch, invalid audience, JWKS unreachable.