---
title: 'Kurumsal Federasyon'
source: 'https://academia.sh/tr/kurslar/kimlik-ve-yetki/kurumsal-federasyon'
course: 'Kimlik Doğrulama ve Yetkilendirme'
language: tr
updated: '2026-08-17T18:06:48+00:00'
license: 'CC BY-SA 4.0'
---

# Kurumsal Federasyon

İddia belgesiyle taşınan kimliğin imza, yayıncı, hedef kitle ve süre penceresiyle denetlenmesi, tekrar kullanımın engellenmesi, dışarıdan gelen özniteliklerin açık bir tabloyla yerel role çevrilmesi ve çıkışın sınırı.

Önceki ders kimlik katmanını yetki devri protokolünün üstüne ekledi: uygulama, kullanıcının
kim olduğunu imzalı bir belgeden öğrendi. Belgeyi üreten taraf ile tüketen taraf aynı
kurumun parçalarıydı.

Kurumsal federasyonda bu varsayım kalkar. Kullanıcı kimliğini **kendi kurumunda**
doğrular; kütüphane servisi o kurumun ürettiği belgeye güvenerek kullanıcıyı kabul eder.
Kütüphane parolayı hiç görmez, kullanıcı listesini hiç tutmaz. Bu düzenin adı **çoklu
oturum açma (single sign-on)**, taşıyıcısı ise **iddia belgesidir (assertion)**.

## Güvenin Yönü ve Sınırı

Federasyonda iki taraf vardır: kimliği doğrulayan **kimlik sağlayıcı** ve kaynağa erişimi
yöneten **hizmet sağlayıcı**. Güven tek yönlüdür ve sınırlıdır: hizmet sağlayıcı, kimlik
sağlayıcının "bu kişi budur" iddiasına güvenir; "bu kişi şunu yapabilir" kararını kendisi
verir.

Bu ayrım kursun ilk dersindeki ayrımın kurumlar arası biçimidir. Kimlik dışarıdan gelir,
yetki içeride kalır. Dışarıdan gelen bir öznitelik doğrudan yetkiye çevrilirse, komşu
kurumun grup yönetimi bizim yetki sistemimizi belirler hâle gelir.

Aşağıdaki hesap bir iddia belgesinin üretilmesini, doğrulanmasını ve yerel role
çevrilmesini uçtan uca çalıştırır.

