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
- Onay ekranı ve giriş sayfası yok. Geçerli her yetkilendirme isteği sabit, kurgusal bir test kullanıcısı için hemen onaylanır ve
code,stateveissile geri yönlendirilir. Kullanıcınınsubdeğeriusr_01m3vnbwg0e8mbe7h7xxp6rmkc, e-posta adresitest.user@example.test(doğrulanmış), adıTest User'dır. - Kayıtlı istemci yok. Her
client_idkabul edilir. İstemci sırları denetlenmez.redirect_urimutlak birhttpsURI'si ya da loopback host'ta (127.0.0.1,[::1],localhost) birhttpURI'si olmalı ve parça (fragment) taşımamalıdır; geçersizredirect_uriya da eksikclient_idyönlendirme yerine hata sayfası alır. - PKCE zorunludur.
code_challenge_method=S256ilecode_challengegönderilmelidir;plainreddedilir. Token isteği eşleşencode_verifier'ı göndermelidir. - Kodlar tek kullanımlıktır ve 60 saniyede sona erer. Bir kodu ikinci kez sunmak
invalid_grantile başarısız olur ve o koddan verilen bütün token'ları iptal eder. - Token'lar. Access token bir saat geçerli bir RFC 9068 JWT'sidir (
typat+jwt);sub,client_id,scopeve rastgele birjtitaşır. Hedef kitlesi yetkilendirme isteğindekiresourceparametresi, gönderilmediysehttps://test.keenauth.invalid/oauth2/userinfo'dur.openidscope'uyla bir ID token da alırsınız (nonceveauth_timeile;emailveprofilescope'larıylaemailvenameclaim'leri).offline_accessile refresh token alırsınız. - Refresh token'lar döner. Her refresh yeni bir refresh token döndürür; eskisini sunmak başarısız olur ve bütün zinciri iptal eder. Refresh scope'u daraltabilir, genişletemez.
- UserInfo yalnız bu sürecin verdiği, süresi geçmemiş ya da iptal edilmemiş ve
openidscope'u taşıyan access token'ları kabul eder.
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)"
- 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.
- Meta veri.
GET /saml-idp/<application_id>/metadata; entity ID'sihttps://test.keenauth.invalid/saml-idp/<application_id>olan, imza sertifikasını,persistentveemailAddressNameID biçimlerini ve iki bağlamanın SSO ucunu taşıyan birEntityDescriptordöndürür. İmzalı AuthnRequest istenmez (WantAuthnRequestsSigned="false"); istekteki imza yok sayılır. - SSO. AuthnRequest'i HTTP-Redirect bağlamasıyla (
GET,SAMLRequestiçinde DEFLATE + base64) ya da HTTP-POST bağlamasıyla (POST, base64) gönderin. Giriş sayfası yoktur: geçerli istek test kullanıcısı için hemen onaylanır veSAMLResponse'u (ve en çok 80 bayt olanRelayState'inizi) servis sağlayıcının ACS URL'sine kendiliğinden gönderen bir HTML sayfası alırsınız. - AuthnRequest şunları taşımalıdır:
ID,Version="2.0",IssueInstant, birsaml:Issuer(servis sağlayıcınızın entity ID'si) veAssertionConsumerServiceURL; sahte sunucuda kayıtlı servis sağlayıcı yoktur. ACS URL'si mutlak birhttpsURL'si ya da loopback host'ta birhttpURL'si olmalı ve parça taşımamalıdır.ProtocolBindingvarsa HTTP-POST,Destinationvarsa SSO URL'si olmalıdır. Başka her istek400alır ve hiçbir yere gönderilmez. DTD reddedilir. - Yanıt RSA-SHA256 ve exclusive kanonikleştirme ile iki kez imzalanır: önce assertion, sonra bütün yanıt.
InResponseToisteğinizinID'si,Destinationve özne onayınınRecipient'ı ACS URL'si,AudienceisteğinizinIssuer'ıdır; assertion verildiği andan başlayarak 5 dakika geçerlidir. NameID, istekemailAddressistemedikçepersistent'tir (uygulama başına sabit bir değer). Öznitelikleremail,given_name,family_namevename'dir.
İ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.
- Kimlik doğrulama. Her istek
Authorization: Bearer keenauth-mock-scim-tokenister. Başka her şeyWWW-Authenticate: Bearermeydan okumasıyla401alır. Değer sabit ve herkese açıktır; bir KeenAuth SCIM token'ı değildir. - Kullanıcılar ve gruplar.
/Usersve/GroupsüzerindePOST,GET,PUT,PATCHveDELETE(RFC 7644).userNameve grubundisplayName'i zorunludur ve dizinde büyük/küçük harf gözetmeden tekildir; tekraruniquenessscimType'ıyla409alır. Grup üyeleri aynı dizinin kullanıcıları olmalıdır. Kullanıcı silinince gruplarından çıkar.passwordkabul edilir ve atılır. - Filtre ve sayfalar.
filter,andile bağlanmışeq,ne,co,sw,ewveprişleçlerini destekler (örneğinuserName eq "ada@example.test"); ayrıcastartIndexvecount(en çok 200).attributesveexcludedAttributesüst düzey öznitelikleri seçer.POST /Users/.searchve/Groups/.searchaynı parametreleri gövdede alır. - PATCH
add,removevereplaceişlemleriniactive,name.givenName,emails[type eq "work"].value,members[value eq "<id>"]gibi yollarla ve enterprise uzantısı öznitelikleriyle destekler; bir isteğin işlemleri ya hep birlikte uygulanır ya hiç. - Sürümler. Her kaynak
meta.versionve birETagbaşlığı taşır (W/"1",W/"2", …).PUT,PATCHveDELETE'teIf-Match, sürüm değiştiyse412;GET'teIf-None-Match304döndürür. - Keşif.
ServiceProviderConfig,ResourceTypesveSchemastam olarak bu davranışı anlatır./Bulkve/Me, KeenAuth'ta olduğu gibi501döndürür.
Ö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.
- Kimlik doğrulama. Her istek
Authorization: Bearer keenauth-mock-management-tokenister. Başka her şey, bilinmeyen yollar dahil,WWW-Authenticate: Bearerbaşlığıyla401alır. Değer sabit ve herkese açıktır; bir KeenAuth yönetim anahtarı değildir. - Yanıtlar. Her işlem belgenin bildirdiği başarı durumuyla (
200,201,202,204; iki indirme ucu, çözümlenmeyen birLocationile302) yanıt verir. Gövde, belgedeki başarı yanıtınınexampledeğeridir; henüz hiç yoksa yanıt şemasından kurulan en küçük geçerli örnektir: yalnız zorunlu alanlar, boş olabilen alanlarnull, sabit listeler ilk değerleriyle,pattern'ine uyan dizeler. - Basit durum. Kayıt oluşturulabilen bir koleksiyon (
POST /v1/users,/v1/organizations,/v1/applications,/v1/organizations/<org_id>/roles, …) kayıtları tutar: oluşturduğunuz kayıt kendi yolundakiGETve listede görünür,PATCHvePUTonu değiştirir,DELETEonu ve altındaki her şeyi siler, olmayan bir kaydın altındaki yol404döner. Kimlikler KeenAuth önek biçimindedir (usr_…,org_…,app_…) ve belgedeki desene uyar; belge desen vermiyorsa önek parametre adından türetilir. Ortam başına tek olan ayarlar (örneğin/v1/identity-settings)PATCHya daPUTile yazdığınızı tutar. API ile oluşturulamayan kaynaklar (örneğin oturumlar ve raporlar) hep örnekle yanıt verir. - Listeler.
limit(1–100, varsayılan 20), imleç olarak kayıt kimliğiyleafterya dabeforeveorder(varsayılandesc, en yeni önce) çalışır; yanıtlist_metadatataşır.statusgibi süzgeçler uygulanmaz. - Hatalar belgedeki gibi
application/problem+json'dır;codeve aynı zamandaIdp-Request-Idbaşlığında bulunan birrequest_idtaşır. Bilinmeyen yol404 not_found, yolda olmayan metotAllowbaşlıklı405 method_not_allowed, geçerli JSON olmayan (ya da nesne olmayan) gövde400 malformed_request, JSON dışıContent-Typebunu bildiren işlemlerde415, eksik zorunlu alanerrors[]ile422 validation_failed, 1 MiB'tan büyük gövde413, hatalılimitya da imleç400döner.
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.