Skip to content

Authorization Support (Using ASP.NET Core Native AuthN/AuthZ Integration) #377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 188 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
0bd80e6
Experimental changes in a different direction
localden May 2, 2025
ac14bb2
Fix build issues
localden May 2, 2025
e8d9a23
Cleanup
localden May 2, 2025
4b3f9f7
Cleanup
localden May 2, 2025
8c790db
Tweaks to logic
localden May 2, 2025
b9ba2b9
Update Program.cs
localden May 2, 2025
47f1937
Cleanup
localden May 2, 2025
638bd35
Update HttpMcpServerBuilderExtensions.cs
localden May 2, 2025
d1f30f8
Tweaks to config
localden May 2, 2025
3713da6
Server configuration
localden May 2, 2025
9582111
Update based on feedback
localden May 2, 2025
8b89c2d
Pop the browser open - implement that in the SDK
localden May 2, 2025
c67ef6c
Tweaks to handles
localden May 2, 2025
a439840
Mock handler
localden May 2, 2025
932e678
Make sure I am not introducing unexpected changes
localden May 2, 2025
2151d00
Rename projects
localden May 2, 2025
3bfc258
Update sample project name and location
localden May 2, 2025
70146dd
Make sure definitions are not changed
localden May 2, 2025
ec25187
Functionality consolidation
localden May 2, 2025
a3926ee
Fix name
localden May 2, 2025
405db57
Organize things better
localden May 2, 2025
a0486d3
Cleanup
localden May 2, 2025
cc2f570
Update samples/ProtectedMCPServer/Program.cs
localden May 2, 2025
4e0b508
Update samples/ProtectedMCPServer/Program.cs
localden May 2, 2025
32f7b16
Update src/ModelContextProtocol.AspNetCore/Auth/McpAuthorizationExten…
localden May 2, 2025
b5728d0
Update samples/AspNetCoreSseServer/Program.cs
localden May 2, 2025
487bbd7
Update src/ModelContextProtocol.AspNetCore/Auth/McpAuthorizationExten…
localden May 2, 2025
22b7bcc
Update src/ModelContextProtocol.AspNetCore/Auth/McpAuthorizationExten…
localden May 2, 2025
a433f5a
Contextual rename
localden May 2, 2025
31f8ce9
Added overload for custom scheme
localden May 2, 2025
48bff9c
Introduce proper constants
localden May 2, 2025
991b29b
Simplify the handling of the WWW-Authenticate implementaiton
localden May 2, 2025
5c28b62
Update Program.cs
localden May 2, 2025
1a1e48c
Remove no longer used entity
localden May 2, 2025
008f521
Move to its own file.
localden May 2, 2025
6e23f4a
Placeholder setup
localden May 2, 2025
ff8a2b7
Fix server devx
localden May 2, 2025
03438d2
Defaults are applied here - no need to redeclare
localden May 2, 2025
a4f2495
Proper authorization configuration
localden May 2, 2025
2cdee6e
Simplify defaults
localden May 2, 2025
e79dcb8
Update McpEndpointRouteBuilderExtensions.cs
localden May 2, 2025
7903c75
Update Program.cs
localden May 2, 2025
fbb1817
Simplify tool configuration
localden May 2, 2025
6aef68b
Update config
localden May 2, 2025
1fd164c
Proper setup
localden May 3, 2025
0badaf8
Update McpAuthenticationHandler.cs
localden May 3, 2025
9209b61
Update samples
localden May 3, 2025
a90d01e
Consolidate some of the PKCE logic.
localden May 3, 2025
f3a3715
Consolidate some OAuth logic
localden May 3, 2025
e044475
Update McpAuthenticationHandler.cs
localden May 3, 2025
8790a35
Clean up the helper
localden May 3, 2025
4cff084
Minor changes to PRM doc logic
localden May 3, 2025
6b768d8
Cleanup
localden May 3, 2025
e3c5c21
Remove unused namespaces
localden May 3, 2025
d77368d
Placeholder for events
localden May 3, 2025
32f2265
Simplify policy setup
localden May 3, 2025
67342cd
Policy setup
localden May 3, 2025
b37a7b9
Escaping
localden May 3, 2025
583de65
Update server configuration
localden May 3, 2025
5f15bce
Validation.
localden May 3, 2025
7c33562
Delegate Base64 encoding to a more performant implementation
localden May 3, 2025
8d4c0c4
Make sure we're consistent
localden May 3, 2025
55bb471
Implement refresh token logic
localden May 3, 2025
debdb67
Stripping out the client implementation - this needs to be re-thought
localden May 4, 2025
003f5a0
Standardize namespacing
localden May 4, 2025
ceee919
Updating the approach for client auth
localden May 4, 2025
51bb38b
Cleanup for client logic
localden May 4, 2025
afd05af
Cleanup
localden May 4, 2025
a0fbec6
Simplify client logic
localden May 4, 2025
4073efd
Complete PRM doc properties. Update for consistency
localden May 4, 2025
2e06f59
Update for consistency
localden May 4, 2025
2d7da73
Work on the basic OAuth implementation in sample
localden May 4, 2025
10cf1f7
Token acquisition logic
localden May 4, 2025
2f84981
Update token logic
localden May 4, 2025
6768089
Significantly more basic provider implementation
localden May 4, 2025
cbb5c36
Working client-server interaction
localden May 4, 2025
0aeec19
Cleanup
localden May 4, 2025
531370a
Simplification
localden May 4, 2025
d511312
Cleanup for consistency
localden May 4, 2025
1496b41
Update with better DevEx
localden May 5, 2025
6b0b7ef
Cleanup
localden May 5, 2025
a9acba8
Delete AuthorizationServerUtils.cs
localden May 5, 2025
f8650f9
Cleanup
localden May 5, 2025
d4cc3ad
Multiple scheme support
localden May 5, 2025
31f611a
Multi-scheme support
localden May 5, 2025
3852be9
Cleaner implementation
localden May 5, 2025
8f926ba
Redundant call
localden May 5, 2025
b501d23
Merge branch 'main' into localden/experimental
localden May 6, 2025
c92343c
Update src/ModelContextProtocol/Authentication/AuthorizationDelegatin…
localden May 7, 2025
c57b85c
Update src/ModelContextProtocol/Authentication/AuthorizationDelegatin…
localden May 7, 2025
bb25dbd
Update src/ModelContextProtocol/Authentication/AuthorizationDelegatin…
localden May 7, 2025
291c7ec
Update src/ModelContextProtocol.AspNetCore/Authentication/McpAuthenti…
localden May 7, 2025
d72221d
Update src/ModelContextProtocol.AspNetCore/Authentication/McpAuthoriz…
localden May 7, 2025
2945083
Clean up scheme checks
localden May 7, 2025
26f44de
Use ConfigureAwait
localden May 7, 2025
ca0cdf3
Fix LINQ issue. Simplify best scheme match check
localden May 7, 2025
45c4b30
Proper array caching
localden May 7, 2025
627e1e4
Update 401 handling logic. Remove pragma warning silencing.
localden May 7, 2025
8903c42
Update based on feedback
localden May 7, 2025
a0275ea
Update the HttpClient configuration
localden May 7, 2025
05e3550
Update for cleanup
localden May 7, 2025
e8f7012
Update McpAuthenticationHandler.cs
localden May 7, 2025
94c39bc
No direct inclusion of HTTP client factory
localden May 8, 2025
0504aee
Remove legacy packages
localden May 8, 2025
7ac5c4a
Update signature and make test explicit
localden May 8, 2025
7b6c9fd
URL check
localden May 8, 2025
c406230
Changes based on feedback
localden May 8, 2025
b8954b3
Update to use a HttpClientFactory
localden May 8, 2025
0b030c2
Update McpAuthenticationHandler.cs
localden May 8, 2025
7c6e406
Update based on feedback
localden May 8, 2025
9420013
Update McpAuthenticationOptions.cs
localden May 8, 2025
4fbf2e9
Update McpAuthenticationOptions.cs
localden May 8, 2025
22962cf
Minor optimizations to the delegating handler
localden May 8, 2025
5c94158
Update AuthorizationDelegatingHandler.cs
localden May 8, 2025
0abea22
Update AuthorizationHelpers.cs
localden May 8, 2025
58a7a3d
Update AuthorizationHelpers.cs
localden May 8, 2025
b3b8168
Update AuthorizationHelpers.cs
localden May 8, 2025
aad7ad5
Update AuthorizationHelpers.cs
localden May 8, 2025
43eb6ff
Add record support for unauthorized result
localden May 8, 2025
9a4cea0
Update BasicOAuthAuthorizationProvider.cs
localden May 8, 2025
b3766aa
Update ProtectedResourceMetadata.cs
localden May 8, 2025
bc1566e
Proper check for resource metadata
localden May 8, 2025
0857b94
Update AuthorizationHelpers.cs
localden May 8, 2025
a40325d
.NET Standard 2.0 compatibility fix
localden May 8, 2025
a0cd4ad
Naming consistency
localden May 8, 2025
fe0d8ba
Update for consistency
localden May 8, 2025
0ff4ac4
Update src/ModelContextProtocol/Authentication/AuthorizationDelegatin…
localden May 10, 2025
3b46c8d
Update src/ModelContextProtocol/Protocol/Transport/SseClientTransport…
localden May 10, 2025
8c6e1dc
Merge branch 'main' into localden/experimental
localden May 10, 2025
3602c66
Merge branch 'main' into localden/experimental
localden May 12, 2025
5980c9a
Update src/ModelContextProtocol/Authentication/AuthorizationDelegatin…
localden May 15, 2025
34794dd
Update samples/ProtectedMCPServer/Program.cs
localden Jun 2, 2025
614f8b3
Update McpAuthenticationOptions.cs
localden Jun 2, 2025
6ed573d
Delete McpAuthorizationPolicyExtensions.cs
localden Jun 2, 2025
bd542e2
Update AuthorizationHelpers.cs
localden Jun 2, 2025
325647b
Update AuthorizationHelpers.cs
localden Jun 2, 2025
5435861
Merge branch 'main' of https://github.com/modelcontextprotocol/csharp…
localden Jun 2, 2025
e1ff4ca
Cleanup
localden Jun 2, 2025
f806625
Update with configuration for generic OAuth provider
localden Jun 2, 2025
8fc0af1
Update GenericOAuthProvider.cs
localden Jun 3, 2025
0af8a58
Merge branch 'main' of https://github.com/modelcontextprotocol/csharp…
localden Jun 3, 2025
c6b1e3a
Move auth stuff to Core.
localden Jun 3, 2025
d3591d6
Update AuthorizationHelpers.cs
localden Jun 3, 2025
4d0a126
Update Program.cs
localden Jun 3, 2025
cbb504f
Shift listener implementation out of the SDK
localden Jun 3, 2025
b6ac759
Remove unused stuff
localden Jun 3, 2025
d81d30c
Update Directory.Packages.props
localden Jun 3, 2025
6ccc1d1
Update Directory.Packages.props
localden Jun 3, 2025
3df91d1
Merge branch 'main' into localden/experimental
localden Jun 4, 2025
9f22fd3
Update src/ModelContextProtocol.AspNetCore/Authentication/McpAuthenti…
localden Jun 4, 2025
e0c507c
Update Directory.Packages.props
localden Jun 6, 2025
253f5d5
Update src/ModelContextProtocol.AspNetCore/Authentication/McpAuthenti…
localden Jun 6, 2025
2c88d7a
Update src/ModelContextProtocol.AspNetCore/Authentication/McpAuthenti…
localden Jun 6, 2025
6b3ec23
Update src/ModelContextProtocol.Core/Authentication/GenericOAuthProvi…
localden Jun 6, 2025
39f0588
Update src/ModelContextProtocol.Core/Authentication/GenericOAuthProvi…
localden Jun 6, 2025
2b4fb27
Update ModelContextProtocol.slnx
localden Jun 7, 2025
ecf63e3
Merge branch 'localden/experimental' of https://github.com/modelconte…
localden Jun 7, 2025
5d32edd
Merge branch 'main' into localden/experimental
localden Jun 8, 2025
01f0e89
Minor tweaks to update logic for PRM
localden Jun 11, 2025
c028c7b
Update McpAuthenticationHandler.cs
localden Jun 11, 2025
6601b79
Update GenericOAuthProvider.cs
localden Jun 11, 2025
f2557ee
Update GenericOAuthProvider.cs
localden Jun 11, 2025
70a1414
Update GenericOAuthProvider.cs
localden Jun 11, 2025
1078ad0
Update AuthorizationHelpers.cs
localden Jun 11, 2025
be83c92
Update AuthorizationHelpers.cs
localden Jun 11, 2025
da9fb9b
Update McpAuthenticationOptions.cs
localden Jun 11, 2025
58ca77c
Small updates
localden Jun 11, 2025
f2c779d
File name changes
localden Jun 11, 2025
84a7253
Merge branch 'main' into localden/experimental
dend Jun 13, 2025
d5c833d
Merge branch 'main' into localden/experimental
localden Jun 13, 2025
c2a77b0
Merge branch 'main' into localden/experimental
localden Jun 17, 2025
cbfe8c7
Don't hard code tenant and client IDs
halter73 Jun 17, 2025
a253cd0
Use top-level statements in ProtectedMCPClient Program.cs
halter73 Jun 17, 2025
1720664
Use scope_supported in GenericOAuthProvider
halter73 Jun 17, 2025
ec926c3
WIP whitespace
halter73 Jun 17, 2025
0c10b09
Merge branch 'main' into localden/experimental
localden Jun 18, 2025
cb52e85
Merge remote-tracking branch 'origin/main' into localden/experimental
halter73 Jun 19, 2025
1de26c7
Manually wrap HttpClient rather than use DelegatingHandler for client…
halter73 Jun 19, 2025
1a3d2c7
Simplify HandleUnauthorizedResponseAsync signature by using exceptions
halter73 Jun 20, 2025
886d388
Add console logger to ProtectedMCPClient sample
halter73 Jun 20, 2025
2b9eae4
Merge remote-tracking branch 'origin/main' into localden/experimental
halter73 Jun 24, 2025
dfa29e1
Add TestOAuthServer
halter73 Jun 26, 2025
3cc5c7f
Allow scopes_supported to be overridden like TS SDK
halter73 Jun 30, 2025
03d0fda
Add ClientOAuthOptions
halter73 Jun 30, 2025
a3e8601
Merge remote-tracking branch 'origin/main' into localden/experimental…
halter73 Jun 30, 2025
5b20710
Add RFC 8707 to the client and TestOAuthServer
halter73 Jun 30, 2025
d747e72
Add Dynamic Client Registration support following RFC 7591
halter73 Jun 30, 2025
910a979
Disable cert validation in tests because the dev cert may not be trusted
halter73 Jun 30, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Tweaks to handles
  • Loading branch information
