Ana içeriğe geç

Kimlik beyanı

Makine çevirisi

Bu sayfa İngilizce dokümantasyondan otomatik olarak çevrildi; esas alınması gereken sürüm İngilizce sayfadır. Yanlış görünen bir şey varsa, nasıl bildireceğinizi Çeviriler sayfası açıklar.

Sıradan bir OAuth sağlayıcısı (OAuth istemcileri) işe MCP sunucusuna bir soru sorarak başlar: hangi yetkilendirme sunucusuna güveniyorsun? Yanıt nereyi gösteriyorsa oraya gider; ardından ya bir kişi oturum açar ya da önceden paylaşılmış bir gizli anahtar onun yerini tutar.

Bir kurum ise bunların hiçbirinin sunucu başına kararlaştırılmasını istemez. Zaten bir kimlik sağlayıcısı işletir (Okta, Microsoft Entra ID, kendi yazdığınız); kullanıcı ona bu sabah zaten oturum açmıştır ve güvenlik ekibinin kimin neye erişebileceğine karar vermek istediği tek yer orasıdır. Enterprise-Managed Authorization uzantısı olan SEP-990, kararı oraya taşır. IdP kısa ömürlü bir JWT imzalar: bir Identity Assertion JWT Authorization Grant, kısaca ID-JAG. Bu, şu kullanıcının, şu istemci aracılığıyla şu MCP sunucusuna erişebileceğini söyleyen bir beyandır. İstemci onu sıradan bir erişim token'ıyla takas eder. Tarayıcı yok, onay ekranı yok, dinamik kayıt yok.

Bu sayfa o takasın iki ucunu da anlatır. MCP sunucusunun kendisi hiç değişmez: hâlâ Yetkilendirme sayfasındaki kaynak sunucusudur ve önüne hangi token gelirse onu denetler.

İki token isteği

İşin içinde iki farklı otorite var ve bu sayfayı anlamanın büyük kısmı ikisini ayrı adlarla anmaktan geçer. Kurumsal IdP, kuruluşunuzun kimlik sağlayıcısıdır: çalışanın kim olduğunu bilir, politikanın bulunduğu yerdir ve ID-JAG'i o düzenler. SDK onunla hiç konuşmaz. MCP yetkilendirme sunucusu ise Yetkilendirme sayfasındaki aynı taraftır: MCP sunucusunun meta verisinde adı geçen issuer, o MCP sunucusunun kabul ettiği token'ları basan şey. Sıradan bir OAuth akışında bu iki rol genellikle tek bir kutudur. Burada iki ayrı kutudur ve grant'in tamamı, ikincisinin birincisine güvenmeyi kabul etmesinden ibarettir.

İstemci her birine birer token isteği gönderir.

  1. Kurumsal IdP'ye. İstemci, kullanıcının oturum açma bilgisini (OpenID Connect ID token'ını) ID-JAG ile takas eder. Bu bir RFC 8693 token takasıdır, tamamen IdP'nizin API'sidir ve bu isteği SDK yapmaz. Siz yaparsınız, tek bir asenkron callback'in içinde. Politika kararı da burada verilir: hayır diyen bir IdP ID-JAG'i hiç düzenlemez ve ortada sunulacak bir şey kalmaz.
  2. MCP yetkilendirme sunucusuna. İstemci ID-JAG'i RFC 7523 jwt-bearer grant'i kapsamında sunar (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, ID-JAG de assertion olarak) ve erişim token'ını alır. SDK'nın yaptığı istek budur ve bu sayfanın bir yetkilendirme sunucusuna eklediği tek şey de onu kabul etmektir.

Aşağıdaki her şey ikinci istekle ilgilidir: onu gönderen istemci ve yanıtlayan yetkilendirme sunucusu.

İstemci

IdentityAssertionOAuthProvider, mcp.client.auth.extensions.identity_assertion modülünde bulunur. OAuth istemcileri sayfasındaki her sağlayıcı gibi o da bir httpx2.Auth nesnesidir: bir tane oluşturun, auth= parametresine verin, httpx2.AsyncClient'ı aktarıma teslim edin.

client.py
import time
import uuid

import httpx2
import jwt

from mcp import Client
from mcp.client.auth.extensions.identity_assertion import IdentityAssertionOAuthProvider
from mcp.client.streamable_http import streamable_http_client
from mcp.shared.auth import OAuthClientInformationFull, OAuthToken

