(t *testing.T)
| 458 | } |
| 459 | |
| 460 | func TestMCPHTTP_E2E_OAuth2_EndToEnd(t *testing.T) { |
| 461 | t.Parallel() |
| 462 | |
| 463 | // Setup Coder server with OAuth2 provider enabled |
| 464 | coderClient, closer, api := coderdtest.NewWithAPI(t, nil) |
| 465 | t.Cleanup(func() { closer.Close() }) |
| 466 | |
| 467 | _ = coderdtest.CreateFirstUser(t, coderClient) |
| 468 | |
| 469 | ctx := t.Context() |
| 470 | |
| 471 | // Create OAuth2 app (for demonstration that OAuth2 provider is working) |
| 472 | _, err := coderClient.PostOAuth2ProviderApp(ctx, codersdk.PostOAuth2ProviderAppRequest{ |
| 473 | Name: "test-mcp-app", |
| 474 | CallbackURL: "http://localhost:3000/callback", |
| 475 | }) |
| 476 | require.NoError(t, err) |
| 477 | |
| 478 | // Test 1: OAuth2 Token Endpoint Error Format |
| 479 | t.Run("OAuth2TokenEndpointErrorFormat", func(t *testing.T) { |
| 480 | t.Parallel() |
| 481 | // Test that the /oauth2/tokens endpoint responds with proper OAuth2 error format |
| 482 | // Note: The endpoint is /oauth2/tokens (plural), not /oauth2/token (singular) |
| 483 | req := &http.Request{ |
| 484 | Method: "POST", |
| 485 | URL: mustParseURL(t, api.AccessURL.String()+"/oauth2/tokens"), |
| 486 | Header: map[string][]string{ |
| 487 | "Content-Type": {"application/x-www-form-urlencoded"}, |
| 488 | }, |
| 489 | Body: http.NoBody, |
| 490 | } |
| 491 | |
| 492 | client := &http.Client{} |
| 493 | resp, err := client.Do(req) |
| 494 | require.NoError(t, err) |
| 495 | defer resp.Body.Close() |
| 496 | |
| 497 | // The OAuth2 token endpoint should return HTTP 400 for invalid requests |
| 498 | require.Equal(t, http.StatusBadRequest, resp.StatusCode) |
| 499 | |
| 500 | // Read and verify the response is OAuth2-compliant JSON error format |
| 501 | bodyBytes, err := io.ReadAll(resp.Body) |
| 502 | require.NoError(t, err) |
| 503 | |
| 504 | t.Logf("OAuth2 tokens endpoint returned status: %d, body: %q", resp.StatusCode, string(bodyBytes)) |
| 505 | |
| 506 | // Should be valid JSON with OAuth2 error format |
| 507 | var errorResponse map[string]any |
| 508 | err = json.Unmarshal(bodyBytes, &errorResponse) |
| 509 | require.NoError(t, err, "Response should be valid JSON") |
| 510 | |
| 511 | // Verify OAuth2 error format (RFC 6749 section 5.2) |
| 512 | require.NotEmpty(t, errorResponse["error"], "Error field should not be empty") |
| 513 | }) |
| 514 | |
| 515 | // Test 2: MCP with OAuth2 Bearer Token |
| 516 | t.Run("MCPWithOAuth2BearerToken", func(t *testing.T) { |
| 517 | t.Parallel() |
nothing calls this directly
no test coverage detected