@@ -390,7 +390,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
390390 })
391391 t .Run ("Protected resource with MISSING Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
392392 authHeader := resp .Header .Get ("WWW-Authenticate" )
393- expected := `Bearer realm="Kubernetes MCP Server", audience="mcp-server", error="missing_token"`
393+ expected := `Bearer realm="Kubernetes MCP Server", error="missing_token"`
394394 if authHeader != expected {
395395 t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
396396 }
@@ -415,7 +415,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
415415 t .Cleanup (func () { _ = resp .Body .Close })
416416 t .Run ("Protected resource with INCOMPATIBLE Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
417417 authHeader := resp .Header .Get ("WWW-Authenticate" )
418- expected := `Bearer realm="Kubernetes MCP Server", audience="mcp-server", error="missing_token"`
418+ expected := `Bearer realm="Kubernetes MCP Server", error="missing_token"`
419419 if authHeader != expected {
420420 t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
421421 }
@@ -432,7 +432,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
432432 if err != nil {
433433 t .Fatalf ("Failed to create request: %v" , err )
434434 }
435- req .Header .Set ("Authorization" , "Bearer invalid_base64" + tokenBasicNotExpired )
435+ req .Header .Set ("Authorization" , "Bearer " + strings . ReplaceAll ( tokenBasicNotExpired , "." , ".invalid" ) )
436436 resp , err := http .DefaultClient .Do (req )
437437 if err != nil {
438438 t .Fatalf ("Failed to get protected endpoint: %v" , err )
@@ -445,13 +445,13 @@ func TestAuthorizationUnauthorized(t *testing.T) {
445445 })
446446 t .Run ("Protected resource with INVALID Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
447447 authHeader := resp .Header .Get ("WWW-Authenticate" )
448- expected := `Bearer realm="Kubernetes MCP Server", audience="mcp-server", error="invalid_token"`
448+ expected := `Bearer realm="Kubernetes MCP Server", error="invalid_token"`
449449 if authHeader != expected {
450450 t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
451451 }
452452 })
453453 t .Run ("Protected resource with INVALID Authorization header logs error" , func (t * testing.T ) {
454- if ! strings .Contains (ctx .LogBuffer .String (), "Authentication failed - JWT validation error" ) &&
454+ if ! strings .Contains (ctx .LogBuffer .String (), "Authentication failed - JWT validation error" ) ||
455455 ! strings .Contains (ctx .LogBuffer .String (), "error: failed to parse JWT token: illegal base64 data" ) {
456456 t .Errorf ("Expected log entry for JWT validation error, got: %s" , ctx .LogBuffer .String ())
457457 }
@@ -476,22 +476,53 @@ func TestAuthorizationUnauthorized(t *testing.T) {
476476 })
477477 t .Run ("Protected resource with EXPIRED Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
478478 authHeader := resp .Header .Get ("WWW-Authenticate" )
479- expected := `Bearer realm="Kubernetes MCP Server", audience="mcp-server", error="invalid_token"`
479+ expected := `Bearer realm="Kubernetes MCP Server", error="invalid_token"`
480480 if authHeader != expected {
481481 t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
482482 }
483483 })
484484 t .Run ("Protected resource with EXPIRED Authorization header logs error" , func (t * testing.T ) {
485- if ! strings .Contains (ctx .LogBuffer .String (), "Authentication failed - JWT validation error" ) &&
485+ if ! strings .Contains (ctx .LogBuffer .String (), "Authentication failed - JWT validation error" ) ||
486486 ! strings .Contains (ctx .LogBuffer .String (), "validation failed, token is expired (exp)" ) {
487487 t .Errorf ("Expected log entry for JWT validation error, got: %s" , ctx .LogBuffer .String ())
488488 }
489489 })
490490 })
491+ // Invalid audience claim Bearer token
492+ testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true , OAuthAudience : "expected-audience" }}, func (ctx * httpContext ) {
493+ req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
494+ if err != nil {
495+ t .Fatalf ("Failed to create request: %v" , err )
496+ }
497+ req .Header .Set ("Authorization" , "Bearer " + tokenBasicExpired )
498+ resp , err := http .DefaultClient .Do (req )
499+ if err != nil {
500+ t .Fatalf ("Failed to get protected endpoint: %v" , err )
501+ }
502+ t .Cleanup (func () { _ = resp .Body .Close })
503+ t .Run ("Protected resource with INVALID AUDIENCE Authorization header returns 401 - Unauthorized" , func (t * testing.T ) {
504+ if resp .StatusCode != 401 {
505+ t .Errorf ("Expected HTTP 401, got %d" , resp .StatusCode )
506+ }
507+ })
508+ t .Run ("Protected resource with INVALID AUDIENCE Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
509+ authHeader := resp .Header .Get ("WWW-Authenticate" )
510+ expected := `Bearer realm="Kubernetes MCP Server", audience="expected-audience", error="invalid_token"`
511+ if authHeader != expected {
512+ t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
513+ }
514+ })
515+ t .Run ("Protected resource with INVALID AUDIENCE Authorization header logs error" , func (t * testing.T ) {
516+ if ! strings .Contains (ctx .LogBuffer .String (), "Authentication failed - JWT validation error" ) ||
517+ ! strings .Contains (ctx .LogBuffer .String (), "invalid audience claim (aud)" ) {
518+ t .Errorf ("Expected log entry for JWT validation error, got: %s" , ctx .LogBuffer .String ())
519+ }
520+ })
521+ })
491522 // Failed OIDC validation
492523 key , oidcProvider , httpServer := NewOidcTestServer (t )
493524 t .Cleanup (httpServer .Close )
494- testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
525+ testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true , OAuthAudience : "mcp-server" }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
495526 req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
496527 if err != nil {
497528 t .Fatalf ("Failed to create request: %v" , err )
@@ -528,7 +559,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
528559 "aud": "mcp-server"
529560 }`
530561 validOidcToken := oidctest .SignIDToken (key , "test-oidc-key-id" , oidc .RS256 , rawClaims )
531- testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
562+ testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true , OAuthAudience : "mcp-server" }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
532563 req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
533564 if err != nil {
534565 t .Fatalf ("Failed to create request: %v" , err )
@@ -576,30 +607,37 @@ func TestAuthorizationRequireOAuthFalse(t *testing.T) {
576607}
577608
578609func TestAuthorizationRawToken (t * testing.T ) {
579- testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true }}, func (ctx * httpContext ) {
580- ctx .mockServer .Handle (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
581- if req .URL .EscapedPath () == "/apis/authentication.k8s.io/v1/tokenreviews" {
582- w .Header ().Set ("Content-Type" , "application/json" )
583- _ , _ = w .Write ([]byte (tokenReviewSuccessful ))
584- return
610+ cases := []string {
611+ "" ,
612+ "mcp-server" ,
613+ }
614+ for _ , audience := range cases {
615+ testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true , OAuthAudience : audience }}, func (ctx * httpContext ) {
616+ ctx .mockServer .Handle (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
617+ if req .URL .EscapedPath () == "/apis/authentication.k8s.io/v1/tokenreviews" {
618+ w .Header ().Set ("Content-Type" , "application/json" )
619+ _ , _ = w .Write ([]byte (tokenReviewSuccessful ))
620+ return
621+ }
622+ }))
623+ req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
624+ if err != nil {
625+ t .Fatalf ("Failed to create request: %v" , err )
585626 }
586- }))
587- req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
588- if err != nil {
589- t .Fatalf ("Failed to create request: %v" , err )
590- }
591- req .Header .Set ("Authorization" , "Bearer " + tokenBasicNotExpired )
592- resp , err := http .DefaultClient .Do (req )
593- if err != nil {
594- t .Fatalf ("Failed to get protected endpoint: %v" , err )
595- }
596- t .Cleanup (func () { _ = resp .Body .Close () })
597- t .Run ("Protected resource with VALID Authorization header returns 200 - OK" , func (t * testing.T ) {
598- if resp .StatusCode != http .StatusOK {
599- t .Errorf ("Expected HTTP 200 OK, got %d" , resp .StatusCode )
627+ req .Header .Set ("Authorization" , "Bearer " + tokenBasicNotExpired )
628+ resp , err := http .DefaultClient .Do (req )
629+ if err != nil {
630+ t .Fatalf ("Failed to get protected endpoint: %v" , err )
600631 }
632+ t .Cleanup (func () { _ = resp .Body .Close () })
633+ t .Run ("Protected resource with audience = '" + audience + "' with VALID Authorization header returns 200 - OK" , func (t * testing.T ) {
634+ if resp .StatusCode != http .StatusOK {
635+ t .Errorf ("Expected HTTP 200 OK, got %d" , resp .StatusCode )
636+ }
637+ })
601638 })
602- })
639+ }
640+
603641}
604642
605643func TestAuthorizationOidcToken (t * testing.T ) {
@@ -611,7 +649,7 @@ func TestAuthorizationOidcToken(t *testing.T) {
611649 "aud": "mcp-server"
612650 }`
613651 validOidcToken := oidctest .SignIDToken (key , "test-oidc-key-id" , oidc .RS256 , rawClaims )
614- testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
652+ testCaseWithContext (t , & httpContext {StaticConfig : & config.StaticConfig {RequireOAuth : true , OAuthAudience : "mcp-server" }, OidcProvider : oidcProvider }, func (ctx * httpContext ) {
615653 ctx .mockServer .Handle (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
616654 if req .URL .EscapedPath () == "/apis/authentication.k8s.io/v1/tokenreviews" {
617655 w .Header ().Set ("Content-Type" , "application/json" )
0 commit comments