Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions test/e2e/requirements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2937,15 +2937,9 @@ export const REQUIREMENTS: Record<string, Requirement> = {
'client-auth:authprovider:onunauthorized-retry': {
source: 'sdk',
behavior:
'When the server answers 401, the transport awaits AuthProvider.onUnauthorized() and retries the request once with the refreshed token; a second 401 (or a provider without onUnauthorized) surfaces as UnauthorizedError.',
'When the server answers 401, the transport awaits AuthProvider.onUnauthorized() and retries the request once with the refreshed token; a second 401 on that retry rejects with SdkHttpError (ClientHttpAuthentication), while a provider without onUnauthorized surfaces the 401 as UnauthorizedError.',
transports: ['streamableHttp'],
note: "This exercises the HTTP client transport's auth hook; the matrix transport arg is ignored, so it runs as a single streamableHttp-labelled cell to avoid duplicate runs.",
knownFailures: [
{
test: 'second 401 after retry surfaces as UnauthorizedError',
note: 'A second 401 after onUnauthorized() re-authentication surfaces as SdkHttpError (ClientHttpAuthentication) instead of the UnauthorizedError documented on AuthProvider.onUnauthorized().'
}
]
note: "This exercises the HTTP client transport's auth hook; the matrix transport arg is ignored, so it runs as a single streamableHttp-labelled cell to avoid duplicate runs."
},
'client-auth:authprovider:oauth-provider-adapted': {
source: 'sdk',
Expand Down
10 changes: 7 additions & 3 deletions test/e2e/scenarios/client-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
RegistrationRejectedError,
resolveClientMetadata,
SdkError,
SdkErrorCode,
SdkHttpError,
SSEClientTransport,
SseError,
startAuthorization,
Expand Down Expand Up @@ -2221,7 +2223,7 @@ verifies(
const STALE = 'stale-bearer-token';
const ROTATED = 'rotated-but-still-rejected-token';

// The provider refreshes on 401 but the resource keeps rejecting: the retry's 401 must surface as UnauthorizedError.
// The provider refreshes on 401 but the resource keeps rejecting: the retry's 401 must reject with SdkHttpError (ClientHttpAuthentication).
let currentToken = STALE;
let unauthorizedCalls = 0;
const provider: AuthProvider = {
Expand All @@ -2244,7 +2246,9 @@ verifies(
const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), { authProvider: provider, fetch: alwaysUnauthorizedFetch });

try {
await expect(client.connect(transport)).rejects.toThrow(UnauthorizedError);
const connectPromise = client.connect(transport);
Comment thread
claude[bot] marked this conversation as resolved.
await expect(connectPromise).rejects.toBeInstanceOf(SdkHttpError);
await expect(connectPromise).rejects.toMatchObject({ code: SdkErrorCode.ClientHttpAuthentication, status: 401 });

// onUnauthorized ran once and the transport retried exactly once before giving up.
expect(unauthorizedCalls).toBe(1);
Expand All @@ -2253,7 +2257,7 @@ verifies(
await client.close();
}
},
{ title: 'second 401 after retry surfaces as UnauthorizedError' }
{ title: 'second 401 after retry rejects with SdkHttpError' }
);

verifies('client-auth:authprovider:oauth-provider-adapted', async (_args: TestArgs) => {
Expand Down
Loading