csharp-sdk/src/ModelContextProtocol.Core/Authentication/ProtectedResourceMetadata.cs
Copilot 3cc4863fc1
Fix XML documentation spelling, grammar, and correctness issues across SDK (#1372)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
2026-02-23 23:56:22 -05:00

225 lines
9.9 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Authentication;
/// <summary>
/// Represents the resource metadata for OAuth authorization as defined in <see href="https://datatracker.ietf.org/doc/rfc9728/">RFC 9728</see>.
/// </summary>
public sealed class ProtectedResourceMetadata
{
/// <summary>
/// Gets or sets the resource URI.
/// </summary>
/// <value>
/// The protected resource's resource identifier.
/// </value>
/// <remarks>
/// OPTIONAL. When omitted, the MCP authentication handler infers the resource URI from the incoming request only when serving
/// the default <c>/.well-known/oauth-protected-resource</c> endpoint. If a custom <c>ResourceMetadataUri</c> is configured,
/// <b>Resource</b> must be explicitly set. Automatic inference only works with the default endpoint pattern.
/// </remarks>
[JsonPropertyName("resource")]
[StringSyntax(StringSyntaxAttribute.Uri)]
public string? Resource { get; set; }
/// <summary>
/// Gets or sets the list of authorization server URIs.
/// </summary>
/// <value>
/// A JSON array containing a list of OAuth authorization server issuer identifiers
/// for authorization servers that can be used with this protected resource.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("authorization_servers")]
public IList<string> AuthorizationServers { get; set; } = [];
/// <summary>
/// Gets or sets the supported bearer token methods.
/// </summary>
/// <value>
/// A JSON array containing a list of the supported methods of sending an OAuth 2.0 bearer token
/// to the protected resource. Defined values are ["header", "body", "query"].
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("bearer_methods_supported")]
public IList<string> BearerMethodsSupported { get; set; } = ["header"];
/// <summary>
/// Gets or sets the supported scopes.
/// </summary>
/// <value>
/// A JSON array containing a list of scope values that are used in authorization
/// requests to request access to this protected resource.
/// </value>
/// <remarks>
/// RECOMMENDED.
/// </remarks>
[JsonPropertyName("scopes_supported")]
public IList<string> ScopesSupported { get; set; } = [];
/// <summary>
/// Gets or sets the URL of the protected resource's JSON Web Key (JWK) Set document.
/// </summary>
/// <remarks>
/// OPTIONAL. This document contains public keys belonging to the protected resource, such as signing keys
/// that the resource server uses to sign resource responses. This URL MUST use the HTTPS scheme.
/// </remarks>
[JsonPropertyName("jwks_uri")]
[StringSyntax(StringSyntaxAttribute.Uri)]
public string? JwksUri { get; set; }
/// <summary>
/// Gets or sets the list of the JWS signing algorithms supported by the protected resource for signing resource responses.
/// </summary>
/// <value>
/// A JSON array containing a list of the JWS signing algorithms (alg values) supported by the protected resource
/// for signing resource responses.
/// </value>
/// <remarks>
/// OPTIONAL. No default algorithms are implied if this entry is omitted. The value "none" MUST NOT be used.
/// </remarks>
[JsonPropertyName("resource_signing_alg_values_supported")]
public IList<string>? ResourceSigningAlgValuesSupported { get; set; }
/// <summary>
/// Gets or sets the human-readable name of the protected resource intended for display to the end user.
/// </summary>
/// <remarks>
/// RECOMMENDED. It is recommended that protected resource metadata include this field.
/// The value of this field MAY be internationalized.
/// </remarks>
[JsonPropertyName("resource_name")]
public string? ResourceName { get; set; }
/// <summary>
/// Gets or sets the URI to the resource documentation.
/// </summary>
/// <value>
/// The URL of a page containing human-readable information that developers might want or need to know
/// when using the protected resource.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("resource_documentation")]
[StringSyntax(StringSyntaxAttribute.Uri)]
public string? ResourceDocumentation { get; set; }
/// <summary>
/// Gets or sets the URL of a page containing human-readable information about the protected resource's requirements.
/// </summary>
/// <value>
/// The URL of a page that contains information about how the client can use the data provided by the protected resource.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("resource_policy_uri")]
[StringSyntax(StringSyntaxAttribute.Uri)]
public string? ResourcePolicyUri { get; set; }
/// <summary>
/// Gets or sets the URL of a page containing human-readable information about the protected resource's terms of service.
/// </summary>
/// <remarks>
/// OPTIONAL. The value of this field MAY be internationalized.
/// </remarks>
[JsonPropertyName("resource_tos_uri")]
[StringSyntax(StringSyntaxAttribute.Uri)]
public string? ResourceTosUri { get; set; }
/// <summary>
/// Gets or sets a value indicating whether there is protected resource support for mutual-TLS client certificate-bound access tokens.
/// </summary>
/// <value>
/// <see langword="true"/> if there's protected resource support for mutual-TLS client certificate-bound access tokens; otherwise, <see langword="false"/>. The default is <see langword="false"/>.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("tls_client_certificate_bound_access_tokens")]
public bool? TlsClientCertificateBoundAccessTokens { get; set; }
/// <summary>
/// Gets or sets the list of the authorization details type values supported by the resource server.
/// </summary>
/// <value>
/// A JSON array containing a list of the authorization details type values supported by the resource server
/// when the authorization_details request parameter is used.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("authorization_details_types_supported")]
public IList<string>? AuthorizationDetailsTypesSupported { get; set; }
/// <summary>
/// Gets or sets the list of the JWS algorithm values supported by the resource server for validating DPoP proof JWTs.
/// </summary>
/// <value>
/// A JSON array containing a list of the JWS alg values supported by the resource server
/// for validating Demonstrating Proof of Possession (DPoP) proof JWTs.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("dpop_signing_alg_values_supported")]
public IList<string>? DpopSigningAlgValuesSupported { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the protected resource always requires the use of DPoP-bound access tokens.
/// </summary>
/// <value>
/// <see langword="true"/> if the protected resource always requires the use of DPoP-bound access tokens; otherwise, <see langword="false"/>. The default is <see langword="false"/>.
/// </value>
/// <remarks>
/// OPTIONAL.
/// </remarks>
[JsonPropertyName("dpop_bound_access_tokens_required")]
public bool? DpopBoundAccessTokensRequired { get; set; }
/// <summary>
/// Used internally by the client to get or set the scope specified as a WWW-Authenticate header parameter.
/// This should be preferred over using the ScopesSupported property.
///
/// The scopes included in the WWW-Authenticate challenge MAY match scopes_supported, be a subset or superset of it,
/// or an alternative collection that is neither a strict subset nor superset. Clients MUST NOT assume any particular
/// set relationship between the challenged scope set and scopes_supported. Clients MUST treat the scopes provided
/// in the challenge as authoritative for satisfying the current request.
///
/// https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#protected-resource-metadata-discovery-requirements
/// </summary>
[JsonIgnore]
internal string? WwwAuthenticateScope { get; set; }
/// <summary>
/// Creates a deep copy of this <see cref="ProtectedResourceMetadata"/> instance, optionally overriding the Resource property.
/// </summary>
/// <param name="derivedResource">Optional resource URI string to use for the Resource property if the original Resource is null.</param>
/// <returns>A new instance of <see cref="ProtectedResourceMetadata"/> with cloned values.</returns>
public ProtectedResourceMetadata Clone(string? derivedResource = null)
{
return new ProtectedResourceMetadata
{
Resource = Resource ?? derivedResource,
AuthorizationServers = [.. AuthorizationServers],
BearerMethodsSupported = [.. BearerMethodsSupported],
ScopesSupported = [.. ScopesSupported],
JwksUri = JwksUri,
ResourceSigningAlgValuesSupported = ResourceSigningAlgValuesSupported is not null ? [.. ResourceSigningAlgValuesSupported] : null,
ResourceName = ResourceName,
ResourceDocumentation = ResourceDocumentation,
ResourcePolicyUri = ResourcePolicyUri,
ResourceTosUri = ResourceTosUri,
TlsClientCertificateBoundAccessTokens = TlsClientCertificateBoundAccessTokens,
AuthorizationDetailsTypesSupported = AuthorizationDetailsTypesSupported is not null ? [.. AuthorizationDetailsTypesSupported] : null,
DpopSigningAlgValuesSupported = DpopSigningAlgValuesSupported is not null ? [.. DpopSigningAlgValuesSupported] : null,
DpopBoundAccessTokensRequired = DpopBoundAccessTokensRequired
};
}
}