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

  1. Panelde, ortamınızda bir web uygulaması oluşturun.
  2. İstemci kimlik doğrulamasını seçin: bir istemci sırrı (bff.ClientSecretBasic) veya private_key_jwt (bff.PrivateKeyJWT). private_key_jwt için uygulamanın genel anahtarını kaydedin ve özel anahtarı sunucunuzda tutun.
  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

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:

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:

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