-
Notifications
You must be signed in to change notification settings - Fork 663
Expand file tree
/
Copy pathProtectedResourceMetadata.cs
More file actions
226 lines (209 loc) · 9.96 KB
/
ProtectedResourceMetadata.cs
File metadata and controls
226 lines (209 loc) · 9.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Authentication;
/// <summary>
/// Represents the resource metadata for OAuth authorization as defined in RFC 9396.
/// Defined by <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
};
}
}