@@ -28,7 +28,23 @@ public async Task McpEndpoint_WithoutToken_Returns401()
2828 using var request = McpTestHelper . CreateInitializeRequest ( "/mcp" ) ;
2929 using HttpResponseMessage response = await client . SendAsync ( request ) ;
3030
31- await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . Unauthorized ) ;
31+ await AssertUnauthorizedMcpChallengeAsync ( response ) ;
32+ }
33+
34+ [ Test ]
35+ public async Task McpEndpoint_WithSiteCookieButWithoutBearer_Returns401 ( )
36+ {
37+ string cookieUserId = await McpTestHelper . CreateUserAsync ( factory , "mcp-cookie-only" ) ;
38+ ( string cookieName , string cookieValue ) =
39+ await McpTestHelper . CreateIdentityApplicationCookieAsync ( factory , cookieUserId ) ;
40+
41+ HttpClient client = McpTestHelper . CreateClient ( factory ) ;
42+ using var request = McpTestHelper . CreateInitializeRequest ( "/mcp" ) ;
43+ McpTestHelper . AddCookie ( request , cookieName , cookieValue ) ;
44+
45+ using HttpResponseMessage response = await client . SendAsync ( request ) ;
46+
47+ await AssertUnauthorizedMcpChallengeAsync ( response ) ;
3248 }
3349
3450 [ Test ]
@@ -96,7 +112,7 @@ public async Task McpEndpoint_WithInvalidToken_Returns401()
96112 using var request = McpTestHelper . CreateInitializeRequest ( "/mcp" ) ;
97113 McpTestHelper . AddBearerToken ( request , "mcp_invalid_token_that_does_not_exist" ) ;
98114 using HttpResponseMessage response = await client . SendAsync ( request ) ;
99- await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . Unauthorized ) ;
115+ await AssertUnauthorizedMcpChallengeAsync ( response ) ;
100116 }
101117
102118 [ Test ]
@@ -115,7 +131,7 @@ public async Task McpEndpoint_WithRevokedToken_Returns401()
115131 using var request = McpTestHelper . CreateInitializeRequest ( "/mcp" ) ;
116132 McpTestHelper . AddBearerToken ( request , rawToken ) ;
117133 using HttpResponseMessage response = await client . SendAsync ( request ) ;
118- await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . Unauthorized ) ;
134+ await AssertUnauthorizedMcpChallengeAsync ( response ) ;
119135 }
120136
121137 [ Test ]
@@ -131,7 +147,25 @@ public async Task McpEndpoint_WithExpiredToken_Returns401()
131147 using var request = McpTestHelper . CreateInitializeRequest ( "/mcp" ) ;
132148 McpTestHelper . AddBearerToken ( request , rawToken ) ;
133149 using HttpResponseMessage response = await client . SendAsync ( request ) ;
134- await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . Unauthorized ) ;
150+ await AssertUnauthorizedMcpChallengeAsync ( response ) ;
151+ }
152+
153+ [ Test ]
154+ public async Task WellKnownOAuthProtectedResource_AllMethodsReturn404WithoutRedirectAndNoStore ( )
155+ {
156+ HttpClient client = McpTestHelper . CreateClient ( factory ) ;
157+
158+ foreach ( HttpMethod method in new [ ] { HttpMethod . Get , HttpMethod . Post , HttpMethod . Options } )
159+ {
160+ using var request = new HttpRequestMessage ( method , "/.well-known/oauth-protected-resource" ) ;
161+ using HttpResponseMessage response = await client . SendAsync ( request ) ;
162+
163+ await Assert . That ( response . StatusCode )
164+ . IsEqualTo ( HttpStatusCode . NotFound )
165+ . Because ( $ "/.well-known should short-circuit for { method } requests") ;
166+ await Assert . That ( response . Headers . Location ) . IsNull ( ) ;
167+ await Assert . That ( response . Headers . CacheControl ? . NoStore ?? false ) . IsTrue ( ) ;
168+ }
135169 }
136170
137171 [ Test ]
@@ -169,4 +203,12 @@ public async Task McpEndpoint_GetFromLoopbackOrigin_Returns405WithoutRedirect()
169203 await Assert . That ( response . Headers . TryGetValues ( "Access-Control-Allow-Origin" , out IEnumerable < string > ? origins ) ) . IsTrue ( ) ;
170204 await Assert . That ( origins ? . SingleOrDefault ( ) ) . IsEqualTo ( "http://localhost:6274" ) ;
171205 }
206+
207+ private static async Task AssertUnauthorizedMcpChallengeAsync ( HttpResponseMessage response )
208+ {
209+ await Assert . That ( response . StatusCode ) . IsEqualTo ( HttpStatusCode . Unauthorized ) ;
210+ await Assert . That ( response . Headers . Location ) . IsNull ( ) ;
211+ await Assert . That ( response . Headers . TryGetValues ( "WWW-Authenticate" , out IEnumerable < string > ? values ) ) . IsTrue ( ) ;
212+ await Assert . That ( values ? . Any ( value => value . Contains ( "Bearer" , StringComparison . OrdinalIgnoreCase ) ) ?? false ) . IsTrue ( ) ;
213+ }
172214}
0 commit comments