localden committed May 2, 2025
commit c67ef6c3db3548885990c0aa4be9237b171f4146
81 changes: 64 additions & 17 deletions samples/SecureWeatherClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,49 @@ static async Task Main(string[] args)
Console.WriteLine("==================================================");
Console.WriteLine();

// Create the authorization config with HTTP listener
var authConfig = new AuthorizationConfig
{
ClientId = "04f79824-ab56-4511-a7cb-d7deaea92dc0",
Scopes = ["User.Read"]
}.UseHttpListener(hostname: "localhost", listenPort: 1170);
Console.WriteLine("Select authentication mode:");
Console.WriteLine("1. Normal OAuth flow with browser");
Console.WriteLine("2. Mock authentication (accepts any token for testing)");
Console.Write("Enter your choice (1-2): ");
var choice = Console.ReadLine()?.Trim();

// Create an HTTP client with OAuth handling
var oauthHandler = new OAuthDelegatingHandler(
redirectUri: authConfig.RedirectUri,
clientId: authConfig.ClientId,
clientName: authConfig.ClientName,
scopes: authConfig.Scopes,
authorizationHandler: authConfig.AuthorizationHandler)
DelegatingHandler oauthHandler;

if (choice == "2")
{
Console.WriteLine("\nUsing mock authentication for testing (no browser will open).\n");

// Create a mock OAuth handler that always returns a token
oauthHandler = new MockOAuthHandler()
{
InnerHandler = new HttpClientHandler()
};
}
else
{
// The OAuth handler needs an inner handler
InnerHandler = new HttpClientHandler()
};
Console.WriteLine("\nUsing standard OAuth flow with browser authentication.\n");

