identity_assertion
SEP-990 Identity Assertion Authorization Grant (RFC 7523 jwt-bearer) client provider.
IdentityAssertionOAuthProvider is the client side of SEP-990 leg 2: it presents an Identity
Assertion Authorization Grant (ID-JAG) - a signed JWT issued by the enterprise identity provider -
to the MCP authorization server's token endpoint using the RFC 7523 jwt-bearer grant
(grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, ID-JAG as assertion), and receives an
MCP access token.
The authorization server is configuration, not discovery. SEP-990's trust model is the inverse of the default OAuth client's: the AS issuer is supplied at construction, authorization-server metadata is fetched from that issuer's own RFC 8414 well-known, and the resource server is never asked which AS to use - so it cannot redirect the ID-JAG or client secret elsewhere. There is no protected resource metadata fetch, no dynamic client registration, and no server-driven scope selection.
Obtaining the ID-JAG (logging into the IdP and the leg-1 token exchange against it) is
deployment-specific and out of scope for the SDK. The caller supplies it through the
assertion_provider callback, which receives the configured issuer (the aud the ID-JAG must
carry) and the MCP server's resource identifier (the resource claim it must carry, per ext-auth
section 4.3), and returns the ID-JAG.
IdentityAssertionOAuthProvider
Bases: Auth
httpx.Auth for the SEP-990 ID-JAG flow (RFC 7523 jwt-bearer grant) against a configured AS.
The authorization server issuer is fixed at construction; metadata is fetched from its
RFC 8414 well-known and the ID-JAG and client secret are sent only to that issuer's token
endpoint. The resource server is never consulted for AS selection. The ID-JAG is fetched lazily
from assertion_provider so a fresh assertion is used on each exchange.
Example
async def fetch_id_jag(audience: str, resource: str) -> str:
# `audience` is the configured issuer (the ID-JAG `aud`); `resource` is the MCP
# server's identifier (the ID-JAG `resource` claim). Obtaining the ID-JAG from the
# enterprise IdP is deployment-specific and not handled by the SDK.
return await my_idp.issue_id_jag(audience=audience, resource=resource)
provider = IdentityAssertionOAuthProvider(
server_url="https://mcp.example.com/mcp",
storage=my_token_storage,
client_id="my-client-id",
client_secret="my-client-secret",
issuer="https://auth.example.com",
assertion_provider=fetch_id_jag,
)
Source code in src/mcp/client/auth/extensions/identity_assertion.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
__init__
__init__(
server_url: str,
storage: TokenStorage,
client_id: str,
client_secret: str,
issuer: str,
assertion_provider: Callable[
[str, str], Awaitable[str]
],
scope: str | None = None,
token_endpoint_auth_method: Literal[
"client_secret_basic", "client_secret_post"
] = "client_secret_post",
) -> None
Initialize the identity-assertion OAuth provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
server_url
|
str
|
The MCP server URL. |
required |
storage
|
TokenStorage
|
Token storage implementation. |
required |
client_id
|
str
|
The OAuth client ID registered with the MCP authorization server. |
required |
client_secret
|
str
|
The client secret. SEP-990 section 5.1 requires a confidential client. |
required |
issuer
|
str
|
The issuer identifier of the MCP authorization server this client is provisioned for. Authorization-server metadata is fetched from this issuer's well-known and the ID-JAG and secret are sent only to its token endpoint. |
required |
assertion_provider
|
Callable[[str, str], Awaitable[str]]
|
Async callback taking |
required |
scope
|
str | None
|
Optional space-separated list of scopes to request. |
None
|
token_endpoint_auth_method
|
Literal['client_secret_basic', 'client_secret_post']
|
Confidential-client auth method, either |
'client_secret_post'
|
Source code in src/mcp/client/auth/extensions/identity_assertion.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |