fix: update default authorization header to include empty Bearer token and improve validation logic

This commit is contained in:
Kent C. Dodds 2025-09-30 15:17:10 -06:00
commit 34534ed062
3 changed files with 17 additions and 7 deletions

View file

@ -165,7 +165,13 @@ const App = () => {
} }
// Default to empty array // Default to empty array
return []; return [
{
name: "Authorization",
value: "Bearer ",
enabled: false,
},
];
}); });
const [pendingSampleRequests, setPendingSampleRequests] = useState< const [pendingSampleRequests, setPendingSampleRequests] = useState<

View file

@ -914,14 +914,14 @@ describe("useConnection", () => {
expect(headers).toHaveProperty("Authorization", "Bearer mock-token"); expect(headers).toHaveProperty("Authorization", "Bearer mock-token");
}); });
test("replaces empty Bearer token placeholder with OAuth token", async () => { test("warns of enabled empty Bearer token", async () => {
// This test prevents regression of the bug where default "Bearer " header // This test prevents regression of the bug where default "Bearer " header
// prevented OAuth token injection, causing infinite auth loops // prevented OAuth token injection, causing infinite auth loops
const customHeaders: CustomHeaders = [ const customHeaders: CustomHeaders = [
{ {
name: "Authorization", name: "Authorization",
value: "Bearer ", // Empty Bearer token placeholder value: "Bearer ", // Empty Bearer token placeholder
enabled: true, enabled: true, // enabled
}, },
]; ];
@ -937,8 +937,8 @@ describe("useConnection", () => {
}); });
const headers = mockSSETransport.options?.requestInit?.headers; const headers = mockSSETransport.options?.requestInit?.headers;
// Should replace the empty "Bearer " with actual OAuth token
expect(headers).toHaveProperty("Authorization", "Bearer mock-token"); expect(headers).toHaveProperty("Authorization", "Bearer");
// Should not have the x-custom-auth-headers since Authorization is standard // Should not have the x-custom-auth-headers since Authorization is standard
expect(headers).not.toHaveProperty("x-custom-auth-headers"); expect(headers).not.toHaveProperty("x-custom-auth-headers");

View file

@ -402,7 +402,7 @@ export function useConnection({
const isEmptyAuthHeader = (header: CustomHeaders[number]) => const isEmptyAuthHeader = (header: CustomHeaders[number]) =>
header.name.trim().toLowerCase() === "authorization" && header.name.trim().toLowerCase() === "authorization" &&
header.value.trim() === "Bearer"; header.value.trim().toLowerCase() === "bearer";
// Check for empty Authorization headers and show validation error // Check for empty Authorization headers and show validation error
const hasEmptyAuthHeader = finalHeaders.some( const hasEmptyAuthHeader = finalHeaders.some(
@ -418,7 +418,11 @@ export function useConnection({
}); });
} }
const needsOAuthToken = finalHeaders.length === 0 || hasEmptyAuthHeader; const needsOAuthToken = !finalHeaders.some(
(header) =>
header.enabled &&
header.name.trim().toLowerCase() === "authorization",
);
if (needsOAuthToken) { if (needsOAuthToken) {
const oauthToken = (await serverAuthProvider.tokens())?.access_token; const oauthToken = (await serverAuthProvider.tokens())?.access_token;