// Create the authorization config with HTTP listener
var authConfig = new AuthorizationConfig
{
ClientId = "04f79824-ab56-4511-a7cb-d7deaea92dc0",
ClientName = "SecureWeatherClient",
Scopes = ["weather.read"]
}.UseHttpListener(hostname: "localhost", listenPort: 1170);

// Create an HTTP client with OAuth handling
oauthHandler = new OAuthDelegatingHandler(
redirectUri: authConfig.RedirectUri,
clientId: authConfig.ClientId,
clientName: authConfig.ClientName,
scopes: authConfig.Scopes,
authorizationHandler: authConfig.AuthorizationHandler)
{
// The OAuth handler needs an inner handler
InnerHandler = new HttpClientHandler()
};
}

var httpClient = new HttpClient(oauthHandler);
var serverUrl = "http://localhost:7071/sse"; // Default server URL
Expand All @@ -46,8 +71,13 @@ static async Task Main(string[] args)

Console.WriteLine();
Console.WriteLine($"Connecting to weather server at {serverUrl}...");
Console.WriteLine("When prompted for authorization, a browser window will open automatically.");
Console.WriteLine("Complete the authentication in the browser, and this application will continue automatically.");

if (choice != "2")
{
Console.WriteLine("When prompted for authorization, a browser window will open automatically.");
Console.WriteLine("Complete the authentication in the browser, and this application will continue automatically.");
}

