11package auth_test
22
33import (
4+ "context"
45 "crypto/sha256"
56 "encoding/base64"
67 "encoding/json"
@@ -69,6 +70,38 @@ func TestAuthMetadata_JSON(t *testing.T) {
6970 assert .Equal (t , "https://auth.example.com/token" , decoded ["token_url" ])
7071}
7172
73+ // -----------------------------------------------------------------------
74+ // MetadataHandler — /.well-known/oauth-authorization-server
75+ // -----------------------------------------------------------------------
76+
77+ func TestMetadataHandler_ServesRFC8414 (t * testing.T ) {
78+ cfg := auth.OAuthConfig {
79+ ClientID : "meridian-mcp" ,
80+ AuthorizationURL : "https://mcp.example.com/oauth/authorize" ,
81+ TokenURL : "https://mcp.example.com/oauth/token" ,
82+ }
83+
84+ handler := auth .NewMetadataHandler ("https://mcp.example.com" , cfg )
85+ req := httptest .NewRequestWithContext (context .Background (), http .MethodGet , "/.well-known/oauth-authorization-server" , nil )
86+ rec := httptest .NewRecorder ()
87+ handler (rec , req )
88+
89+ assert .Equal (t , http .StatusOK , rec .Code )
90+ assert .Equal (t , "application/json; charset=utf-8" , rec .Header ().Get ("Content-Type" ))
91+ assert .Contains (t , rec .Header ().Get ("Cache-Control" ), "public" )
92+
93+ var meta auth.AuthorizationServerMetadata
94+ require .NoError (t , json .Unmarshal (rec .Body .Bytes (), & meta ))
95+
96+ assert .Equal (t , "https://mcp.example.com" , meta .Issuer )
97+ assert .Equal (t , "https://mcp.example.com/oauth/authorize" , meta .AuthorizationEndpoint )
98+ assert .Equal (t , "https://mcp.example.com/oauth/token" , meta .TokenEndpoint )
99+ assert .Equal (t , []string {"code" }, meta .ResponseTypesSupported )
100+ assert .Equal (t , []string {"authorization_code" }, meta .GrantTypesSupported )
101+ assert .Equal (t , []string {"S256" }, meta .CodeChallengeMethodsSupported )
102+ assert .Equal (t , []string {"none" }, meta .TokenEndpointAuthMethodsSupported )
103+ }
104+
72105// -----------------------------------------------------------------------
73106// AuthorizationHandler
74107// -----------------------------------------------------------------------
@@ -85,7 +118,7 @@ func TestAuthorizationHandler_GeneratesCode(t *testing.T) {
85118
86119 _ , challenge := generatePKCEPair (t )
87120
88- req := httptest .NewRequest ( http .MethodGet , "/oauth/authorize?" + url.Values {
121+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/oauth/authorize?" + url.Values {
89122 "response_type" : {"code" },
90123 "client_id" : {cfg .ClientID },
91124 "redirect_uri" : {cfg .RedirectURI },
@@ -119,7 +152,7 @@ func TestAuthorizationHandler_MissingChallenge_ReturnsBadRequest(t *testing.T) {
119152 }
120153 handler := auth .NewAuthorizationHandler (cfg , store )
121154
122- req := httptest .NewRequest ( http .MethodGet , "/oauth/authorize?response_type=code&client_id=meridian-mcp" , nil )
155+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/oauth/authorize?response_type=code&client_id=meridian-mcp" , nil )
123156 w := httptest .NewRecorder ()
124157 handler .ServeHTTP (w , req )
125158
@@ -136,7 +169,7 @@ func TestAuthorizationHandler_WrongClientID_ReturnsBadRequest(t *testing.T) {
136169
137170 _ , challenge := generatePKCEPair (t )
138171
139- req := httptest .NewRequest ( http .MethodGet , "/oauth/authorize?" + url.Values {
172+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/oauth/authorize?" + url.Values {
140173 "response_type" : {"code" },
141174 "client_id" : {"wrong-client" },
142175 "redirect_uri" : {cfg .RedirectURI },
@@ -159,7 +192,7 @@ func TestAuthorizationHandler_WrongRedirectURI_ReturnsBadRequest(t *testing.T) {
159192
160193 _ , challenge := generatePKCEPair (t )
161194
162- req := httptest .NewRequest ( http .MethodGet , "/oauth/authorize?" + url.Values {
195+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/oauth/authorize?" + url.Values {
163196 "response_type" : {"code" },
164197 "client_id" : {cfg .ClientID },
165198 "redirect_uri" : {"https://evil.example.com/steal" },
@@ -180,7 +213,7 @@ func TestAuthorizationHandler_NonGetMethod_ReturnsMethodNotAllowed(t *testing.T)
180213 }
181214 handler := auth .NewAuthorizationHandler (cfg , store )
182215
183- req := httptest .NewRequest ( http .MethodPost , "/oauth/authorize" , nil )
216+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/authorize" , nil )
184217 w := httptest .NewRecorder ()
185218 handler .ServeHTTP (w , req )
186219
@@ -220,7 +253,7 @@ func TestTokenHandler_ExchangesCodeForToken(t *testing.T) {
220253 "client_id" : {cfg .ClientID },
221254 "code_verifier" : {verifier },
222255 }
223- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
256+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
224257 strings .NewReader (form .Encode ()))
225258 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
226259 w := httptest .NewRecorder ()
@@ -261,7 +294,7 @@ func TestTokenHandler_InvalidVerifier_ReturnsBadRequest(t *testing.T) {
261294 "client_id" : {cfg .ClientID },
262295 "code_verifier" : {"wrong-verifier-AAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }, // 43+ chars per RFC 7636
263296 }
264- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
297+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
265298 strings .NewReader (form .Encode ()))
266299 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
267300 w := httptest .NewRecorder ()
@@ -298,7 +331,7 @@ func TestTokenHandler_ExpiredCode_ReturnsBadRequest(t *testing.T) {
298331 "client_id" : {cfg .ClientID },
299332 "code_verifier" : {verifier },
300333 }
301- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
334+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
302335 strings .NewReader (form .Encode ()))
303336 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
304337 w := httptest .NewRecorder ()
@@ -326,7 +359,7 @@ func TestTokenHandler_UnknownCode_ReturnsBadRequest(t *testing.T) {
326359 "client_id" : {cfg .ClientID },
327360 "code_verifier" : {verifier },
328361 }
329- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
362+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
330363 strings .NewReader (form .Encode ()))
331364 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
332365 w := httptest .NewRecorder ()
@@ -362,7 +395,7 @@ func TestTokenHandler_CodeIsConsumedAfterExchange(t *testing.T) {
362395 "client_id" : {cfg .ClientID },
363396 "code_verifier" : {verifier },
364397 }
365- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
398+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
366399 strings .NewReader (form .Encode ()))
367400 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
368401 w := httptest .NewRecorder ()
@@ -405,7 +438,7 @@ func TestTokenHandler_MismatchedRedirectURI_ReturnsBadRequest(t *testing.T) {
405438 "client_id" : {cfg .ClientID },
406439 "code_verifier" : {verifier },
407440 }
408- req := httptest .NewRequest ( http .MethodPost , "/oauth/token" ,
441+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodPost , "/oauth/token" ,
409442 strings .NewReader (form .Encode ()))
410443 req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
411444 w := httptest .NewRecorder ()
@@ -470,7 +503,7 @@ func TestBearerMiddleware_RejectsUnauthenticated(t *testing.T) {
470503 w .WriteHeader (http .StatusOK )
471504 })
472505
473- req := httptest .NewRequest ( http .MethodGet , "/mcp" , nil )
506+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/mcp" , nil )
474507 w := httptest .NewRecorder ()
475508 mw .Handler (inner ).ServeHTTP (w , req )
476509
@@ -496,7 +529,7 @@ func TestBearerMiddleware_AcceptsValidToken(t *testing.T) {
496529 w .WriteHeader (http .StatusOK )
497530 })
498531
499- req := httptest .NewRequest ( http .MethodGet , "/mcp" , nil )
532+ req := httptest .NewRequestWithContext ( context . Background (), http .MethodGet , "/mcp" , nil )
500533 req .Header .Set ("Authorization" , "Bearer valid-token" )
501534 w := httptest .NewRecorder ()
502535 mw .Handler (inner ).ServeHTTP (w , req )
0 commit comments