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
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@cloudflare/codemode": "^0.4.3",
"@cloudflare/shell": "^0.4.1",
"@cloudflare/worker-bundler": "^0.2.1",
"@cloudflare/workers-oauth-provider": "^0.4.0",
"@cloudflare/workers-oauth-provider": "^0.8.2",
"@epic-web/cachified": "^5.6.3",
"@epic-web/invariant": "^1.0.0",
"@epic-web/totp": "^4.0.1",
Expand Down
14 changes: 12 additions & 2 deletions packages/worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ const oauthProvider = new OAuthProvider({
tokenEndpoint: oauthPaths.token,
clientRegistrationEndpoint: oauthPaths.register,
scopesSupported: oauthScopes,
// Provider default onError logs every structured OAuth error via console.warn.
// Keep those responses on the wire without duplicating them into worker logs /
// test console guards; unexpected throws still reach our fetch catch + Sentry.
onError: () => undefined,
// NOTE: we intentionally do NOT set `allowPlainPKCE: false`. In this provider
// version that option rejects EVERY authorize request whose
// `code_challenge_method` is absent or `plain` — including confidential
Expand Down Expand Up @@ -397,8 +401,8 @@ function isOAuthProviderOwnedPath(pathname: string) {

function isMalformedOAuthClientException(error: unknown, pathname: string) {
const message = error instanceof Error ? error.message : ''
// @cloudflare/workers-oauth-provider@0.4.0 throws this raw TypeError
// when a stored client is missing redirectUris during token validation.
// @cloudflare/workers-oauth-provider still throws this raw TypeError when a
// stored client is missing redirectUris during token redirect_uri checks.
return (
pathname === oauthPaths.token &&
message.includes("Cannot read properties of undefined (reading 'some')")
Expand Down Expand Up @@ -539,6 +543,12 @@ const workerHandler = {
name: 'stripe_plan_refresh',
run: () => refreshStaleStripePlans({ env, now: scheduledAt }),
},
{
// 0.5+ defaults refresh/client TTLs and exposes purgeExpiredData for
// defense-in-depth cleanup of orphaned OAUTH_KV grants/tokens.
name: 'oauth_purge_expired',
run: () => oauthProvider.purgeExpiredData(env),
},
]
if (shouldRunRetentionCron(scheduledAt)) {
lanes.push({
Expand Down
10 changes: 10 additions & 0 deletions packages/worker/src/mcp-auth.workers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ function createHelpers(overrides: Partial<OAuthHelpers> = {}): OAuthHelpers {
listUserGrants: async () => ({ items: [] }),
revokeGrant: async () => undefined,
unwrapToken: async () => null,
async exchangeToken() {
throw new Error('Not implemented')
},
purgeExpiredData: async () => ({
grantsChecked: 0,
grantsPurged: 0,
tokensChecked: 0,
tokensPurged: 0,
done: true,
}),
...overrides,
}
}
Expand Down
15 changes: 15 additions & 0 deletions packages/worker/src/oauth-handlers.workers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ function createHelpers(overrides: Partial<OAuthHelpers> = {}): OAuthHelpers {
listUserGrants: async () => ({ items: [] }),
revokeGrant: async () => undefined,
unwrapToken: async () => null,
async exchangeToken() {
throw new Error('Not implemented')
},
purgeExpiredData: async () => ({
grantsChecked: 0,
grantsPurged: 0,
tokensChecked: 0,
tokensPurged: 0,
done: true,
}),
...overrides,
}
}
Expand Down Expand Up @@ -791,6 +801,11 @@ test('worker entrypoint returns OAuth errors for provider-owned route exceptions
encryptedProps: '',
createdAt: Math.floor(Date.now() / 1000),
authCodeId: await createSha256Hex(code),
// 0.8+ treats a missing authCodeWrappedKey as an already-used code and
// returns invalid_grant before redirect_uri validation. Keep a dummy
// wrapped key so the malformed-client redirectUris TypeError still
// reaches the worker exception mapper under test.
authCodeWrappedKey: 'malformed-client-auth-code-wrapped-key',
resource: 'https://heykody.dev/mcp',
codeChallenge: 'verifier',
codeChallengeMethod: 'plain',
Expand Down
Loading