IDP_SIGNING_KEY = "the-enterprise-idp-signing-key-for-this-demo"


class InMemoryTokenStorage:
    def __init__(self) -> None:
        self.tokens: OAuthToken | None = None
        self.client_info: OAuthClientInformationFull | None = None

    async def get_tokens(self) -> OAuthToken | None:
        return self.tokens

    async def set_tokens(self, tokens: OAuthToken) -> None:
        self.tokens = tokens

    async def get_client_info(self) -> OAuthClientInformationFull | None:
        return self.client_info

    async def set_client_info(self, client_info: OAuthClientInformationFull) -> None:
        self.client_info = client_info


def idp_issue_id_jag(subject: str, audience: str, resource: str) -> str:
    now = int(time.time())
    claims = {
        "iss": "https://idp.example.com",
        "sub": subject,
        "aud": audience,
        "client_id": "finance-agent",
        "resource": resource,
        "scope": "notes:read",
        "jti": str(uuid.uuid4()),
        "iat": now,
        "exp": now + 300,
    }
    return jwt.encode(claims, IDP_SIGNING_KEY, algorithm="HS256", headers={"typ": "oauth-id-jag+jwt"})


async def fetch_id_jag(audience: str, resource: str) -> str:
    return idp_issue_id_jag("alice@example.com", audience, resource)


oauth = IdentityAssertionOAuthProvider(
    server_url="http://localhost:8001/mcp",
    storage=InMemoryTokenStorage(),
    client_id="finance-agent",
    client_secret="finance-agent-secret",
    issuer="https://auth.example.com/",
    assertion_provider=fetch_id_jag,
    scope="notes:read",
)


async def main() -> None:
    async with httpx2.AsyncClient(auth=oauth, follow_redirects=True) as http_client:
        transport = streamable_http_client("http://localhost:8001/mcp", http_client=http_client)
        async with Client(transport) as client:
            result = await client.list_tools()
            print([tool.name for tool in result.tools])

Aşağıdan yukarıya okuyun.

  • main(), standart OAuth istemcisi main()'idir (OAuth istemcileri), satırı satırına aynı. Mesele de bu: sağlayıcı bir kez var olduktan sonra, akışın devamındaki hiçbir şey token'ı hangi grant'in ürettiğini bilmez.
  • Sağlayıcı, diğer sağlayıcıların keşfedemeyeceği şeyleri alır: birinin yetkilendirme sunucusuna önceden kaydettirdiği bir client_id ve client_secret, o yetkilendirme sunucusunun issuer'ı ve assertion_provider, yani istendiğinde taze bir ID-JAG döndüren asenkron bir callback.
  • storage aynı TokenStorage protokolüdür. Yalnızca iki token metodu çağrılır; burada dinamik kayıt olmadığından hatırlanacak bir client_info da yoktur.

Beyan sağlayıcı

