Skip to content

Commit 34beb0c

Browse files
author
Manuel Naujoks
committed
ClientOAuthProvider.Scopes have priority again (#1236)
1 parent 712068b commit 34beb0c

2 files changed

Lines changed: 45 additions & 3 deletions

File tree

src/ModelContextProtocol.Core/Authentication/ClientOAuthProvider.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,16 +640,22 @@ private static Uri GetRequiredResourceUri(ProtectedResourceMetadata protectedRes
640640

641641
private string? GetScopeParameter(ProtectedResourceMetadata protectedResourceMetadata)
642642
{
643-
if (!string.IsNullOrEmpty(protectedResourceMetadata.WwwAuthenticateScope))
643+
if (_configuredScopes is not null)
644+
{
645+
return _configuredScopes;
646+
}
647+
else if (!string.IsNullOrEmpty(protectedResourceMetadata.WwwAuthenticateScope))
644648
{
645649
return protectedResourceMetadata.WwwAuthenticateScope;
646650
}
647651
else if (protectedResourceMetadata.ScopesSupported.Count > 0)
648652
{
649653
return string.Join(" ", protectedResourceMetadata.ScopesSupported);
650654
}
651-
652-
return _configuredScopes;
655+
else
656+
{
657+
return null;
658+
}
653659
}
654660

655661
/// <summary>

tests/ModelContextProtocol.AspNetCore.Tests/OAuth/AuthTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,42 @@ public async Task AuthorizationFlow_UsesScopeFromForbiddenHeader()
501501
Assert.Equal(adminScopes, requestedScope);
502502
}
503503

504+
[Fact]
505+
public async Task AuthorizationFlow_UsesScopeFromClientOAuthOptions()
506+
{
507+
Builder.Services.Configure<McpAuthenticationOptions>(McpAuthenticationDefaults.AuthenticationScheme, options =>
508+
{
509+
options.ResourceMetadata!.ScopesSupported = ["mcp:tools", "files:read"];
510+
});
511+
512+
await using var app = await StartMcpServerAsync();
513+
514+
string? requestedScope = null;
515+
516+
await using var transport = new HttpClientTransport(new()
517+
{
518+
Endpoint = new(McpServerUrl),
519+
OAuth = new()
520+
{
521+
ClientId = "demo-client",
522+
ClientSecret = "demo-secret",
523+
RedirectUri = new Uri("http://localhost:1179/callback"),
524+
Scopes = ["mcp:tools"],
525+
AuthorizationRedirectDelegate = (uri, redirect, ct) =>
526+
{
527+
var query = QueryHelpers.ParseQuery(uri.Query);
528+
requestedScope = query["scope"].ToString();
529+
return HandleAuthorizationUrlAsync(uri, redirect, ct);
530+
},
531+
},
532+
}, HttpClient, LoggerFactory);
533+
534+
await using var client = await McpClient.CreateAsync(
535+
transport, loggerFactory: LoggerFactory, cancellationToken: TestContext.Current.CancellationToken);
536+
537+
Assert.Equal("mcp:tools", requestedScope);
538+
}
539+
504540
[Fact]
505541
public async Task AuthorizationFails_WhenResourceMetadataPortDiffers()
506542
{

0 commit comments

Comments
 (0)