Ders 09 / 23
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ı.
İçindekiler
Ö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.
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
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?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.