Yazdığınız tek kod fetch_id_jag(audience, resource) fonksiyonudur. Her token takasında bir kez await edilir; oluşturma sırasında asla, ve ancak yetkilendirme sunucusunun meta verisi alınıp doğrulandıktan sonra. Böylece yanlış yapılandırılmış bir issuer hiçbir zaman bir beyan sızdırmaz. İki argümanı, ID-JAG'in basılırken taşıması gereken claim'lerden ikisidir: audience yetkilendirme sunucusunun issuer'ıdır (ID-JAG'deki aud), resource ise MCP sunucusunun kanonik tanımlayıcısıdır (ID-JAG'deki resource). Üçüncüsü zaten elinizde: ID-JAG'in client_id claim'i, sağlayıcıya verdiğiniz client_id'yi göstermelidir; yoksa yetkilendirme sunucusu takası reddeder.

Onun üstündeki idp_issue_id_jag sizin kodunuz değildir. Kimlik sağlayıcısının yerini tutar; dosya eksiksiz olsun ve bir ID-JAG'in taşıdığı her claim'i okuyabilesiniz diye beyanı süreç içinde imzalar. Gerçek bir fetch_id_jag ise bunun yerine önceki bölümdeki ilk token isteğini yapar: IdP'nize karşı bir RFC 8693 token takası. Bu takası, SEP-990 belgesinin profil olarak daralttığı Identity Assertion JWT Authorization Grant taslağı tanımlar. Oturum açmış kullanıcının ID token'ı subject_token olarak girer, requested_token_type ID-JAG'in kendi URN'idir (urn:ietf:params:oauth:token-type:id-jag), audience ve resource olduğu gibi aktarılır ve yanıt ID-JAG'i taşır. IdP'nizin belgelerinde aramanız gereken şey, bu adlarla anılan bu takastır.

Tip

Her takas için taze bir ID-JAG istenir ve amaç da budur: tek kullanımlık, ömrü dakikalarla ölçülen bir grant'tir ve bu sayfadaki yetkilendirme sunucusu aynısını ikinci kez kabul etmez. Onu önbelleğe almayın. Yeniden kullanılan şey, size kazandırdığı erişim token'ıdır.

Yapılandırma olarak issuer

Tersine çevirme işte burada. OAuthClientProvider, kaynak sunucusuna hangi yetkilendirme sunucusunu kullanacağını sorar ve yanıt nereyi gösteriyorsa oraya gider. Bu sağlayıcı bunu reddeder: issuer zorunludur, RFC 8414 meta verisi o issuer'ın kendi well-known yolundan alınır, token endpoint'i o issuer'ın origin'inde olmalıdır ve kaynak sunucusuna hiçbir şey sorulmaz.

Uzantı bunu şart koşmaz; bu, bilerek yapılmış daha katı bir tercihtir. Bu istemci çalınmaya değer iki şey taşır: önceden kaydedilmiş bir gizli anahtar ve audience'a bağlı bir beyan. Ele geçirilmiş bir MCP sunucusunun kendisini saldırganın yetkilendirme sunucusuna yönlendirmesine izin veren bir istemci, ikisini de oraya gönderirdi. Oluşturma sırasında issuer'ı sabitlemek bu konuşmayı ortadan kaldırır.

Warning

Yapılandırılan issuer, meta veri belgesinin issuer alanıyla RFC 8414 §3.3'teki basit dize karşılaştırmasıyla karşılaştırılır: karakter karakter, sondaki eğik çizgi dahil, normalleştirme olmadan. Tahmin etmeyin. Yetkilendirme sunucunuzdan /.well-known/oauth-authorization-server belgesini alın ve döndürdüğü issuer değerini kopyalayın. Bu sayfadaki yetkilendirme sunucusu için bu değer, eğik çizgisiyle birlikte https://auth.example.com/ adresidir; çünkü issuer'ı bir pydantic URL nesnesinden oluşturulmuştur. Bir uyuşmazlık, tek bir kimlik bilgisi ya da beyan gönderilmeden akışı OAuthFlowError: Authorization server metadata issuer mismatch hatasında durdurur.

Gizli istemci

client_secret zorunludur; yapıcı onsuz ValueError fırlatır. SEP-990 belgesinin dayandığı IETF profili bu grant'i gizli istemcilere ayırır, SEP-990 istemcinin kimliğini doğrulamasını şart koşar ve bu SDK, paylaşılan bir gizli anahtarda ısrar ederek ikisini de uygular. token_endpoint_auth_method, anahtarın nereden gideceğini seçer: client_secret_post (varsayılan, form gövdesinde) veya client_secret_basic (bir HTTP Basic başlığı). Profil private_key_jwt yöntemine de izin verir; bu sağlayıcı onu desteklemez.

Tip

client_secret'ı ortam değişkenlerinden veya bir gizli anahtar yöneticisinden okuyun, asla kaynak kod deposundan değil.

Sağlayıcının sizin için yaptıkları

İlk istek kimlik doğrulaması olmadan gider ve sunucunun 401 yanıtı akışı başlatır.

  1. Keşif. Yetkilendirme sunucusu meta verisini yapılandırılan issuer'ın RFC 8414 well-known yolundan alır, belgenin issuer alanının eşleştiğini denetler ve token endpoint'inin issuer'ın origin'inde olduğunu denetler.
  2. Beyan. assertion_provider'ınızı await eder.
  3. Takas. jwt-bearer grant'ini token endpoint'ine POST eder, OAuthToken'ı saklar ve özgün isteğinizi Authorization: Bearer ... ile yeniden gönderir.

WWW-Authenticate başlığında insufficient_scope geçen bir 403, 2. ve 3. adımları sizin scope'unuz ile yanıtın istediği kapsamın birleşimiyle yeniden çalıştırır. (scope yalnızca bir istektir; bu sayfadaki yetkilendirme sunucusu ID-JAG ne diyorsa onu verir, başka bir şey değil.) Bunun hiçbir yerinde yenileme token'ı yoktur: erişim token'ının süresi dolduğunda bir sonraki 401 taze bir ID-JAG bastırır ve takas yeniden yapılır; IdP'nin elinde tuttuğu kaldıraç işte budur. Hatalar, OAuth istemcileri sayfasının geri kalanındaki aynı iki istisnadır: keşif ve doğrulama için OAuthFlowError, token endpoint'i hayır dediğinde onun alt sınıfı OAuthTokenError.

Yetkilendirme sunucusu

Çoğu zaman burada durursunuz. MCP yetkilendirme sunucusu başkasının ürünüdür, ID-JAG kabul etmek o ürünün açılacak bir yapılandırmasıdır ve SDK'nın SEP-990 içindeki payı yukarıdaki istemcidir.

SDK yetkilendirme sunucusunun kendisi de olabilir: create_auth_routes, yetkilendirme sunucusunun route'larını herhangi bir Starlette uygulamasının bağlayabileceği bir liste olarak döndürür; depodaki examples/servers/simple-auth/ da bir tanesini böyle çalıştırır. SEP-990 bu yüzeye bir bayrak ve bir metot ekler:

auth_server.py
import secrets
import time

import jwt
from pydantic import AnyHttpUrl
from starlette.applications import Starlette

from mcp.server.auth.provider import (
    AccessToken,
    AuthorizationCode,
    AuthorizationParams,
    AuthorizeError,
    IdentityAssertionParams,
    OAuthAuthorizationServerProvider,
    RefreshToken,
    TokenError,
)
from mcp.server.auth.routes import create_auth_routes
from mcp.shared.auth import JWT_BEARER_GRANT_TYPE, OAuthClientInformationFull, OAuthToken

ISSUER = "https://auth.example.com/"
MCP_SERVER = "http://localhost:8001/mcp"
IDP_ISSUER = "https://idp.example.com"
IDP_SIGNING_KEY = "the-enterprise-idp-signing-key-for-this-demo"

REGISTERED_CLIENTS = {
    "finance-agent": OAuthClientInformationFull(
        client_id="finance-agent",
        client_secret="finance-agent-secret",
        redirect_uris=None,
        grant_types=[JWT_BEARER_GRANT_TYPE],
        token_endpoint_auth_method="client_secret_post",
    )
}


class EnterpriseAuthorizationServer(OAuthAuthorizationServerProvider[AuthorizationCode, RefreshToken, AccessToken]):
    def __init__(self) -> None:
        self.access_tokens: dict[str, AccessToken] = {}
        self.seen_jtis: set[str] = set()

    async def get_client(self, client_id: str) -> OAuthClientInformationFull | None:
        return REGISTERED_CLIENTS.get(client_id)

    async def load_access_token(self, token: str) -> AccessToken | None:
        return self.access_tokens.get(token)

    async def exchange_identity_assertion(
        self, client: OAuthClientInformationFull, params: IdentityAssertionParams
    ) -> OAuthToken:
        try:
            header = jwt.get_unverified_header(params.assertion)
            claims = jwt.decode(
                params.assertion,
                IDP_SIGNING_KEY,
                algorithms=["HS256"],
                issuer=IDP_ISSUER,
                audience=ISSUER,
                options={"require": ["iss", "sub", "aud", "exp", "iat", "jti", "client_id", "resource", "scope"]},
            )
        except jwt.InvalidTokenError as error:
            raise TokenError("invalid_grant", "the assertion did not verify") from error
        if header.get("typ") != "oauth-id-jag+jwt":
            raise TokenError("invalid_grant", "the assertion is not an ID-JAG")
        if claims["client_id"] != client.client_id:
            raise TokenError("invalid_grant", "the assertion was issued to a different client")
        if claims["resource"] != MCP_SERVER:
            raise TokenError("invalid_target", "the assertion is for a resource this server does not serve")
        if claims["jti"] in self.seen_jtis:
            raise TokenError("invalid_grant", "the assertion has already been used")
        self.seen_jtis.add(claims["jti"])
        scopes = claims["scope"].split()
        access_token = f"mcp_{secrets.token_hex(16)}"
        self.access_tokens[access_token] = AccessToken(
            token=access_token,
            client_id=claims["client_id"],
            scopes=scopes,
            expires_at=int(time.time()) + 300,
            resource=claims["resource"],
            subject=claims["sub"],
        )
        return OAuthToken(access_token=access_token, token_type="Bearer", expires_in=300, scope=" ".join(scopes))

    async def authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str:
        raise AuthorizeError("unauthorized_client", "this authorization server only accepts ID-JAGs")

    async def load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> None:
        return None

    async def exchange_authorization_code(
        self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode
    ) -> OAuthToken:
        raise TokenError("invalid_grant", "this authorization server only accepts ID-JAGs")

    async def load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> None:
        return None

    async def exchange_refresh_token(
        self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]
    ) -> OAuthToken:
        raise TokenError("invalid_grant", "this authorization server only accepts ID-JAGs")


