GNL
Dokümanlar menüsü
Enterprise@gnldev/auth-ee

SSO (OAuth/OIDC/SAML/JWT)

Kurumsal kimlik sağlayıcıdan (IdP/gateway) gelen isteği Principal'a çözen SSO sağlayıcısı; createEnterpriseAuth kimlik zincirinde userStore ve fallback'ten önce çalışır.

Ne işe yarar / ne zaman kullanılır#

Kurumsal dağıtımlarda kimlik doğrulama genelde GNL'in dışında, bir IdP/gateway (Okta, Azure AD, Auth0, bir API gateway...) tarafından zaten yapılmıştır ve istek GNL'e ulaştığında üzerinde imzalı bir JWT taşır. createJwtSso tam olarak bu senaryo için: redirect/login akışını yürütmez — gelen isteğin Authorization: Bearer <jwt> (ya da özel bir header) içindeki JWT'yi imza + süre (exp) + iss/aud bakımından doğrular ve claim'lerden bir Principal türetir.

Bunun yanında iki adlandırılmış sağlayıcı gerçek redirect+token akışını tam olarak yürütür: createAuth0Sso (OIDC authorization-code — code'u /oauth/token'da id_token'a değiştirir, id_token'ı Auth0'ın JWKS'inden türetilen RS256 public key ile verifyJwt üzerinden doğrular; iss/aud zorunludur) ve createWorkOsSso (WorkOS SSO API — code'u /sso/token'da profile'a değiştirir). Bugün üründe kullanılabilir üç gerçek yol vardır: createJwtSso (yukarı akıştan doğrulanmış JWT), createAuth0Sso ve createWorkOsSso.

Kurulum / import#

paket
import { createJwtSso, createAuth0Sso, createWorkOsSso, createEnterpriseAuth } from '@gnldev/auth-ee';

@gnldev/auth-ee paralı (Enterprise) bir pakettir — geçerli bir lisans anahtarı olmadan createEnterpriseAuth otomatik olarak fallback'e düşer (bkz. aşağıdaki uyarı). SsoProvider arayüzü, ücretsiz @gnldev/auth'un AuthProvider sözleşmesini genişletmez — yalnızca createEnterpriseAuth'a sso seçeneği olarak verilir.

Adım adım kullanım#

1. createJwtSso'ya doğrulama parametrelerini verin — HS256 için secret, RS256/Ed25519 için publicKey (PEM ya da base64url DER/spki); ikisinden biri zorunludur, hiçbiri verilmezse fabrika hata fırlatır:

server/src/auth.ts
const sso = createJwtSso({
  publicKey: process.env.SSO_JWT_PUBLIC_KEY, // the public key taken from Okta / Azure AD / Auth0 JWKS
  issuer: 'https://idp.example.com',
  audience: 'gnl-api',
  // claimMap: { id: 'sub', roles: 'roles', orgId: 'orgId' } (default)
});

2. sso'yu createEnterpriseAuth'a verin — kimlik zincirinde önce SSO denenir, sonra journal-destekli userStore, en son ücretsiz fallback:

server/src/auth.ts
const auth = createEnterpriseAuth({
  licenseKey: process.env.GNL_LICENSE_KEY,
  sso,
  fallback: roleAuth({ admin: { token: process.env.GNL_ADMIN_TOKEN } }),
});

app.route('/api', createRestApi(config, { title: 'GNL API', auth }));

3. İstemci, IdP'den aldığı JWT'yi normal şekilde gönderir; createJwtSso isteği doğrudan principalFromRequest(c) ile çözer (bu, createEnterpriseAuth'un authenticate adımı içinde otomatik çağrılır — host kodunda ekstra bir şey yapmaya gerek yoktur):

curl -s http://localhost:3001/api/agents \
  -H 'authorization: Bearer <jwt-signed-by-your-idp>'

JWT geçersiz, süresi dolmuş ya da bozuksa principalFromRequest asla fırlatmaz — sessizce null döner ve zincir bir sonraki adıma (userStore, ardından fallback) düşer.

4. createAuth0Sso — Auth0 tenant'ınızın domain/clientId/clientSecret/redirectUri'sini verin; authorizeUrl ile /authorize'a yönlendirir, handleCallback code'u /oauth/token'da id_token'a değiştirip Auth0'ın JWKS'i (.well-known/jwks.json) ile RS256 doğrular (iss/aud zorunlu):

server/src/auth.ts — Auth0
const auth0 = createAuth0Sso({
  domain: 'acme.eu.auth0.com',
  clientId: process.env.AUTH0_CLIENT_ID!,
  clientSecret: process.env.AUTH0_CLIENT_SECRET!,
  redirectUri: 'https://app.example.com/callback',
  validateState: (state) => checkStateAgainstSession(state), // CSRF optional but recommended
});

const auth = createEnterpriseAuth({ licenseKey, sso: auth0, fallback });

JWKS ağ çağrısı bir jwksTtlMs (varsayılan 10 dakika) in-memory önbelleğe alınır — principalFromRequest her istekte çalıştığından bu önbellek olmadan her istek bir JWKS fetch'i olurdu; önbellek bayatken fetch başarısız olursa (Auth0 kesintisi) elde bayat bir kopya varsa o kullanılmaya devam eder (stale-while-error).

5. createWorkOsSso — WorkOS SSO API'sini kullanır; handleCallback code'u /sso/token'da profile'a değiştirip Principal türetir (WorkOS profili zaten WorkOS tarafından imzalı/doğrulanmış gelir — ayrı bir JWKS doğrulaması gerekmez):

server/src/auth.ts — WorkOS
const workos = createWorkOsSso({
  clientId: process.env.WORKOS_CLIENT_ID!,
  apiKey: process.env.WORKOS_API_KEY!,
  redirectUri: 'https://app.example.com/callback',
  validateState: (state) => checkStateAgainstSession(state),
});
WorkOS tuzağı: principalFromRequest DAİMA null
createWorkOsSso YALNIZCA handleCallback tabanlı login akışını kurar — WorkOS'ta istek üzerinde taşınan doğrulanabilir bir bearer token sözleşmesi yoktur, bu yüzden principalFromRequest her zaman null döner. Bunu tek başına createEnterpriseAuth({ sso: workos }) olarak bağlarsanız SSO adımı HER istekte null döner ve korunan uçlar sessizce anonime düşer — genelde istenen davranış budur değildir. Doğru desen: WorkOS callback'inden dönen Principal ile kendi oturum JWT'nizi basıp createJwtSso ile birleştirmek:
WorkOS + createJwtSso birleşimi
const session = createJwtSso({ secret: process.env.SESSION_SECRET!, issuer: 'my-app' });

// callback ucunda:
const principal = await workos.handleCallback(c);
const jwt = signMySessionJwt(principal); // a short-lived session JWT you sign yourself
// hand it to the client via Set-Cookie or the body

// sonraki istekler:
const auth = createEnterpriseAuth({ licenseKey, sso: session, fallback });

API referansı#

fncreateJwtSso

JwtSsoOptions → SsoProvider. Yukarı akıştan gelen JWT'yi imza+exp+iss/aud ile doğrular, claim'lerden Principal türetir (redirect/login akışı yürütmez).

fncreateAuth0Sso

Auth0SsoOptions → SsoProvider. OIDC authorization-code: code→id_token değişimi + Auth0 JWKS'iyle RS256 doğrulama (iss/aud zorunlu), TTL cache'li JWKS, opsiyonel validateState CSRF kancası.

typeAuth0SsoOptions

{ domain, clientId, clientSecret, redirectUri, scope?, claimMap?, validateState?, fetch?, jwks?, jwksTtlMs?, now? } — createAuth0Sso yapılandırması.

fncreateWorkOsSso

WorkOsSsoOptions → SsoProvider. WorkOS SSO API: code→profile değişimi ile Principal türetir. principalFromRequest DAİMA null döner — yalnız login akışı kurar, createJwtSso ile birleştirilmelidir.

typeWorkOsSsoOptions

{ clientId, apiKey, redirectUri, organization?, connection?, validateState?, fetch? } — createWorkOsSso yapılandırması.

typeSsoProvider

{ authorizeUrl(state), handleCallback(c), principalFromRequest(c) } — createEnterpriseAuth'un sso seçeneği bu sözleşmeyi bekler.

typeJwtSsoOptions

secret (HS256) ya da publicKey (RS256/Ed25519, PEM veya base64url DER/spki), issuer?, audience?, claimMap?, header? — createJwtSso'nun yapılandırması.

Dikkat
@gnldev/auth-ee paralı bir katmandır: geçerli bir licenseKey olmadan createEnterpriseAuth uyarı loglayıp fallback'e düşer (sso hiç devreye girmez); failClosed: true ile bu durum yerine boot'ta hata fırlatılması sağlanabilir.
Not
Alg-confusion saldırısına karşı imza doğrulaması JWT header'ındaki alg'a körü körüne güvenmez: beklenen algoritma secret/publicKey anahtar tipinden (HS256 / RS256 / EdDSA) türetilir ve header'daki değerle çapraz kontrol edilir. Ayrıca exp claim'i olmayan ya da süresi dolmuş token'lar her zaman reddedilir.
İpucu
Kimlik zinciri sırası önemlidir: ssouserStorefallback. Böylece SSO devredeyken bile boş bir kullanıcı deposuyla operatör bootstrap token'ı ile girip ilk kullanıcıları oluşturabilirsiniz.