Console.WriteLine();

try
Expand Down Expand Up @@ -97,4 +127,21 @@ static async Task Main(string[] args)
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}

/// <summary>
/// A mock OAuth handler that always returns a predefined token without going through the OAuth flow.
/// This is useful for testing without requiring a real OAuth server.
/// </summary>
public class MockOAuthHandler : DelegatingHandler
{
private readonly string _mockToken = "mock_test_token_" + Guid.NewGuid().ToString("N");

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Always attach the mock token to outgoing requests
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _mockToken);

return base.SendAsync(request, cancellationToken);
}
}
58 changes: 16 additions & 42 deletions src/ModelContextProtocol/Auth/McpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,52 +96,26 @@ public static async Task<OAuthToken> HandleUnauthorizedResponseAsync(
throw new InvalidOperationException("The HTTP client has not been configured for authorization handling. Call ConfigureAuthorizationHandler() first.");
}

// Create OAuthAuthenticationService
var authService = new OAuthAuthenticationService();
// Create OAuthAuthenticationService - use appropriate constructor based on whether we have a handler
OAuthAuthenticationService authService = config.AuthorizationHandler != null
? new OAuthAuthenticationService(config.AuthorizationHandler)
: new OAuthAuthenticationService();

// Get resource URI
var resourceUri = response.RequestMessage?.RequestUri ?? throw new InvalidOperationException("Request URI is not available.");