provider = EnterpriseAuthorizationServer()
auth_app = Starlette(
    routes=create_auth_routes(provider, issuer_url=AnyHttpUrl(ISSUER), identity_assertion_enabled=True)
)
  • identity_assertion_enabled=True her şeyin kapısıdır. Kapalıyken (varsayılan budur) /token, hook'u uygulamış olsanız bile bu grant'e unsupported_grant_type ile yanıt verir ve meta veri ondan söz etmez. Açıkken meta veri jwt-bearer grant türünü kazanır ve uzantının desteği duyurmak için kullandığı alan olan authorization_grant_profiles_supported içinde urn:ietf:params:oauth:grant-profile:id-jag değerini listeler. (Bu SDK'nın istemcisi onu hiç okumaz: tek bir issuer için hazırlanmıştır ve doğrudan sorar.)
  • exchange_identity_assertion hook'un kendisidir. O çalışmadan önce SDK istemcinin kimliğini doğrulamış, açık (public) istemcileri reddetmiş ve kaydında bu grant'in listelenmediği istemcileri reddetmiştir. Size bir IdentityAssertionParams gelir (ham assertion, istenen scopes ve resource) ve düz bir OAuthToken döndürürsünüz.
  • Dinamik istemci kaydı bu grant'i koşulsuz reddeder; bu yüzden buradaki get_client elle hazırlanmış bir istemci sunar. Bir ID-JAG istemcisi kendi kendini kaydederek var olamaz.
  • Sınıfın yarısı retlerden oluşur. OAuthAuthorizationServerProvider yetkilendirme sunucusunun tamamıdır, bu yüzden yetkilendirme kodu akışını da ister; kullanıcılara oturum da açtıran bir sunucu onları gerçekten uygular, bunun ise tam olarak tek bir kapısı var.

Warning

SDK beyanın kodunu hiçbir zaman çözmez: hangi IdP'ye güvendiğini ve o IdP'nin hangi anahtarları yayımladığını yalnızca sizin dağıtımınız bilir; bu yüzden exchange_identity_assertion içindeki her şey yük taşır. İmzayı IdP'nin yayımladığı anahtarlara karşı (JWKS'i; buradaki paylaşılan gizli anahtar demoya aittir), iss ve exp değerlerini de RFC 7523 §3 uyarınca doğrulayın. JWT başlığındaki typ değerinin oauth-id-jag+jwt olmasını şart koşun; bu, profilin başka bir JWT'nin grant olarak yeniden oynatılmasına karşı koyduğu korumadır. aud değerinin kendi issuer'ınız olmasını şart koşun. ID-JAG'in client_id claim'inin işleyicinin kimliğini doğruladığı istemciye eşit olmasını, resource claim'inin de gerçekten sunduğunuz bir kaynağı göstermesini şart koşun. Beyan yalnızca bir kez kabul edilsin diye jti değerini beyanın exp süresine kadar takip edin. Verilen kapsamları ve her şeyden önce düzenlenen token'ın resource değerini istekten değil, doğrulanmış ID-JAG'den alın: params.resource istemci ne yazdıysa odur. İşleme kurallarının tamamı Enterprise-Managed Authorization spesifikasyonunda yer alır.

