Test kiti ile çevrimdışı test etme
Her sunucu SDK'sının (Go, TypeScript ve Python) birim testleri ve CI için bir testing modülü vardır. Bu modül, sabit bir test anahtarıyla imzalanmış erişim belirteçleri ve kimlik belirteçleri üretir, yalnızca bu belirteçleri kabul eden bir belirteç doğrulayıcı oluşturur, ağ erişimi gerektirmeden çalışır, örnek olay yükleri sunar ve webhook teslimlerini herkese açık bir test sırrıyla imzalar. Testleriniz KeenAuth ortamı olmadan, kimlik bilgisi olmadan ve internet bağlantısı olmadan çalışır.
Nasıl çalışır
- Sabit, herkese açık bir test anahtarı. Test belirteçleri ES256 ile ve
keenauth-test-1anahtar kimliğiyle imzalanır. Anahtar bilinçli olarak herkese açıktır: özel kısmı yayımlanmış bir etiketten türetilir ve herkese açık anahtar kümesi her SDK'nın içindedir. Bu anahtara başka hiçbir yerde güvenmeyin. - Var olamayacak bir veren. Test belirteçleri
https://test.keenauth.invalidverenini taşır..invalidüst düzey alan adı ayrılmıştır (RFC 2606) ve hiçbir zaman çözümlenmez; bu nedenle hiçbir gerçek ortam bu verene sahip olamaz. - Açık test modu. SDK doğrulayıcısı bu veren değerini yalnızca kodda test modu etkinleştirildiğinde kabul eder. Normal yöntemle yapılandırılmış bir doğrulayıcı,
.invalidaltındaki her veren değerini bir yapılandırma hatası olarak reddeder. Böylece üretim doğrulayıcısı, veren yanlışlıkla test verenine ayarlansa bile bir test belirtecini kabul edemez. Test anahtarıyla imzalanmış ama gerçek veren değerini taşıyan bir belirteç de reddedilir, çünkü ortamınız farklı anahtarlar yayımlar. - Ağ erişimi yok. Test modunda doğrulayıcı test anahtarını bellekten alır ve hiçbir şey getirmez. Yalnızca test verenini kabul eder.
Test modu diğer kontrolleri zayıflatmaz: süresi dolmuş belirteçler, yanlış hedef kitle, değiştirilmiş yük, eksik jti ve DPoP'ye bağlı ama kanıtı olmayan bir belirteç, üretimdekiyle aynı şekilde reddedilir. Tam liste için API'nizde belirteçleri doğrulama sayfasına bakın.
Test modunu yalnızca test kodunda kullanın. Test belirteçlerini herkes imzalayabilir, dolayısıyla bu modu etkinleştiren bir servis sahte belirteçleri kabul ederdi.
Go
Paket keenauthtest adındadır ve net/http/httptest tarzını izler.
import (
"github.com/keenauth/keenauth-go/keenauthtest"
"github.com/keenauth/keenauth-go/verify"
)
func TestOrdersAPI(t *testing.T) {
v, err := keenauthtest.NewVerifier(verify.Config{Audience: "https://api.acme.example"})
if err != nil {
t.Fatal(err)
}
token, err := keenauthtest.AccessToken("https://api.acme.example",
keenauthtest.WithClaims(map[string]any{"scope": "orders:read", "org_id": "org_01m3vnbwg0fvav6zw6w7v3st0r"}))
if err != nil {
t.Fatal(err)
}
// Pass v to the handler under test and send "Authorization: Bearer " + token.
claims, err := v.VerifyAccessToken(context.Background(), token, nil)
if err != nil || claims.Scope != "orders:read" {
t.Fatal(err)
}
}
keenauthtest.IDToken(clientID, ...) bir kimlik belirteci üretir. WithLifetime geçerlilik süresini değiştirir (negatif bir değer süresi dolmuş bir belirteç üretir) ve WithIssuedAt düzenlenme zamanını ayarlar. WithClaims içinde nil değeri bir talep alanını kaldırır. Paketi kullanmadan verify.Config{TestingMode: true} değerini kendiniz ayarlayabilirsiniz.
TypeScript
Modül @keenauth/node/testing alt yoludur.
import { createTestVerifier, mintAccessToken } from "@keenauth/node/testing";
const verifier = createTestVerifier({ audience: "https://api.acme.example" });
const token = mintAccessToken("https://api.acme.example", {
claims: { scope: "orders:read", org_id: "org_01m3vnbwg0fvav6zw6w7v3st0r" },
});
const claims = await verifier.verifyAccessToken(token);
// claims.subject, claims.scope, claims.claims.org_id
mintIdToken(clientId, ...) bir kimlik belirteci üretir. Seçenekler claims (null değeri bir talep alanını kaldırır), lifetimeSeconds ve issuedAt'tir. Modülü kullanmadan createVerifier fonksiyonuna testing: true geçebilirsiniz.
Python
Modül keenauth.testing olup doğrulayıcı gibi verify ek paketini gerektirir.
from keenauth import testing
verifier = testing.verifier(audience="https://api.acme.example")
token = testing.mint_access_token(
"https://api.acme.example",
claims={"scope": "orders:read", "org_id": "org_01m3vnbwg0fvav6zw6w7v3st0r"},
)
claims = verifier.verify_access_token(token)
# claims.subject, claims.scope, claims.claims["org_id"]
testing.mint_id_token(client_id, ...) bir kimlik belirteci üretir. Anahtar kelime argümanları claims (None değeri bir talep alanını kaldırır), lifetime_seconds ve issued_at'tir. Modülü kullanmadan VerifierConfig içine testing=True geçebilirsiniz.
Varsayılan talep alanları
| Talep | Erişim belirteci | Kimlik belirteci |
|---|---|---|
iss |
https://test.keenauth.invalid |
https://test.keenauth.invalid |
sub |
usr_01m3vnbwg0e8mbe7h7xxp6rmkc |
usr_01m3vnbwg0e8mbe7h7xxp6rmkc |
aud |
geçtiğiniz hedef kitle | geçtiğiniz istemci kimliği |
client_id |
app_01m3vnbwg0fqba5ntanfd63s8n |
— |
iat, exp |
şu an, şu an + 3600 saniye | şu an, şu an + 3600 saniye |
jti |
rastgele | — |
auth_time |
— | iat ile aynı |
Erişim belirteci başlığında typ: at+jwt bulunur (RFC 9068). scope, org_id, permissions, acr, amr veya auth_time gibi API'nizin okuduğu talepleri ekleyin. Kimlik belirteçleri için kodunuz bir nonce kontrol ediyorsa bu talebi ekleyin.
Örnek olaylar
Kit, yaygın olayların örnek yüklerini içerir: user.created, user.updated, user.deleted, session.created, session.revoked, organization.created ve organization_membership.created. Bunlar KeenAuth'un gönderdiği olaylarla aynı zarfı ve şemaları kullanır; varsayılan ince modda çalışırlar: tanımlayıcılar, durum ve değişen alan adları içerir, kişisel veri içermezler. Olay işleyicilerinizi test etmek için bunları kullanın.
- Go:
keenauthtest.Event("user.created")JSON'u döndürür;keenauthtest.EventTypes()türleri listeler. - TypeScript:
sampleEvent("user.created")vesampleEventTypes(). - Python:
testing.sample_event("user.created")vetesting.event_types().
Webhook'ları test etme
Kit, bir payload'ı tıpkı bir KeenAuth webhook teslimi gibi imzalar (Standard Webhooks v1): ham gövdeyi ve webhook-id, webhook-timestamp ve webhook-signature başlıklarını döndürür. İşleyiciniz bunu, üretimde çalışan aynı kod olan SDK'nın webhook doğrulayıcısıyla doğrular. Yalnızca sır farklıdır.
- Herkese açık bir test sırrı. Varsayılan olarak kit, yayımlanmış
KeenAuth offline test kit webhook secret (public, TEST ONLY)etiketinden türetilen sabit biridp_whsec_test sırrıyla imzalar. Bunu herkes hesaplayabilir, bu nedenle gerçek bir uç noktaya asla yapılandırmayın. Testlerde doğrulayıcınızı bu sırla yapılandırın veya yardımcı fonksiyona kendi sırrınızı geçin. - Gerçek teslimle aynı.
webhook-id, olayıniddeğeridir (payload'ta yoksa rastgele birmsg_kimliği) ve aksini ayarlamadığınız sürecewebhook-timestampşu andır. Gövde, geçtiğiniz şekliyle olduğu gibi gönderilir. - Tekrar oynatma ve kurcalama. Handler'ın 5 dakikalık pencere dışındaki teslimleri reddettiğini test etmek için eski bir zaman damgasıyla imzalayın; hatalı imzayı reddettiğini test etmek için imzalamadan sonra gövdeyi değiştirin.
Node
import { Webhook, WebhookVerificationError } from "@keenauth/node/webhooks";
import { sampleEvent, signWebhook, testWebhookSecret } from "@keenauth/node/testing";
const webhook = new Webhook(testWebhookSecret()); // in production: process.env.KEENAUTH_WEBHOOK_SECRET
const delivery = signWebhook(sampleEvent("user.created"));
const event = webhook.verify(delivery.body, delivery.headers); // the parsed event
// A delivery from an hour ago is refused.
const old = signWebhook(sampleEvent("user.created"), { timestamp: Math.floor(Date.now() / 1000) - 3600 });
try {
webhook.verify(old.body, old.headers);
} catch (e) {
// e instanceof WebhookVerificationError, e.kind === "timestamp"
}
signWebhook(payload, options) bir dize, bir Uint8Array veya bir nesne alır (JSON.stringify ile serileştirilir). Seçenekler secret, id ve timestamp'tir (Unix saniyesi veya bir Date). Bir HTTP işleyicisini test etmek için delivery.body değerini ham istek gövdesi olarak, delivery.headers değerini ve Content-Type: application/json başlığını göndərin.
Python
import time
from keenauth import testing
from keenauth.webhooks import WebhookTimestampError, WebhookVerifier
verifier = WebhookVerifier(testing.webhook_secret()) # in production: os.environ["KEENAUTH_WEBHOOK_SECRET"]
delivery = testing.sign_webhook(testing.sample_event("user.created"))
verifier.verify(delivery.body, delivery.headers)
# A delivery from an hour ago is refused.
old = testing.sign_webhook(testing.sample_event("user.created"), timestamp=int(time.time()) - 3600)
try:
verifier.verify(old.body, old.headers)
except WebhookTimestampError:
pass
testing.sign_webhook(payload, secret=None, msg_id=None, timestamp=None) bayt dizisi, dize veya sözlük alır (sıkıştırılmış JSON olarak serileştirilir) ve delivery.body (bayt) ile delivery.headers (sözlük) değerlerini döndürür. Flask veya FastAPI test istemcisiyle delivery.body değerini ham gövde, delivery.headers değerini başlık olarak gönderin.
Go
import (
"net/http"
"net/http/httptest"
"github.com/keenauth/keenauth-go/keenauthtest"
"github.com/keenauth/keenauth-go/webhook"
)
func TestWebhookHandler(t *testing.T) {
v, err := webhook.NewVerifier([]string{keenauthtest.WebhookSecret()}) // in production: os.Getenv("KEENAUTH_WEBHOOK_SECRET")
if err != nil {
t.Fatal(err)
}
body, err := keenauthtest.Event("user.created")
if err != nil {
t.Fatal(err)
}
delivery, err := keenauthtest.SignWebhook(body)
if err != nil {
t.Fatal(err)
}
req, err := delivery.Request("http://localhost/webhooks/keenauth")
if err != nil {
t.Fatal(err)
}
rec := httptest.NewRecorder()
newWebhookHandler(v).ServeHTTP(rec, req) // your handler, which calls v.Verify(r.Header, body)
if rec.Code != http.StatusOK {
t.Fatalf("status %d", rec.Code)
}
}
keenauthtest.SignWebhook(payload, ...) delivery.Body ve delivery.Header değerlerini döndürür; delivery.Request(url) Content-Type: application/json başlığıyla POST isteği oluşturur. Seçenekler WithWebhookSecret, WithWebhookID ve WithWebhookTimestamp'tir.
Kitin yapmadıkları
- KeenAuth'u taklit etmez. Oturum açma akışları, belirteç düzenleme kuralları, hız sınırları ve diğer tüm sunucu davranışları yalnızca barındırılan
developmentortamınızda gerçektir; yayın öncesinde entegrasyon testlerinizi orada çalıştırın. - Test saati yoktur. Zamanı kontrol etmek için doğrulayıcıya kendi saatinizi verin (
Now,now) ve belirtecin düzenlenme zamanını ayarlayın. - DPoP kanıtları oluşturmaz.
cnf.jkttalebi ekleyebilirsiniz, ancak bu durumda kanıtı kendiniz imzalamanız gerekir. - Webhook'ları teslim etmez. Gerçek teslimler, yeniden denemeler ve olay seçimi yalnızca barındırılan
developmentortamınızda gerçektir.