@@ -27,7 +27,16 @@ public McpAuthenticationHandler(
2727 : base ( options , logger , encoder )
2828 {
2929 _optionsMonitor = options ;
30- _resourceMetadataPath = options . CurrentValue . ResourceMetadataUri . ToString ( ) ;
30+
31+ // Note: this.Options is not fully available here.
32+ // _resourceMetadataPath will be correctly updated by GetAbsoluteResourceMetadataUri
33+ // or can be fetched from this.Options directly in HandleRequestAsync if needed.
34+ // For initial setup, if ResourceMetadataUri can be different per scheme,
35+ // this might need to be deferred or handled carefully.
36+ // However, GetAbsoluteResourceMetadataUri which is called by HandleChallengeAsync
37+ // will use this.Options and update _resourceMetadataPath.
38+ // And HandleResourceMetadataRequestAsync will also use this.Options.
39+ _resourceMetadataPath = options . CurrentValue . ResourceMetadataUri ? . ToString ( ) ?? string . Empty ;
3140 }
3241
3342 /// <inheritdoc />
@@ -36,13 +45,19 @@ public async Task<bool> HandleRequestAsync()
3645 // Check if the request is for the resource metadata endpoint
3746 string requestPath = Request . Path . Value ?? string . Empty ;
3847
48+ string expectedMetadataPath = this . Options . ResourceMetadataUri ? . ToString ( ) ?? string . Empty ;
49+ if ( this . Options . ResourceMetadataUri != null && ! this . Options . ResourceMetadataUri . IsAbsoluteUri )
50+ {
51+ // For relative URIs, it's just the path component.
52+ expectedMetadataPath = this . Options . ResourceMetadataUri . OriginalString ;
53+ }
54+
3955 // If the path doesn't match, let the request continue through the pipeline
40- if ( ! string . Equals ( requestPath , _resourceMetadataPath , StringComparison . OrdinalIgnoreCase ) )
56+ if ( ! string . Equals ( requestPath , expectedMetadataPath , StringComparison . OrdinalIgnoreCase ) )
4157 {
4258 return false ;
4359 }
4460
45- // Use the request's cancellation token if available
4661 var cancellationToken = Request . HttpContext . RequestAborted ;
4762 await HandleResourceMetadataRequestAsync ( cancellationToken ) ;
4863 return true ;
@@ -58,27 +73,28 @@ public async Task<bool> HandleRequestAsync()
5873 /// </summary>
5974 private string GetAbsoluteResourceMetadataUri ( )
6075 {
61- var options = _optionsMonitor . CurrentValue ;
76+ var options = this . Options ;
6277 var resourceMetadataUri = options . ResourceMetadataUri ;
6378
6479 // If the options have changed, update the cached path
65- string currentPath = resourceMetadataUri . ToString ( ) ;
66- if ( _resourceMetadataPath != currentPath )
80+ string currentPath = resourceMetadataUri ? . ToString ( ) ?? string . Empty ;
81+ if ( _resourceMetadataPath != currentPath && resourceMetadataUri != null )
6782 {
68- _resourceMetadataPath = currentPath ;
83+ _resourceMetadataPath = resourceMetadataUri . IsAbsoluteUri ? currentPath : resourceMetadataUri . OriginalString ;
6984 }
7085
71- if ( resourceMetadataUri . IsAbsoluteUri )
86+ if ( resourceMetadataUri != null && resourceMetadataUri . IsAbsoluteUri )
7287 {
7388 return currentPath ;
7489 }
7590
7691 // For relative URIs, combine with the base URL
7792 string baseUrl = GetBaseUrl ( ) ;
78-
79- if ( ! Uri . TryCreate ( baseUrl + _resourceMetadataPath , UriKind . Absolute , out var absoluteUri ) )
93+ string relativePath = resourceMetadataUri ? . OriginalString . TrimStart ( '/' ) ?? string . Empty ;
94+
95+ if ( ! Uri . TryCreate ( $ "{ baseUrl . TrimEnd ( '/' ) } /{ relativePath } ", UriKind . Absolute , out var absoluteUri ) )
8096 {
81- throw new InvalidOperationException ( "Could not create absolute URI for resource metadata." ) ;
97+ throw new InvalidOperationException ( $ "Could not create absolute URI for resource metadata. Base URL: { baseUrl } , Relative Path: { relativePath } ") ;
8298 }
8399
84100 return absoluteUri . ToString ( ) ;
@@ -90,8 +106,7 @@ private string GetAbsoluteResourceMetadataUri()
90106 /// <param name="cancellationToken">A token to cancel the operation.</param>
91107 private Task HandleResourceMetadataRequestAsync ( CancellationToken cancellationToken = default )
92108 {
93- // Get resource metadata from options, using the dynamic provider if available
94- var options = _optionsMonitor . CurrentValue ;
109+ var options = this . Options ;
95110 var resourceMetadata = options . GetResourceMetadata ( Request . HttpContext ) ;
96111
97112 // Create a copy to avoid modifying the original
@@ -136,7 +151,6 @@ protected override Task HandleChallengeAsync(AuthenticationProperties properties
136151 // Get the absolute URI for the resource metadata
137152 string rawPrmDocumentUri = GetAbsoluteResourceMetadataUri ( ) ;
138153
139- // Initialize properties if null
140154 properties ??= new AuthenticationProperties ( ) ;
141155
142156 // Store the resource_metadata in properties in case other handlers need it
0 commit comments