Express oturumları

@keenauth/node/bff bir Express 4 veya 5 uygulamasına kimlik doğrulama ekler. Sunucunuz OAuth istemcisidir ve tüm belirteçleri sunucuda tutar. Tarayıcı yalnızca şifrelenmiş, HttpOnly bir oturum çerezi alır; hiçbir erişim, yenileme veya ID belirtecini görmez. Bu, arka uç-ön uç (BFF) desenidir. Paket Express'i içe aktarmaz, dolayısıyla ek bir bağımlılık eklemez. Henüz npm'de yayımlanmamıştır.

Bearer belirteçleri alan bir API'yi korumak için bunun yerine API'nizi koruma bölümüne bakın. Yönetim API'sini çağırmak için Node.js yönetim SDK'sına bakın.

Başlamadan önce

  1. Panelde, ortamınızda bir web uygulaması oluşturun.
  2. İstemci kimlik doğrulamasını seçin: bir istemci sırrı (client_secret_basic) veya genel anahtarını uygulamaya kaydettiğiniz bir anahtar çifti ile private_key_jwt. Paylaşılan bir sır sunucunuzdan çıkmadığı için private_key_jwt önerilir.
  3. https://app.acme.example/auth/callback yönlendirme URI'sini ve https://app.acme.example/ çıkış sonrası yönlendirme URI'sini ekleyin.
  4. En az 32 karakterlik bir çerez sırrı üretin, örneğin openssl rand -base64 32 ile. Bunu depoda değil, gizli bilgi deponuzda saklayın.

Kurulum

import express from "express";
import { createBff, expressRequireAuth, expressSession } from "@keenauth/node/bff";

const bff = createBff({
  issuer: "https://acme.eu.keenauth.app", // your environment's issuer, exactly
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  clientAuth: { method: "client_secret_basic", clientSecret: process.env.KEENAUTH_CLIENT_SECRET! },
  appBaseUrl: "https://app.acme.example",
  secret: process.env.KEENAUTH_COOKIE_SECRET!,
});

const app = express();
app.use(expressSession(bff));

app.get("/orders", expressRequireAuth(bff), (req, res) => {
  const { session } = req.keenauth!;
  res.send(`Signed in as ${session!.user.email}`);
});

