Add auth regression test for missing resource in PRM (#1265)
This commit is contained in:
parent
53e9ed8f65
commit
b8ae4fec2b
2 changed files with 52 additions and 2 deletions
|
|
@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModelContextProtocol;
|
||||
using ModelContextProtocol.AspNetCore.Authentication;
|
||||
using ModelContextProtocol.Authentication;
|
||||
using ModelContextProtocol.Client;
|
||||
|
|
@ -528,6 +529,47 @@ public class AuthTests : OAuthTestBase
|
|||
transport, loggerFactory: LoggerFactory, cancellationToken: TestContext.Current.CancellationToken));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CannotAuthenticate_WhenProtectedResourceMetadataMissingResource()
|
||||
{
|
||||
TestOAuthServer.RequireResource = false;
|
||||
|
||||
Builder.Services.Configure<McpAuthenticationOptions>(McpAuthenticationDefaults.AuthenticationScheme, options =>
|
||||
{
|
||||
options.Events.OnResourceMetadataRequest = async context =>
|
||||
{
|
||||
context.HandleResponse();
|
||||
|
||||
var metadata = new ProtectedResourceMetadata
|
||||
{
|
||||
AuthorizationServers = { new Uri(OAuthServerUrl) },
|
||||
ScopesSupported = ["mcp:tools"],
|
||||
};
|
||||
|
||||
await Results.Json(metadata, McpJsonUtilities.DefaultOptions).ExecuteAsync(context.HttpContext);
|
||||
};
|
||||
});
|
||||
|
||||
await using var app = await StartMcpServerAsync();
|
||||
|
||||
await using var transport = new HttpClientTransport(new()
|
||||
{
|
||||
Endpoint = new(McpServerUrl),
|
||||
OAuth = new()
|
||||
{
|
||||
ClientId = "demo-client",
|
||||
ClientSecret = "demo-secret",
|
||||
RedirectUri = new Uri("http://localhost:1179/callback"),
|
||||
AuthorizationRedirectDelegate = HandleAuthorizationUrlAsync,
|
||||
},
|
||||
}, HttpClient, LoggerFactory);
|
||||
|
||||
var ex = await Assert.ThrowsAsync<McpException>(() => McpClient.CreateAsync(
|
||||
transport, loggerFactory: LoggerFactory, cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Contains("Resource URI in metadata", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanAuthenticate_WithAuthorizationServerPathInsertionMetadata()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,14 @@ public sealed class Program
|
|||
/// </remarks>
|
||||
public bool ClientIdMetadataDocumentSupported { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the authorization server requires a resource parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default value is <c>true</c>.
|
||||
/// </remarks>
|
||||
public bool RequireResource { get; set; } = true;
|
||||
|
||||
public HashSet<string> DisabledMetadataPaths { get; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
public IReadOnlyCollection<string> MetadataRequests => _metadataRequests.ToArray();
|
||||
|
||||
|
|
@ -290,7 +298,7 @@ public sealed class Program
|
|||
}
|
||||
|
||||
// Validate resource in accordance with RFC 8707
|
||||
if (string.IsNullOrEmpty(resource) || !ValidResources.Contains(resource))
|
||||
if (RequireResource && (string.IsNullOrEmpty(resource) || !ValidResources.Contains(resource)))
|
||||
{
|
||||
return Results.Redirect($"{redirect_uri}?error=invalid_target&error_description=The+specified+resource+is+not+valid&state={state}");
|
||||
}
|
||||
|
|
@ -338,7 +346,7 @@ public sealed class Program
|
|||
|
||||
// Validate resource in accordance with RFC 8707
|
||||
var resource = form["resource"].ToString();
|
||||
if (string.IsNullOrEmpty(resource) || !ValidResources.Contains(resource))
|
||||
if (RequireResource && (string.IsNullOrEmpty(resource) || !ValidResources.Contains(resource)))
|
||||
{
|
||||
return Results.BadRequest(new OAuthErrorResponse
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue