Fastify oturumları

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

Taşıyıcı (bearer) belirteçleri alan bir API'yi korumak için bunun yerine API'nizi koruma sayfası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) ya da 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. Yönlendirme URI'sini https://app.acme.example/auth/callback ve çıkış sonrası yönlendirme URI'sini https://app.acme.example/ olarak ekleyin.
  4. En az 32 karakterlik bir çerez sırrı oluşturun; örneğin openssl rand -base64 32 ile. Bunu depoya değil, gizli bilgi deponuzda saklayın.

Kurulum

import Fastify from "fastify";
import { createBff, fastifyRequireAuth, fastifySession } 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 = Fastify();
fastifySession(app, bff); // on the root instance, so it applies to every route

app.get("/orders", { preHandler: fastifyRequireAuth(bff) }, async (request) => {
  return `Signed in as ${request.keenauth!.session!.user.email}`;
});

private_key_jwt kullanırken sır yerine özel anahtarı geçirin: clientAuth: { method: "private_key_jwt", privateKey: readFileSync("bff-key.pem", "utf8") }. SDK, belirteç ve PAR uç noktalarına yapılan her istek için yeni bir istemci onayı imzalar. Anahtar bir KMS veya HSM'de tutuluyorsa, assertion() her çağrıldığında yeni bir imzalı istemci onayı döndüren clientAuth: { method: "private_key_jwt", assertion } değerini geçirin. Onayı ve desteklenen algoritmaları Express sayfası açıklar.

fastifySession işlevini kök örnekte çağırın. Kapsüllenmiş bir eklentinin içinde çağrılırsa yalnızca o eklentinin yollarında geçerli olur.

appBaseUrl, uygulamanızın herkese açık adresidir. SDK yönlendirme URI'sini ve tüm yönlendirmeleri bundan oluşturur; istekteki Host veya X-Forwarded-* başlıklarından asla oluşturmaz. Bu nedenle trustProxy seçeneği 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.

Yollar

fastifySession üç yol ekler ve diğer her istekte bir onRequest kancasında oturumu okur:

Yol Ne yapar
GET /auth/login Girişi başlatır. İsteğe bağlı sorgu parametreleri: returnTo (kullanıcının varacağı yer) ve organization (bir kuruluşta giriş yapın).
GET /auth/callback Girişi tamamlar ve oturum çerezini ayarlar.
GET veya POST /auth/logout KeenAuth'tan çıkış yapar ve uygulamanıza geri döner.

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

returnTo, uygulamanıza ait bir yol olmalıdır, örneğin /orders?tab=open. //evil.example ya da tam bir URL gibi başka her değer yok sayılır ve kullanıcı / sayfasına yönlendirilir.

Yolları koruma

fastifyRequireAuth(bff), yalnızca oturumu olan isteklerin geçmesine izin veren bir preHandler'dır:

POST, PUT, PATCH, DELETE ve diğer güvensiz yöntemler için tarayıcı isteğin uygulamanızdan geldiğini belirtmelidir: Sec-Fetch-Site: same-origin ya da uygulamanızın kaynağına eşit bir Origin başlığı. Diğer istekler 403 alır. Bu, SameSite=Lax korumasına ek olarak siteler arası istek sahteciliğine karşı korur.

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

request.keenauth şunları içerir:

app.get("/api/orders", { preHandler: fastifyRequireAuth(bff) }, async (request, reply) => {
  const upstream = await fetch("https://api.acme.example/v1/orders", {
    headers: { Authorization: `Bearer ${request.keenauth!.accessToken}` },
  });
  return reply.code(upstream.status).send(await upstream.json());
});

TypeScript'te özelliği bir kez bildirin:

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

declare module "fastify" {
  interface FastifyRequest {
    keenauth?: SessionContext | null;
  }
}

Erişim belirtecinin süresi 60 saniye içinde dolacaksa SDK, işleyiciniz çalışmadan önce belirteci yeniler. Her yenileme, yenileme belirtecini döndürür ve yanıta 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ştirme

bff.switchOrganizationPath("org_01j9…", "/dashboard"), kullanıcıyı o kuruluşta yeniden giriş yaptıran /auth/login bağlantısını döndürür. KeenAuth üyeliği denetler. Girişten sonra session.user.orgId kuruluşu içerir.

Çıkış yapma

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

  1. oturum çerezini siler (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 istek reddedilir. Sec-Fetch-Site göndermeyen tarayıcılar yalnızca kendi sayfalarınızdan gönderilen bir POST ile çıkış yapabilir.

Oturum depolama

Varsayılan olarak tüm oturum çerezdedir; secret değerinden türetilen bir anahtarla AES-256-GCM kullanılarak şifrelenir ve doğrulanır. Değiştirilmiş ya da kopyalanmış çerez reddedilir. Çerez adı __Host-keenauth_session.0 olup Secure, HttpOnly, SameSite=Lax ve Path=/ ile ayarlanır. http://localhost üzerinde __Host- öneki ve Secure kullanılmaz. 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 giriş yeni bir kimlik oluşturur ve önceki kaydı siler. Depo belirteç içerdiği için erişimi kısıtlayın. MemorySessionStore yalnızca geliştirme ve testler içindir.

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

Bugünkü sınırlar