// Start the authentication flow
try
{
var tokenResponse = await authService.HandleAuthenticationAsync(
resourceUri,
wwwAuthenticateHeader,
config.RedirectUri,
config.ClientId,
config.ClientName,
config.Scopes);

// Attach the access token to future requests
httpClient.AttachToken(tokenResponse.AccessToken);

return tokenResponse;
}
catch (NotImplementedException ex) when (ex.Message.Contains("Authorization requires user interaction"))
{
// Extract the authorization URL from the exception message
var authUrlStart = ex.Message.IndexOf("http");
var authUrlEnd = ex.Message.IndexOf("\n", authUrlStart);
var authUrl = ex.Message.Substring(authUrlStart, authUrlEnd - authUrlStart);

// Check if a handler is registered
if (config.AuthorizationHandler != null)
{
// Call the handler to get the authorization code
var authCode = await config.AuthorizationHandler(new Uri(authUrl));

// In a real implementation, we would use the authorization code to get a token
// For now, throw an exception with instructions
throw new NotImplementedException(
"Authorization code acquired, but token exchange is not implemented. " +
"In a real implementation, this would call ExchangeAuthorizationCodeForTokenAsync.");
}
else
{
// Re-throw the original exception
throw;
}
}
var tokenResponse = await authService.HandleAuthenticationAsync(
resourceUri,
wwwAuthenticateHeader,
config.RedirectUri,
config.ClientId,
config.ClientName,
config.Scopes);

// Attach the access token to future requests
httpClient.AttachToken(tokenResponse.AccessToken);

