Skip to content

Commit c945019

Browse files
committed
feat: Add Enterprise Managed Authorization (SEP-990) support
1 parent c3bb9c1 commit c945019

File tree

5 files changed

+1875
-0
lines changed

5 files changed

+1875
-0
lines changed

README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,67 @@ This attribute may be placed on a method to provide for the tool, prompt, or res
236236
XML comments may also be used; if an `[McpServerTool]`, `[McpServerPrompt]`, or `[McpServerResource]`-attributed method is marked as `partial`,
237237
XML comments placed on the method will be used automatically to generate `[Description]` attributes for the method and its parameters.
238238

239+
## Enterprise Auth / Enterprise Managed Authorization (SEP-990)
240+
241+
The SDK provides Enterprise Auth utilities for the Identity Assertion Authorization Grant flow (SEP-990),
242+
enabling enterprise SSO scenarios where users authenticate once via their enterprise Identity Provider and
243+
access MCP servers without per-server authorization prompts.
244+
245+
The flow consists of two token operations:
246+
1. **RFC 8693 Token Exchange** at the IdP: ID TokenJWT Authorization Grant (JAG)
247+
2. **RFC 7523 JWT Bearer Grant** at the MCP Server: JAGAccess Token
248+
249+
### Using the Layer 2 utilities directly
250+
251+
```csharp
252+
using ModelContextProtocol.Authentication;
253+
254+
// Step 1: Exchange ID token for a JAG at the enterprise IdP
255+
var jag = await EnterpriseAuth.DiscoverAndRequestJwtAuthorizationGrantAsync(
256+
new DiscoverAndRequestJwtAuthGrantOptions
257+
{
258+
IdpUrl = "https://company.okta.com",
259+
Audience = "https://auth.mcp-server.example.com",
260+
Resource = "https://mcp-server.example.com",
261+
IdToken = myIdToken, // obtained via SSO/OIDC login
262+
ClientId = "idp-client-id",
263+
});
264+
265+
// Step 2: Exchange JAG for an access token at the MCP authorization server
266+
var tokens = await EnterpriseAuth.ExchangeJwtBearerGrantAsync(
267+
new ExchangeJwtBearerGrantOptions
268+
{
269+
TokenEndpoint = "https://auth.mcp-server.example.com/token",
270+
Assertion = jag,
271+
ClientId = "mcp-client-id",
272+
});
273+
```
274+
275+
### Using the EnterpriseAuthProvider (Layer 3)
276+
277+
```csharp
278+
var provider = new EnterpriseAuthProvider(new EnterpriseAuthProviderOptions
279+
{
280+
ClientId = "mcp-client-id",
281+
AssertionCallback = async (context, ct) =>
282+
{
283+
return await EnterpriseAuth.DiscoverAndRequestJwtAuthorizationGrantAsync(
284+
new DiscoverAndRequestJwtAuthGrantOptions
285+
{
286+
IdpUrl = "https://company.okta.com",
287+
Audience = context.AuthorizationServerUrl.ToString(),
288+
Resource = context.ResourceUrl.ToString(),
289+
IdToken = myIdToken,
290+
ClientId = "idp-client-id",
291+
}, ct);
292+
}
293+
});
294+
295+
var tokens = await provider.GetAccessTokenAsync(
296+
resourceUrl: new Uri("https://mcp-server.example.com"),
297+
authorizationServerUrl: new Uri("https://auth.mcp-server.example.com"));
298+
```
299+
239300
## Acknowledgements
240301

241302
The starting point for this library was a project called [mcpdotnet](https://github.com/PederHP/mcpdotnet), initiated by [Peder Holdgaard Pedersen](https://github.com/PederHP). We are grateful for the work done by Peder and other contributors to that repository, which created a solid foundation for this library.

0 commit comments

Comments
 (0)