using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; namespace ModelContextProtocol.Authentication; /// /// Represents the resource metadata for OAuth authorization as defined in RFC 9728. /// public sealed class ProtectedResourceMetadata { /// /// Gets or sets the resource URI. /// /// /// The protected resource's resource identifier. /// /// /// OPTIONAL. When omitted, the MCP authentication handler infers the resource URI from the incoming request only when serving /// the default /.well-known/oauth-protected-resource endpoint. If a custom ResourceMetadataUri is configured, /// Resource must be explicitly set. Automatic inference only works with the default endpoint pattern. /// [JsonPropertyName("resource")] [StringSyntax(StringSyntaxAttribute.Uri)] public string? Resource { get; set; } /// /// Gets or sets the list of authorization server URIs. /// /// /// A JSON array containing a list of OAuth authorization server issuer identifiers /// for authorization servers that can be used with this protected resource. /// /// /// OPTIONAL. /// [JsonPropertyName("authorization_servers")] public IList AuthorizationServers { get; set; } = []; /// /// Gets or sets the supported bearer token methods. /// /// /// 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"]. /// /// /// OPTIONAL. /// [JsonPropertyName("bearer_methods_supported")] public IList BearerMethodsSupported { get; set; } = ["header"]; /// /// Gets or sets the supported scopes. /// /// /// A JSON array containing a list of scope values that are used in authorization /// requests to request access to this protected resource. /// /// /// RECOMMENDED. /// [JsonPropertyName("scopes_supported")] public IList ScopesSupported { get; set; } = []; /// /// Gets or sets the URL of the protected resource's JSON Web Key (JWK) Set document. /// /// /// 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. /// [JsonPropertyName("jwks_uri")] [StringSyntax(StringSyntaxAttribute.Uri)] public string? JwksUri { get; set; } /// /// Gets or sets the list of the JWS signing algorithms supported by the protected resource for signing resource responses. /// /// /// A JSON array containing a list of the JWS signing algorithms (alg values) supported by the protected resource /// for signing resource responses. /// /// /// OPTIONAL. No default algorithms are implied if this entry is omitted. The value "none" MUST NOT be used. /// [JsonPropertyName("resource_signing_alg_values_supported")] public IList? ResourceSigningAlgValuesSupported { get; set; } /// /// Gets or sets the human-readable name of the protected resource intended for display to the end user. /// /// /// RECOMMENDED. It is recommended that protected resource metadata include this field. /// The value of this field MAY be internationalized. /// [JsonPropertyName("resource_name")] public string? ResourceName { get; set; } /// /// Gets or sets the URI to the resource documentation. /// /// /// The URL of a page containing human-readable information that developers might want or need to know /// when using the protected resource. /// /// /// OPTIONAL. /// [JsonPropertyName("resource_documentation")] [StringSyntax(StringSyntaxAttribute.Uri)] public string? ResourceDocumentation { get; set; } /// /// Gets or sets the URL of a page containing human-readable information about the protected resource's requirements. /// /// /// The URL of a page that contains information about how the client can use the data provided by the protected resource. /// /// /// OPTIONAL. /// [JsonPropertyName("resource_policy_uri")] [StringSyntax(StringSyntaxAttribute.Uri)] public string? ResourcePolicyUri { get; set; } /// /// Gets or sets the URL of a page containing human-readable information about the protected resource's terms of service. /// /// /// OPTIONAL. The value of this field MAY be internationalized. /// [JsonPropertyName("resource_tos_uri")] [StringSyntax(StringSyntaxAttribute.Uri)] public string? ResourceTosUri { get; set; } /// /// Gets or sets a value indicating whether there is protected resource support for mutual-TLS client certificate-bound access tokens. /// /// /// if there's protected resource support for mutual-TLS client certificate-bound access tokens; otherwise, . The default is . /// /// /// OPTIONAL. /// [JsonPropertyName("tls_client_certificate_bound_access_tokens")] public bool? TlsClientCertificateBoundAccessTokens { get; set; } /// /// Gets or sets the list of the authorization details type values supported by the resource server. /// /// /// 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. /// /// /// OPTIONAL. /// [JsonPropertyName("authorization_details_types_supported")] public IList? AuthorizationDetailsTypesSupported { get; set; } /// /// Gets or sets the list of the JWS algorithm values supported by the resource server for validating DPoP proof JWTs. /// /// /// 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. /// /// /// OPTIONAL. /// [JsonPropertyName("dpop_signing_alg_values_supported")] public IList? DpopSigningAlgValuesSupported { get; set; } /// /// Gets or sets a value indicating whether the protected resource always requires the use of DPoP-bound access tokens. /// /// /// if the protected resource always requires the use of DPoP-bound access tokens; otherwise, . The default is . /// /// /// OPTIONAL. /// [JsonPropertyName("dpop_bound_access_tokens_required")] public bool? DpopBoundAccessTokensRequired { get; set; } /// /// 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 /// [JsonIgnore] internal string? WwwAuthenticateScope { get; set; } /// /// Creates a deep copy of this instance, optionally overriding the Resource property. /// /// Optional resource URI string to use for the Resource property if the original Resource is null. /// A new instance of with cloned values. 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 }; } }