@@ -390,7 +390,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
390
390
})
391
391
t .Run ("Protected resource with MISSING Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
392
392
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"`
394
394
if authHeader != expected {
395
395
t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
396
396
}
@@ -415,7 +415,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
415
415
t .Cleanup (func () { _ = resp .Body .Close })
416
416
t .Run ("Protected resource with INCOMPATIBLE Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
417
417
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"`
419
419
if authHeader != expected {
420
420
t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
421
421
}
@@ -432,7 +432,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
432
432
if err != nil {
433
433
t .Fatalf ("Failed to create request: %v" , err )
434
434
}
435
- req .Header .Set ("Authorization" , "Bearer invalid_base64" + tokenBasicNotExpired )
435
+ req .Header .Set ("Authorization" , "Bearer " + strings . ReplaceAll ( tokenBasicNotExpired , "." , ".invalid" ) )
436
436
resp , err := http .DefaultClient .Do (req )
437
437
if err != nil {
438
438
t .Fatalf ("Failed to get protected endpoint: %v" , err )
@@ -445,13 +445,13 @@ func TestAuthorizationUnauthorized(t *testing.T) {
445
445
})
446
446
t .Run ("Protected resource with INVALID Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
447
447
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"`
449
449
if authHeader != expected {
450
450
t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
451
451
}
452
452
})
453
453
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" ) ||
455
455
! strings .Contains (ctx .LogBuffer .String (), "error: failed to parse JWT token: illegal base64 data" ) {
456
456
t .Errorf ("Expected log entry for JWT validation error, got: %s" , ctx .LogBuffer .String ())
457
457
}
@@ -476,22 +476,53 @@ func TestAuthorizationUnauthorized(t *testing.T) {
476
476
})
477
477
t .Run ("Protected resource with EXPIRED Authorization header returns WWW-Authenticate header" , func (t * testing.T ) {
478
478
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"`
480
480
if authHeader != expected {
481
481
t .Errorf ("Expected WWW-Authenticate header to be %q, got %q" , expected , authHeader )
482
482
}
483
483
})
484
484
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" ) ||
486
486
! strings .Contains (ctx .LogBuffer .String (), "validation failed, token is expired (exp)" ) {
487
487
t .Errorf ("Expected log entry for JWT validation error, got: %s" , ctx .LogBuffer .String ())
488
488
}
489
489
})
490
490
})
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
+ })
491
522
// Failed OIDC validation
492
523
key , oidcProvider , httpServer := NewOidcTestServer (t )
493
524
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 ) {
495
526
req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
496
527
if err != nil {
497
528
t .Fatalf ("Failed to create request: %v" , err )
@@ -528,7 +559,7 @@ func TestAuthorizationUnauthorized(t *testing.T) {
528
559
"aud": "mcp-server"
529
560
}`
530
561
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 ) {
532
563
req , err := http .NewRequest ("GET" , fmt .Sprintf ("http://%s/mcp" , ctx .HttpAddress ), nil )
533
564
if err != nil {
534
565
t .Fatalf ("Failed to create request: %v" , err )
@@ -576,30 +607,37 @@ func TestAuthorizationRequireOAuthFalse(t *testing.T) {
576
607
}
577
608
578
609
func 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 )
585
626
}
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 )
600
631
}
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
+ })
601
638
})
602
- })
639
+ }
640
+
603
641
}
604
642
605
643
func TestAuthorizationOidcToken (t * testing.T ) {
@@ -611,7 +649,7 @@ func TestAuthorizationOidcToken(t *testing.T) {
611
649
"aud": "mcp-server"
612
650
}`
613
651
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 ) {
615
653
ctx .mockServer .Handle (http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
616
654
if req .URL .EscapedPath () == "/apis/authentication.k8s.io/v1/tokenreviews" {
617
655
w .Header ().Set ("Content-Type" , "application/json" )
0 commit comments