Go net/http oturumları
Paket github.com/keenauth/keenauth-go/bff, bir Go net/http uygulamasına Giriş yap özelliği ekler. Sunucunuz OAuth istemcisidir ve tüm belirteçleri sunucuda tutar. Tarayıcı yalnızca şifreli, HttpOnly bir oturum çerezi alır ve hiçbir zaman erişim, yenileme veya ID belirteci görmez. Bu, backend-for-frontend (BFF) desenidir. Paket yalnızca standart kütüphaneyi kullanır. Henüz yayımlanmamıştır.
Taşıyıcı belirteç (bearer token) alan bir API'yi korumak için bunun yerine API'nizi koruma sayfasına bakın.
Başlamadan önce
- Panelde, ortamınızda bir web uygulaması oluşturun.
- İstemci kimlik doğrulamasını seçin: bir istemci sırrı (
bff.ClientSecretBasic) veyaprivate_key_jwt(bff.PrivateKeyJWT).private_key_jwtiçin uygulamanın genel anahtarını kaydedin ve özel anahtarı sunucunuzda tutun. https://app.acme.example/auth/callbackyönlendirme URI'sini vehttps://app.acme.example/çıkış sonrası yönlendirme URI'sini ekleyin.- En az 32 karakterlik bir çerez sırrı üretin, örneğin
openssl rand -base64 32ile. Bunu depoda değil, gizli bilgi deponuzda saklayın.
Kurulum
package main
import (
"fmt"
"net/http"
"os"
"github.com/keenauth/keenauth-go/bff"
)
func main() {
auth, err := bff.New(bff.Options{
Issuer: "https://acme.eu.keenauth.app", // your environment's issuer, exactly
ClientID: "app_01j9zzzzzzzzzzzzzzzzzzzz",
ClientAuth: bff.ClientSecretBasic{Secret: os.Getenv("KEENAUTH_CLIENT_SECRET")},
AppBaseURL: "https://app.acme.example",
Secrets: []string{os.Getenv("KEENAUTH_COOKIE_SECRET")},
})
if err != nil {
panic(err) // configuration errors stop the app at start-up
}
mux := http.NewServeMux()
mux.Handle("GET /orders", auth.RequireAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s := bff.FromContext(r.Context()).Session
fmt.Fprintf(w, "Signed in as %s", s.User.Email)
})))
http.ListenAndServe(":8080", auth.Middleware(mux))
}
İstemci sırrı yerine private_key_jwt kullanmak için özel anahtarı geçirin. Paket her belirteç ve PAR isteği için yeni bir istemci onayı (assertion) imzalar (iss ve sub istemci kimliğinizdir, aud yayıncıdır, ömrü 2 dakikadır ve her seferinde yeni bir jti kullanılır):
pemBytes, err := os.ReadFile("/run/secrets/keenauth-app-key.pem")
if err != nil {
panic(err)
}
key, err := assertion.ParsePrivateKeyPEM(pemBytes) // import "github.com/keenauth/keenauth-go/assertion"
if err != nil {
panic(err)
}
auth, err := bff.New(bff.Options{
Issuer: "https://acme.eu.keenauth.app",
ClientID: "app_01j9zzzzzzzzzzzzzzzzzzzz",
ClientAuth: bff.PrivateKeyJWT{Key: key, KeyID: "app-key-2026-11"},
AppBaseURL: "https://app.acme.example",
Secrets: []string{os.Getenv("KEENAUTH_COOKIE_SECRET")},
})
ES256 (P-256), EdDSA (Ed25519), RS256 ve PS256 (RSA, 2048 bit veya daha fazla) desteklenir; algoritma anahtarı takip eder, Algorithm: "PS256" ise RSA anahtarı için PSS'i seçer. Key herhangi bir crypto.Signer olabilir, dolayısıyla bir KMS veya HSM'de tutulan anahtar da çalışır. Onayı başka bir yerde imzalıyorsanız, bunun yerine bff.PrivateKeyJWT{Assertion: f} ayarlayın; burada f her çağrıda yeni bir imzalı onay döndürür. Key ve Assertion alanlarından yalnızca birini ayarlayın, ikisini birden değil.
AppBaseURL uygulamanızın genel adresidir. Paket 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. Düz http yalnızca localhost için kabul edilir.
Rotalar
Middleware üç rota sunar ve diğer her istekte oturumu okur. Rotaları tek başına da mux.Handle("/auth/", auth) ile bağlayabilirsiniz.
| Rota | Ne yapar |
|---|---|
GET /auth/login |
Giriş işlemini başlatır. İsteğe bağlı sorgu parametreleri: returnTo (kullanıcının varacağı yer) ve organization (bir kuruluşta oturum açma). |
GET /auth/callback |
Girişi tamamlar ve oturum çerezini ayarlar. |
GET veya POST /auth/logout |
KeenAuth'ta Çıkış yap işlemini gerçekleştirir ve uygulamanıza geri döner. |
Giriş, PKCE (S256) ile yetkilendirme kodu akışını kullanır. Ortamınız sunduğunda istek sunucuya gönderilir (PAR). Geri çağırmada paket 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, /orders?tab=open gibi uygulamanızın kendi yolu olmalıdır. //evil.example veya tam bir URL gibi başka her değer yok sayılır ve kullanıcı / sayfasına yönlendirilir.
İşleyicileri koruma
auth.RequireAuth(handler) yalnızca oturumu olan isteklerin geçmesine izin verir:
- oturumu olmayan bir sayfa isteği (
GETveyaHEAD),returnToile/auth/loginadresine yönlendirilir; /api/…yoluna veya başka bir yönteme yapılan istek, bir sorun belgesiyle birlikte401alır. Her yolda401yanıtı içinbff.GuardOptions{API: true}geçirin.
POST, PUT, PATCH, DELETE ve diğer güvenli olmayan 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 kullanma ve API'nizi çağırma
bff.FromContext(r.Context()) şunları döndürür:
Session:nilveya oturum açmış kullanıcı.Session.User,Subject,Email,Name,OrgIDveOrgRolesgibi tipli ID belirteci taleplerine sahiptir; tüm taleplerSession.User.Claimsiçindedir. Oturum asla bir belirteç içermez.AccessToken: sunucu tarafı çağrılar için geçerli bir erişim belirteci veya"". Bunu tarayıcıya göndermeyin.
Erişim belirtecinin süresi 60 saniye içinde dolacaksa, paket işleyicinizi çalıştırmadan ö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. Bir süreçteki eş zamanlı istekler tek bir yenilemeyi paylaşır.
Kuruluş değiştirme
auth.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. Girişten sonra Session.User.OrgID kuruluşu tutar.
Çıkış yapma
Bir formdan /auth/logout adresine POST gönderin. Paket oturum çerezini siler (ve bir depo kullanıyorsanız saklanan oturumu da), yenileme belirtecini iptal eder ve tarayıcıyı ortamınızın çıkış uç noktasına yönlendirir; bu uç nokta da tarayıcıyı uygulamanıza geri 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 gelen bir POST ile çıkış yapabilir.
Oturum depolama
Varsayılan olarak tüm oturum çerezdedir; sırrdan türetilen bir anahtarla AES-256-GCM kullanılarak şifrelenir ve kimliği doğrulanır. Değiştirilmiş veya kopyalanmış çerez reddedilir. Çerezin 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 Options.Store değerini bir bff.SessionStore (Get, Set, Delete) olarak ayarlayın; örneğin Redis üzerinde. Bu durumda çerez yalnızca şifreli, rastgele bir oturum kimliği tutar. Her girişte yeni bir kimlik oluşturulur ve önceki kayıt silinir. Depo belirteçleri tuttuğu için erişimini kısıtlayın. bff.MemoryStore yalnızca geliştirme ve testler içindir.
Bir oturum en fazla 7 gün sürer (SessionMaxAge); yenileme bunu uzatmaz. Sırrı değiştirmek için yeni sırrı önce listeleyin: Secrets: []string{newSecret, oldSecret}. Eski sırrı SessionMaxAge süresinden sonra kaldırın.
Bugünkü sınırlar
- DPoP'a bağlı belirteçler ve arka kanal çıkışı henüz desteklenmiyor.
- Yenilemeler yalnızca tek bir sunucu sürecinde paylaşılır. Birden çok örnek varsa,
refresh_reuse_interval_suygulama ayarı (varsayılan 5 saniye) paralel yenilemenin başarılı olmasına izin verir; değeri0yaparsanız ikinci yenileme oturumu sonlandırır.