Yerel sahte sunucu

keenauth mock serve, ağ erişimi olmayan CI işleri ve yerel geliştirme için makinenizde küçük bir OpenID Connect, SAML 2.0 ve SCIM 2.0 sunucusu ile /v1 yönetim API'sinin bellek içi sürümünü çalıştırır. KeenAuth ortamı, API anahtarı ya da internet gerekmez. Bütün veri bellektedir ve süreç bitince silinir.

Sahte sunucu KeenAuth değildir. Yalnız aşağıdaki akışları uygular, her isteği kendiliğinden onaylar ve gerçek hizmetten çok daha az şey denetler. Gerçek davranışın tek ölçütü barındırılan development ortamınızdır: yayımlamadan önce uçtan uca testlerinizi ona karşı çalıştırın.

Sunucuyu başlatma

keenauth mock serve

Sunucu varsayılan olarak 127.0.0.1:4010 adresini dinler; bu, başka makinelerin erişemediği bir loopback adresidir. --port portu değiştirir (0 boş bir port seçer). --host adresi değiştirir; loopback dışındaki her adres sahte sunucuyu ağınıza açar ve CLI bir uyarı basar. Sunucuyu Ctrl+C ile durdurun.

Komut kimlik bilgisi okumaz ve KeenAuth'a hiçbir şey göndermez.

Uçlar