```bash
cat > federasyon.mjs <<'EOF'
// federasyon.mjs — iddia belgesinin uretilmesi, dogrulanmasi ve yerel role cevrilmesi
import { createHmac, timingSafeEqual, randomBytes } from "node:crypto";

const SIR = Buffer.from("kurum-imzalama-anahtari-ornek");
const b64 = (o) => Buffer.from(JSON.stringify(o)).toString("base64url");
const imzala = (govde) => createHmac("sha256", SIR).update(govde).digest("base64url");

// Kimlik saglayan kurum bir iddia belgesi uretir.
function iddiaUret({ ozne, epostaDogrulandi, gruplar, hedef, saniye, saat }) {
  const govde = b64({
    iss: "https://kimlik.kuzey-universite.test",
    sub: ozne, aud: hedef,
    iat: saat, exp: saat + saniye,
    jti: randomBytes(6).toString("hex"),
    eposta_dogrulandi: epostaDogrulandi, gruplar,
  });
  return govde + "." + imzala(govde);
}

// Hizmet saglayan kurum belgeyi dogrular. Her adim ayri bir karar.
const KULLANILAN = new Set();
function dogrula(belge, { hedef, saat, yayinci }) {
  const [govde, imza] = belge.split(".");
  const beklenen = imzala(govde);
  if (imza.length !== beklenen.length ||
      !timingSafeEqual(Buffer.from(imza), Buffer.from(beklenen))) return "red: imza";
  const i = JSON.parse(Buffer.from(govde, "base64url"));
  if (i.iss !== yayinci) return "red: yayinci";
  if (i.aud !== hedef) return "red: hedef kitle";
  if (saat >= i.exp) return "red: suresi gecmis";
  if (saat < i.iat) return "red: gelecek tarihli";
  if (KULLANILAN.has(i.jti)) return "red: yeniden kullanim";
  KULLANILAN.add(i.jti);
  return "kabul";
}

const SAAT = 1_770_000_000;                       // sabit saat: cikti yeniden uretilebilsin
const HEDEF = "https://kutuphane.kuzey-universite.test";
const YAYINCI = "https://kimlik.kuzey-universite.test";
const temel = { ozne: "ogr-4417", epostaDogrulandi: true, gruplar: ["ogrenci", "fen-fakultesi"],
                hedef: HEDEF, saniye: 300, saat: SAAT };

const denemeler = [
  ["gecerli belge", iddiaUret(temel), { hedef: HEDEF, saat: SAAT + 10, yayinci: YAYINCI }],
  ["baska kuruma yazilmis", iddiaUret({ ...temel, hedef: "https://baska.test" }), { hedef: HEDEF, saat: SAAT + 10, yayinci: YAYINCI }],
  ["suresi gecmis", iddiaUret({ ...temel, saniye: 5 }), { hedef: HEDEF, saat: SAAT + 60, yayinci: YAYINCI }],
  ["imzasi bozulmus", iddiaUret(temel).slice(0, -1) + "x", { hedef: HEDEF, saat: SAAT + 10, yayinci: YAYINCI }],
  ["baska yayincidan", iddiaUret(temel), { hedef: HEDEF, saat: SAAT + 10, yayinci: "https://sahte.test" }],
];
console.log("deneme                    sonuc");
for (const [ad, belge, kosul] of denemeler) console.log(`  ${ad.padEnd(24)} ${dogrula(belge, kosul)}`);

// Ayni belge iki kez sunulursa
const tekrar = iddiaUret(temel);
console.log(`  ${"ilk sunum".padEnd(24)} ${dogrula(tekrar, { hedef: HEDEF, saat: SAAT + 10, yayinci: YAYINCI })}`);
console.log(`  ${"ayni belge ikinci kez".padEnd(24)} ${dogrula(tekrar, { hedef: HEDEF, saat: SAAT + 20, yayinci: YAYINCI })}`);

// Disaridan gelen oznitelikler yerel role cevrilir; esleme tablosu acik olmali.
const ESLEME = [
  { kosul: (i) => i.gruplar.includes("kutuphane-personeli"), rol: "gorevli" },
  { kosul: (i) => i.gruplar.includes("ogrenci") && i.eposta_dogrulandi, rol: "uye" },
  { kosul: (i) => i.gruplar.includes("akademik"), rol: "uye" },
];
function yerelRol(belge) {
  const i = JSON.parse(Buffer.from(belge.split(".")[0], "base64url"));
  const eslesen = ESLEME.find((e) => e.kosul(i));
  return { ozne: i.sub, gruplar: i.gruplar.join(","), rol: eslesen ? eslesen.rol : "rol yok" };
}
console.log("\ndisaridan gelen ozne       gruplar                     yerel rol");
for (const g of [["ogrenci", "fen-fakultesi"], ["kutuphane-personeli"], ["misafir"]]) {
  const r = yerelRol(iddiaUret({ ...temel, gruplar: g }));
  console.log(`  ${r.ozne.padEnd(24)} ${r.gruplar.padEnd(27)} ${r.rol}`);
}
const dogrulanmamis = yerelRol(iddiaUret({ ...temel, epostaDogrulandi: false, gruplar: ["ogrenci"] }));
console.log(`  ${dogrulanmamis.ozne.padEnd(24)} ${"ogrenci (eposta dogrulanmamis)".padEnd(27)} ${dogrulanmamis.rol}`);
EOF
node federasyon.mjs
```

```text
deneme                    sonuc
  gecerli belge            kabul
  baska kuruma yazilmis    red: hedef kitle
  suresi gecmis            red: suresi gecmis
  imzasi bozulmus          red: imza
  baska yayincidan         red: yayinci
  ilk sunum                kabul
  ayni belge ikinci kez    red: yeniden kullanim

disaridan gelen ozne       gruplar                     yerel rol
  ogr-4417                 ogrenci,fen-fakultesi       uye
  ogr-4417                 kutuphane-personeli         gorevli
  ogr-4417                 misafir                     rol yok
  ogr-4417                 ogrenci (eposta dogrulanmamis) rol yok
```

## Doğrulama Tek Adım Değildir

Çıktının ilk bölümü beş ayrı reddi gösteriyor ve her biri ayrı bir denetimden geliyor.
İmza, belgenin yolda değişmediğini söyler — ama tek başına yeterli değildir. Yayıncı
denetimi, belgenin **beklenen kurumdan** geldiğini doğrular; bu denetim atlanırsa, geçerli
imzalı bir belge üretebilen herhangi bir kurum bizim kullanıcılarımızı tanımlayabilir.