Kötü bir beyanı TokenError("invalid_grant", ...) ile reddedin. Bu akıştaki diğer hata kodu invalid_target'tır: sunmadığınız bir kaynağı gösteren bir ID-JAG onunla reddedilir; bu sunucunun başkasının kaynağı için token basmasını engelleyen de budur. Verilen kapsamlar ise ID-JAG'in scope claim'inden gelir (bu claim'i olmayan bir beyan da reddedilir); sizinki bunun yerine kullanıcının gruplarını eşleyebilir.

Döndürülen OAuthToken'ın ne taşımadığına da dikkat edin: bir yenileme token'ı. IdP, bir sonraki ID-JAG'i düzenleyip düzenlemeyeceğine karar vererek bu kullanıcının erişimi ne kadar süre koruyacağına karar verir. Burada basılacak bir yenileme token'ı o kararı sessizce geri teslim ederdi.

Info

Yetkilendirme sunucusunu hâlâ auth_server_provider= ile içine gömen bir sunucu, aynı koda AuthSettings(identity_assertion_enabled=True) üzerinden ulaşır. Yeni sunucuların neden oradan başlamaması gerektiğini Yetkilendirme sayfası açıklar.

Check

Bu sayfadaki iki dosyayı birbirine bağlayın; grant'in tamamı tek bir POST /token olur:

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=eyJhbGciOiJIUzI1NiIsInR5cCI6Im9hdXRoLWlkLWphZytqd3QifQ...
client_id=finance-agent
resource=http://localhost:8001/mcp
scope=notes:read
client_secret=finance-agent-secret