Yol Amaç
/.well-known/openid-configuration OIDC keşif belgesi (/.well-known/oauth-authorization-server adresinde de sunulur)
/.well-known/jwks.json Herkese açık test anahtar kümesi (anahtar kimliği keenauth-test-1)
/oauth2/authorize Yetkilendirme ucu: PKCE'li (S256) yetkilendirme kodu akışı
/oauth2/token Token ucu: authorization_code ve refresh_token grant'leri
/oauth2/userinfo UserInfo ucu (openid scope'lu Bearer access token)
/saml-idp/<application_id>/metadata SAML 2.0 kimlik sağlayıcısı meta verisi
/saml-idp/<application_id>/sso SAML tek oturum açma ucu (HTTP-Redirect ve HTTP-POST bağlamaları)
/scim/v2/<directory_id>/… SCIM 2.0 uçları: Users, Groups, ServiceProviderConfig, ResourceTypes, Schemas
/v1/… Bellek içi yönetim API'si: yönetim API'sinin OpenAPI belgesindeki her işlem

Keşif belgesindeki ve SAML meta verisindeki uç URL'leri sunucunun dinlediği yerel adresi gösterir. <application_id> ve <directory_id> sizin seçtiğiniz herhangi bir addır (A-Z, a-z, 0-9, -, _ karakterlerinden 1–64 karakter); önceden bir şey kaydetmek gerekmez.

Nasıl davranır

Token'lar ve doğrulayıcınız

Token'lar çevrim dışı test kitinin herkese açık test anahtarıyla imzalanır ve yerel adresi değil, https://test.keenauth.invalid issuer'ını taşır. .invalid üst alan adı ayrılmıştır; bu yüzden üretim doğrulayıcısı bu token'ları hiçbir zaman kabul edemez: SDK doğrulayıcıları onları yalnız test kodunda açıkça açtığınız test kipinde kabul eder.

// Go: bir testte sahte sunucunun token'larını kabul et.
v, err := keenauthtest.NewVerifier(verify.Config{Audience: "https://test.keenauth.invalid/oauth2/userinfo"})
if err != nil {
	t.Fatal(err)
}
claims, err := v.VerifyAccessToken(ctx, accessToken, nil)

TypeScript'te (createTestVerifier) ve Python'da (keenauth.testing.verifier) aynı test kipini kullanın. Keşif belgesindeki issuer'ın belgenin alındığı URL'ye eşit olmasını isteyen genel OIDC istemci kütüphaneleri sahte sunucunun keşif belgesini reddeder; onları doğrudan uç URL'leriyle yapılandırın ya da development ortamınıza karşı test edin.

Örnek: curl ile bütün akış

Örnek curl, openssl ve jq ister. Önce sunucuyu başka bir terminalde başlatın.

BASE=http://127.0.0.1:4010
REDIRECT=http://127.0.0.1:8080/callback
VERIFIER=$(openssl rand -hex 32)
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')

# 1. Yetkilendirme: sunucu kodu taşıyan bir yönlendirmeyle yanıt verir.
LOCATION=$(curl -s -o /dev/null -w '%{redirect_url}' --get "$BASE/oauth2/authorize" \
  --data-urlencode response_type=code --data-urlencode client_id=app_local \
  --data-urlencode redirect_uri="$REDIRECT" --data-urlencode 'scope=openid email offline_access' \
  --data-urlencode state=xyz --data-urlencode code_challenge="$CHALLENGE" \
  --data-urlencode code_challenge_method=S256)
CODE=$(printf '%s' "$LOCATION" | sed -E 's/.*[?&]code=([^&]+).*/\1/')

# 2. Kodu token'larla değiştir.
TOKENS=$(curl -s "$BASE/oauth2/token" -d grant_type=authorization_code -d client_id=app_local \
  --data-urlencode code="$CODE" --data-urlencode redirect_uri="$REDIRECT" -d code_verifier="$VERIFIER")

# 3. Access token ile UserInfo'yu çağır.
curl -s "$BASE/oauth2/userinfo" -H "Authorization: Bearer $(printf '%s' "$TOKENS" | jq -r .access_token)"

# 4. Refresh.
curl -s "$BASE/oauth2/token" -d grant_type=refresh_token -d client_id=app_local \
  --data-urlencode refresh_token="$(printf '%s' "$TOKENS" | jq -r .refresh_token)"
  1. adım test kullanıcısını basar:
{"email":"test.user@example.test","email_verified":true,"sub":"usr_01m3vnbwg0e8mbe7h7xxp6rmkc"}

SAML kimlik sağlayıcısı

Sahte sunucuyu geliştirdiğiniz bir SAML servis sağlayıcısının kimlik sağlayıcısı olarak kullanın: servis sağlayıcıyı meta veri URL'sine yöneltin, giriş yapın; sahte sunucu test kullanıcısı için imzalı bir yanıt döndürür. Yollar, KeenAuth'un sonraki bir sürüm için planladığı barındırılan SAML kimlik sağlayıcısının yollarını izler.

İmza anahtarı herkese açıktır. Yayımlanmış bir etiketten türetilir; bu yüzden herkes bu sertifikanın doğruladığı yanıtlar imzalayabilir. SHA-256 parmak izi fcc2fc37b9ddb800721283156f9eb26ff1b80f099d996a65650f8cb469a9be81, konusu TEST ONLY ibaresini taşır. Onu servis sağlayıcınızın yalnız geliştirme ve test yapılandırmalarına kaydedin, üretime asla. KeenAuth bunu kendi SAML bağlantıları için uygular: staging ve production ortamlarında bu anahtarı ve .invalid altındaki her entity ID'yi metadata içe aktarırken, sertifika eklerken ve girişte yeniden reddeder; development ortamları kabul eder.

Örnek: curl ile SAML girişi

Örnek curl ve openssl ister. Önce sunucuyu başka bir terminalde başlatın.

BASE=http://127.0.0.1:4010
APP=app_local
ACS=http://127.0.0.1:8080/saml/acs

# 1. IdP meta verisi: servis sağlayıcınız için entity ID, imza sertifikası ve SSO URL'si.
curl -s "$BASE/saml-idp/$APP/metadata" -o idp-metadata.xml

# 2. HTTP-POST bağlamasıyla bir AuthnRequest gönder (base64, sıkıştırmasız).
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
REQUEST=$(printf '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_req1" Version="2.0" IssueInstant="%s" AssertionConsumerServiceURL="%s"><saml:Issuer>https://sp.example.com</saml:Issuer></samlp:AuthnRequest>' "$NOW" "$ACS" | openssl base64 -A)
curl -s "$BASE/saml-idp/$APP/sso" --data-urlencode SAMLRequest="$REQUEST" --data-urlencode RelayState=xyz -o form.html

# 3. Sayfa SAMLResponse'u ACS URL'sine kendisi gönderir; imzalı yanıtı görmek için çöz.
sed -n 's/.*name="SAMLResponse" value="\([^"]*\)".*/\1/p' form.html | openssl base64 -d -A > response.xml
grep -o 'InResponseTo="[^"]*"' response.xml | head -1

Son komut InResponseTo="_req1" yazar. Servis sağlayıcınız response.xml'i idp-metadata.xml'deki sertifikaya göre doğrular.

SCIM 2.0 uçları

SCIM uçlarıyla bir SCIM istemcisini (provizyon bağlayıcısı ya da kullanıcı ve grup oluşturan bir betik) ağsız sınayın. Her <directory_id>, süreç yaşadıkça duran ayrı ve boş bir dizindir.

Örnek: curl ile kullanıcı provizyonu

Örnek curl ve jq ister. Önce sunucuyu başka bir terminalde başlatın.

SCIM=http://127.0.0.1:4010/scim/v2/dir_local
AUTH='Authorization: Bearer keenauth-mock-scim-token'
CT='Content-Type: application/scim+json'

# 1. Kullanıcı oluştur; yanıt id'yi, meta.version'ı ve ETag başlığını taşır.
USER_ID=$(curl -s "$SCIM/Users" -H "$AUTH" -H "$CT" -d '{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "userName": "ada@example.test",
  "name": {"givenName": "Ada", "familyName": "Lovelace"},
  "emails": [{"value": "ada@example.test", "type": "work", "primary": true}]
}' | jq -r .id)

# 2. Filtreyle bul.
curl -s -G "$SCIM/Users" -H "$AUTH" --data-urlencode 'filter=userName eq "ada@example.test"' | jq .totalResults

# 3. Okuduğun sürüme bağlı PATCH ile pasifleştir.
curl -s -X PATCH "$SCIM/Users/$USER_ID" -H "$AUTH" -H "$CT" -H 'If-Match: W/"1"' -d '{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [{"op": "replace", "path": "active", "value": false}]
}' | jq -c '{active, version: .meta.version}'