private_key_jwt kullanırken sır yerine özel anahtarı geçirin. SDK, belirteç ve PAR uç noktasına yapılan her istek için yeni bir istemci onay belirteci imzalar (aud issuer'dır, jti rastgeledir, 120 saniye geçerlidir, kid anahtarın RFC 7638 parmak izidir). Algoritma anahtarı izler: RSA için RS256 (veya alg: "PS256"), P-256 için ES256 ve Ed25519 için EdDSA.

import { readFileSync } from "node:fs";

const bff = createBff({
  issuer: "https://acme.eu.keenauth.app",
  clientId: "app_01j9zzzzzzzzzzzzzzzzzzzz",
  clientAuth: { method: "private_key_jwt", privateKey: readFileSync("bff-key.pem", "utf8") },
  appBaseUrl: "https://app.acme.example",
  secret: process.env.KEENAUTH_COOKIE_SECRET!,
});

Anahtar bir KMS veya HSM içinde tutuluyorsa, bunun yerine clientAuth: { method: "private_key_jwt", assertion } geçirin; burada assertion() her seferinde yeni bir imzalı istemci onay belirteci döndürür. privateKey veya assertion değerlerinden yalnızca birini geçirin, ikisini birden değil.

appBaseUrl, uygulamanızın herkese açık adresidir. SDK yönlendirme URI'sini ve tüm yönlendirmeleri bundan oluşturur; isteğin Host veya X-Forwarded-* başlıklarından asla oluşturmaz, bu yüzden trust proxy ayarı buna etki etmez. Düz http yalnızca localhost için kabul edilir.

Seçenekler createBff çalıştığında denetlenir; dolayısıyla bir yapılandırma hatası uygulamayı başlangıçta durdurur.

Rotalar

expressSession üç rota sunar ve diğer her istekte oturumu okur:

Rota Ne yapar
GET /auth/login Oturum açmayı başlatır. İsteğe bağlı sorgu parametreleri: returnTo (kullanıcının geleceği yer) ve organization (bir kuruluşta oturum açmak için).
GET /auth/callback Oturum açmayı tamamlar ve oturum çerezini ayarlar.
GET veya POST /auth/logout KeenAuth'ta oturumu kapatır ve uygulamanıza geri döner.

Oturum açma, PKCE (S256) ile yetkilendirme kodu akışını kullanır. Ortamınız sunduğunda istek sunucuya gönderilir (PAR). Geri çağırmada SDK state, iss ve ID belirtecini, nonce dahil, denetler. Her başarılı oturum açma yeni bir oturum oluşturur; eski oturum atılır.

returnTo, /orders?tab=open gibi uygulamanıza ait bir yol olmalıdır. //evil.example veya tam bir URL gibi başka değerler yok sayılır ve kullanıcı / adresine gelir.

Rotaları koruma

expressRequireAuth(bff), bir isteğin yalnızca oturumla geçmesine izin verir:

POST, PUT, PATCH, DELETE ve diğer güvensiz yöntemlerde tarayıcı isteğin uygulamanızdan geldiğini belirtmelidir: Sec-Fetch-Site: same-origin veya uygulamanızın kaynağına eşit bir Origin başlığı. Diğer istekler 403 alır. Bu, SameSite=Lax ile birlikte siteler arası istek sahteciliğine karşı koruma sağlar.

Oturumu kullanın ve API'nizi çağırın

req.keenauth şunları içerir:

app.get("/api/orders", expressRequireAuth(bff), async (req, res) => {
  const upstream = await fetch("https://api.acme.example/v1/orders", {
    headers: { Authorization: `Bearer ${req.keenauth!.accessToken}` },
  });
  res.status(upstream.status).json(await upstream.json());
});

TypeScript'te özelliği bir kez tanımlayın:

import type { SessionContext } from "@keenauth/node/bff";

declare module "express-serve-static-core" {
  interface Request {
    keenauth?: SessionContext | null;
  }
}

Erişim belirtecinin süresi 60 saniye içinde dolacaksa SDK, işleyiciniz çalışmadan önce onu yeniler. Her yenileme, yenileme belirtecini döndürür ve yanıtta yeni oturum çerezini ayarlar. Sunucu yenileme belirtecini reddederse oturum sona erer. Geçici bir sunucu hatası oturumu değiştirmeden bırakır.

Erişim belirtecini tarayıcıya göndermeyin.

Kuruluş değiştirin

bff.switchOrganizationPath("org_01j9…", "/dashboard"), kullanıcıyı o kuruluşta yeniden oturum açtıran bir /auth/login bağlantısı döndürür. KeenAuth üyeliği denetler. Oturum açtıktan sonra session.user.orgId kuruluşu tutar.

Oturumu kapatın

Bir formdan /auth/logout adresine POST gönderin. SDK şunları yapar:

  1. oturum çerezini siler (ve bir depo kullanıyorsanız saklanan oturumu da);
  2. yenileme belirtecini iptal eder;
  3. tarayıcıyı, sizi uygulamanıza geri döndüren ortamınızın çıkış uç noktasına gönderir.

Tarayıcının başka bir siteden geldiğini işaretlediği bir istek reddedilir. Sec-Fetch-Site göndermeyen tarayıcılar, oturumu yalnızca kendi sayfalarınızdan gelen bir POST ile kapatabilir.

Oturum depolama

Varsayılan olarak tüm oturum çerezde bulunur; secret değerinden türetilmiş bir anahtarla AES-256-GCM kullanılarak şifrelenir ve kimlik doğrulaması yapılır. Değiştirilmiş veya kopyalanmış bir çerez reddedilir. Çerez __Host-keenauth_session.0 adını taşır ve Secure, HttpOnly, SameSite=Lax ve Path=/ ile ayarlanır. http://localhost üzerinde __Host- öneki ve Secure kaldırılır. Büyük oturumlar en fazla üç çereze bölünür.

Belirteçleri sunucuda tutmak için bir depo geçirin:

import { createBff, type SessionStore } from "@keenauth/node/bff";

const store: SessionStore = {
  get: async (id) => JSON.parse((await redis.get(`sess:${id}`)) ?? "null"),
  set: async (id, session, ttl) => void (await redis.set(`sess:${id}`, JSON.stringify(session), { EX: ttl })),
  delete: async (id) => void (await redis.del(`sess:${id}`)),
};
const bff = createBff({ /* … */ store });

Bu durumda çerez yalnızca şifrelenmiş rastgele bir oturum kimliği içerir. Her oturum açma yeni bir kimlik oluşturur ve önceki kaydı siler. Depo belirteçleri tuttuğu için erişimi kısıtlayın. MemorySessionStore yalnızca geliştirme ve testler içindir.

Bir oturum en fazla 7 gün sürer (sessionMaxAge); yenileme bu süreyi uzatmaz. Sırrı değiştirmek için bir liste geçirin: secret: [newSecret, oldSecret]. Eskisini sessionMaxAge süresinden sonra kaldırın.

Bugünkü sınırlar