HTTP/1.1 200 OK
{"access_token": "mcp_...", "token_type": "Bearer", "expires_in": 300, "scope": "notes:read"}

/authorize yok, /register yok, korumalı kaynak meta verisi isteği yok. Ağ üzerindeki tek istekler 401'i çeken istek, well-known isteği, bu takas ve ardından bearer eklenmiş sıradan MCP trafiğidir. Doğrulayıcınızın ID-JAG'den okuduğu sub da bir aracın içinde get_access_token().subject'in bildirdiği değerin ta kendisidir.

Deneyin

SDK deposundaki examples/stories/identity_assertion/, bu sayfanın gerçekten çalışan hâlidir: aynı exchange_identity_assertion doğrulayıcısı, onun token'larıyla korunan bir MCP sunucusu, yerine geçen bir IdP ve istemci; hepsi kendi kendini denetleyen tek bir programda. uv run python -m stories.identity_assertion.client --http takasın tamamını çalıştırır ve IdP'nin adını verdiği kullanıcının, aracın gördüğü kullanıcı olduğunu doğrular.

Özet

  • SEP-990, bir istemcinin hangi MCP sunucularına erişebileceğine son kullanıcının değil, kurumsal kimlik sağlayıcısının karar vermesini sağlar. IdP o kararı imzalayıp bir ID-JAG içine koyar.
  • ID-JAG'i elde etmek IdP'nize karşı yapılan bir RFC 8693 token takasıdır ve SDK bunu yapmaz. Onu MCP yetkilendirme sunucusuna sunmak RFC 7523 jwt-bearer grant'idir ve SDK bunun iki tarafını da üstlenir.
  • IdentityAssertionOAuthProvider bir başka httpx2.Auth nesnesidir: önceden kaydedilmiş gizli bir istemci, sabitlenmiş bir issuer ve tek bir assertion_provider(audience, resource) callback'i. Tarayıcı yok, kayıt yok, yenileme token'ı yok.
  • Yetkilendirme sunucusu hiçbir zaman kaynak sunucusundan keşfedilmez. issuer'ı, meta veri belgesinin sunduğu dizenin tıpatıp aynısı olarak yapılandırın; karşılaştırma karakter karakter yapılır.
  • Sunucu tarafında identity_assertion_enabled=True artı exchange_identity_assertion. SDK istemcinin kimliğini doğrular ve grant'in kapısını tutar; ID-JAG'i doğrulamak tamamen size aittir ve düzenlenen token isteğin değil, ID-JAG'in resource değerine bağlanır.

Bu sayfanın hiç dokunmadığı tek taraf MCP sunucusudur. Az önce bastığınız token'la ne yapıyorsa, onu Yetkilendirme sayfasında zaten yapıyordu.