Hedef kitle denetimi en sık atlananıdır. Kimlik sağlayıcı aynı kullanıcı için birden çok
hizmete belge üretir; bir hizmet için üretilmiş belge diğerinde kabul edilirse, zayıf
korunan bir servis güçlü korunan bir servise geçiş kapısı olur. Belgenin hedefi, onu kimin
kabul edeceğini yazar.

Süre penceresi iki yönlüdür: geçmiş taraf belgenin ömrünü, gelecek taraf saat kaymasını
denetler. Pencerenin dar tutulması, belge ele geçirildiğinde kullanım süresini kısaltır.

## Aynı Belge İkinci Kez Kullanılamaz

İkinci bölümdeki iki satır tekrar kullanım savunmasını gösteriyor. Belge, benzersiz bir
tanımlayıcı taşır ve tüketildiğinde bu tanımlayıcı kaydedilir; aynı belge ikinci kez
sunulduğunda reddedilir.

Kaydın ömrü belgenin ömrü kadardır: süresi geçmiş bir belgenin tanımlayıcısını saklamak
gereksizdir, çünkü süre denetimi zaten reddeder. Bu, kaydın sınırsız büyümesini engeller —
tekrar kullanım listesi, geçerlilik penceresi kadar geriye bakan bir kayıttır.

## Öznitelikten Role Çevrim Açık Olmalı

Üçüncü bölüm eşleme tablosunu çalıştırıyor. Dışarıdan gelen grup adları doğrudan rol olarak
kullanılmıyor; yerel bir tabloya göre çevriliyor. Eşleşmeyen bir grup "rol yok" sonucunu
veriyor ve kullanıcı kaynağa erişemiyor.

Son satır ek bir koşulu gösteriyor: öğrenci grubunda olmak yetmiyor, e-postanın doğrulanmış
olması da gerekiyor. Kimlik sağlayıcının gönderdiği her öznitelik aynı güvenilirlikte
değildir; hangi özniteliğe hangi koşulla güvenileceği hizmet sağlayıcının kararıdır.

Tablonun açık olmasının pratik sonucu şudur: komşu kurum yeni bir grup açtığında bizim
sistemimizde hiçbir şey değişmez. Yetki genişlemesi ancak eşleme tablosuna bir satır
eklendiğinde olur ve o satır incelemeden geçer.

## Çıkışın Sınırı

Federasyonda çıkış işlemi tek taraflı değildir. Kullanıcı kütüphane servisinden çıktığında
kimlik sağlayıcıdaki oturumu sürer; sonraki istekte yeniden yönlendirme sessizce yeni bir
belge üretir ve kullanıcı hiç çıkmamış gibi görünür.

Bunun iki karşılığı vardır. Yerel çıkış, yalnız hizmet sağlayıcıdaki oturumu sonlandırır ve
"başka bir hesapla gir" isteğini karşılamaz. Merkezî çıkış, kimlik sağlayıcıdaki oturumu da
sonlandırır ve o sağlayıcıya bağlı bütün hizmetleri etkiler. Ortak makinelerde ikincisi
gerekir; kullanıcıya hangisinin yapıldığı açıkça söylenmelidir.

## Özet

- Federasyonda kimlik dışarıdan gelir, yetki içeride kalır: iddia belgesi kişiyi bildirir,
  ne yapabileceğini hizmet sağlayıcı belirler.
- Doğrulama tek adım değildir; imza, yayıncı, hedef kitle ve süre penceresi ayrı ayrı
  denetlenir — modelde bu denetimlerin her biri ayrı bir reddi üretti.
- Belge benzersiz tanımlayıcısıyla bir kez tüketilir; tekrar kullanım listesi belgenin
  geçerlilik penceresi kadar geriye bakar.
- Dışarıdan gelen öznitelikler açık bir tabloyla yerel role çevrilir; eşleşmeyen grup yetki
  almaz ve komşu kurumun grup açması bizim yetkilerimizi değiştirmez.
- Yerel çıkış ile merkezî çıkış farklı şeylerdir; hangisinin yapıldığı kullanıcıya
  bildirilmelidir.

## Sonraki Adım

Buraya kadarki bütün akışlarda karşıda bir insan vardı: parola giren, onay ekranını
okuyan, ikinci etmeni sağlayan biri. Kütüphane servisini çağıranların bir bölümü ise
insan değildir — gece çalışan bir toplu iş, komşu kurumun katalog eşitleyicisi, bir
gösterge panosu. Bunların ne parolası ne de onay ekranı vardır. Sonraki ders bu çağıranlar
için kullanılan kimlik bilgisini ele alır: nasıl üretilir, nerede saklanır ve nasıl
döndürülür?