return tokenResponse;
}
}
68 changes: 50 additions & 18 deletions src/ModelContextProtocol/Auth/OAuthAuthenticationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@ namespace ModelContextProtocol.Auth;
public class OAuthAuthenticationService
{
private static readonly HttpClient _httpClient = new();
private readonly Func<Uri, Task<string>>? _authorizationHandler;

/// <summary>
/// Initializes a new instance of the <see cref="OAuthAuthenticationService"/> class.
/// </summary>
public OAuthAuthenticationService()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="OAuthAuthenticationService"/> class with an authorization handler.
/// </summary>
/// <param name="authorizationHandler">A handler to invoke when authorization is required.</param>
public OAuthAuthenticationService(Func<Uri, Task<string>> authorizationHandler)
{
_authorizationHandler = authorizationHandler ?? throw new ArgumentNullException(nameof(authorizationHandler));
}

/// <summary>
/// Handles the OAuth authentication flow when a 401 Unauthorized response is received.
Expand All @@ -23,15 +40,20 @@ public class OAuthAuthenticationService
/// <param name="clientId">The client ID to use for authentication, or null to register a new client.</param>
/// <param name="clientName">The client name to use for registration.</param>
/// <param name="scopes">The requested scopes.</param>
/// <param name="authorizationHandler">A handler to invoke when authorization is required. If not provided, the handler from the constructor will be used.</param>
/// <returns>The OAuth token response.</returns>
public async Task<OAuthToken> HandleAuthenticationAsync(
Uri resourceUri,
string wwwAuthenticateHeader,
Uri redirectUri,
string? clientId = null,
string? clientName = null,
IEnumerable<string>? scopes = null)
IEnumerable<string>? scopes = null,
Func<Uri, Task<string>>? authorizationHandler = null)
{
// Use the provided authorization handler or fall back to the one from the constructor
var effectiveAuthHandler = authorizationHandler ?? _authorizationHandler;

// Extract resource metadata URL from WWW-Authenticate header
var resourceMetadataUri = ExtractResourceMetadataUri(wwwAuthenticateHeader);
if (resourceMetadataUri == null)
Expand Down Expand Up @@ -88,7 +110,8 @@ public async Task<OAuthToken> HandleAuthenticationAsync(
effectiveClientId, // This is now guaranteed to be non-null
clientSecret,
redirectUri,
scopes?.ToList() ?? resourceMetadata.ScopesSupported);
scopes?.ToList() ?? resourceMetadata.ScopesSupported,
effectiveAuthHandler);

return tokenResponse;
}
Expand Down Expand Up @@ -219,7 +242,8 @@ private async Task<OAuthToken> PerformAuthorizationCodeFlowAsync(
string clientId,
string? clientSecret,
Uri redirectUri,
IEnumerable<string> scopes)
IEnumerable<string> scopes,
Func<Uri, Task<string>>? authorizationHandler)
{
// Generate PKCE code verifier and challenge
var codeVerifier = GenerateCodeVerifier();
Expand All @@ -233,26 +257,34 @@ private async Task<OAuthToken> PerformAuthorizationCodeFlowAsync(
codeChallenge,
scopes);

// At this point, in a real application, you would redirect the user to the authorizationUrl
// and then handle the callback to redirectUri with the authorization code.
// For this implementation, we'll assume the code is obtained externally and passed to us.
// Check if an authorization handler is available
if (authorizationHandler != null)
{
try
{
// Get the authorization code using the provided handler
string authorizationCode = await authorizationHandler(new Uri(authorizationUrl));

// Exchange the authorization code for a token
return await ExchangeAuthorizationCodeForTokenAsync(
authServerMetadata.TokenEndpoint,
clientId,
clientSecret,
redirectUri,
authorizationCode,
codeVerifier);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to complete OAuth authorization flow: {ex.Message}", ex);
}
}

// Since we can't actually perform the browser interaction in this service,
// we'll throw with instructions
// No authorization handler available, throw with instructions
throw new NotImplementedException(
$"Authorization requires user interaction. Please direct the user to: {authorizationUrl}\n" +
$"After authorization, the user will be redirected to: {redirectUri}?code=[authorization_code]\n" +
$"You need to handle this redirect and extract the authorization code to complete the flow.");

// In a real implementation, after getting the authorization code:
// var authorizationCode = GetAuthorizationCodeFromRedirect();
// return await ExchangeAuthorizationCodeForTokenAsync(
// authServerMetadata.TokenEndpoint,
// clientId,
// clientSecret,
// redirectUri,
// authorizationCode,
// codeVerifier);
}

private string GenerateCodeVerifier()
Expand Down
Loading
Loading