# 4. Kullanıcıyı üye yapan bir grup oluştur, sonra kullanıcıyı sil.
curl -s "$SCIM/Groups" -H "$AUTH" -H "$CT" -d '{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "displayName": "Engineering",
  "members": [{"value": "'"$USER_ID"'"}]
}' | jq -c '.members[0] | {display, type}'
curl -s -o /dev/null -w '%{http_code}\n' -X DELETE "$SCIM/Users/$USER_ID" -H "$AUTH"

Komutlar 1, {"active":false,"version":"W/\"2\""}, {"display":"ada@example.test","type":"User"} ve 204 yazar.

Yönetim API'si (/v1)

KeenAuth yönetim API'sini çağıran kodu (bir SDK, CLI, bir dağıtım betiği) ağ olmadan CI'da sınamak için yönetim API'si uçlarını kullanın. Yollar barındırılan ortamla aynıdır: barındırılan taban URL yerine http://127.0.0.1:4010/v1 kullanın, başka bir şey değişmez. Uçlar CLI'ya gömülü yönetim API'si OpenAPI belgesinden üretilir; yani o sürümdeki API'nin her işlemi yanıt verir.

development ortamından farkı. Sahte sunucu yalnız gövdenin zorunlu alanları olan bir JSON nesnesi olduğunu denetler; alan biçimleri, uzunluklar, sabit listeler ve tekillik denetlenmez, türü yanlış alan yok sayılır. If-Match, Idempotency-Key ve diğer başlıkları yok sayar, ETag döndürmez. İzin, plan sınırı, kota, hız sınırı ve bölgeyi denetlemez, kişisel veriyi maskelemez, e-posta göndermez, iş çalıştırmaz (kabul edilen iş oluşturulduğu gibi kalır) ve tek ortamı vardır. Kayıtlar yalnız sürecin ömrü boyunca vardır, en çok 10.000 tane. Gerçek API'nin nasıl davrandığını öğrenmek için development ortamınızı kullanın.

Örnek: curl ile oluştur, oku, değiştir, sil

Örnek curl ve jq ister. Önce sunucuyu başka bir terminalde başlatın.

API=http://127.0.0.1:4010/v1
AUTH='Authorization: Bearer keenauth-mock-management-token'
CT='Content-Type: application/json'

# 1. Bir kuruluş oluştur.
ORG_ID=$(curl -s "$API/organizations" -H "$AUTH" -H "$CT" -d '{"name": "Acme"}' | jq -r .id)

# 2. Geri oku ve listele.
curl -s "$API/organizations/$ORG_ID" -H "$AUTH" | jq -c '{id: (.id | .[0:4]), name}'
curl -s "$API/organizations" -H "$AUTH" | jq -c '{count: (.data | length), list_metadata}'

# 3. Birleştirme yamasıyla adını değiştir.
curl -s -X PATCH "$API/organizations/$ORG_ID" -H "$AUTH" -H 'Content-Type: application/merge-patch+json' -d '{"name": "Acme Inc"}' | jq -r .name

# 4. Sil; ikinci okuma 404 problemidir.
curl -s -o /dev/null -w '%{http_code}\n' -X DELETE "$API/organizations/$ORG_ID" -H "$AUTH"
curl -s "$API/organizations/$ORG_ID" -H "$AUTH" | jq -c '{status, code}'

# 5. Token'sız.
curl -s "$API/organizations" | jq -c '{status, code}'

Komutlar {"id":"org_","name":"Acme"}, {"count":1,"list_metadata":{"after":null,"before":null}}, Acme Inc, 204, {"status":404,"code":"not_found"} ve {"status":401,"code":"unauthenticated"} yazdırır.

Desteklenmeyenler

Test saati, DPoP, PAR, istek nesneleri, cihaz akışı, client credentials, token exchange, oturum kapatma ve iptal ile barındırılan sayfalar yoktur. SAML kimlik sağlayıcısında tek oturum kapatma, şifreli assertion, artifact bağlaması ve IdP tarafından başlatılan giriş yoktur. SCIM uçlarında toplu işlem, sıralama, /Me ve iç içe grup yoktur; filtrede or, not, parantez ve gt/ge/lt/le yoktur. Bunları development ortamınızda test edin.