Skip to content

Commit 54066b9

Browse files
committed
fix(oauth): fix redirect_uri error handling, skip upsert on cache hit
- Move scheme check outside try/catch so specific error isn't swallowed - Return fromCache flag from resolveClientMetadata to skip redundant DB writes
1 parent 2099037 commit 54066b9

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

apps/sim/lib/auth/auth.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,10 @@ export const auth = betterAuth({
546546
const clientId = (ctx.query?.client_id ?? ctx.body?.client_id) as string | undefined
547547
if (clientId && isMetadataUrl(clientId)) {
548548
try {
549-
const metadata = await resolveClientMetadata(clientId)
550-
await upsertCimdClient(metadata)
549+
const { metadata, fromCache } = await resolveClientMetadata(clientId)
550+
if (!fromCache) {
551+
await upsertCimdClient(metadata)
552+
}
551553
} catch (err) {
552554
logger.warn('CIMD resolution failed', {
553555
clientId,

apps/sim/lib/auth/cimd.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ async function fetchClientMetadata(url: string): Promise<ClientMetadataDocument>
4949
}
5050

5151
for (const uri of doc.redirect_uris) {
52+
let parsed: URL
5253
try {
53-
const parsed = new URL(uri)
54-
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
55-
throw new Error(`Invalid redirect_uri scheme: ${parsed.protocol}`)
56-
}
54+
parsed = new URL(uri)
5755
} catch {
5856
throw new Error(`Invalid redirect_uri: ${uri}`)
5957
}
58+
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
59+
throw new Error(`Invalid redirect_uri scheme: ${parsed.protocol}`)
60+
}
6061
if (uri.includes(',')) {
6162
throw new Error(`redirect_uri must not contain commas: ${uri}`)
6263
}
@@ -86,10 +87,15 @@ const cache = new Map<string, { doc: ClientMetadataDocument; expiresAt: number }
8687
const failureCache = new Map<string, { error: string; expiresAt: number }>()
8788
const inflight = new Map<string, Promise<ClientMetadataDocument>>()
8889

89-
export async function resolveClientMetadata(url: string): Promise<ClientMetadataDocument> {
90+
interface ResolveResult {
91+
metadata: ClientMetadataDocument
92+
fromCache: boolean
93+
}
94+
95+
export async function resolveClientMetadata(url: string): Promise<ResolveResult> {
9096
const cached = cache.get(url)
9197
if (cached && Date.now() < cached.expiresAt) {
92-
return cached.doc
98+
return { metadata: cached.doc, fromCache: true }
9399
}
94100

95101
const failed = failureCache.get(url)
@@ -99,7 +105,7 @@ export async function resolveClientMetadata(url: string): Promise<ClientMetadata
99105

100106
const pending = inflight.get(url)
101107
if (pending) {
102-
return pending
108+
return pending.then((doc) => ({ metadata: doc, fromCache: false }))
103109
}
104110

105111
const promise = fetchClientMetadata(url)
@@ -118,7 +124,7 @@ export async function resolveClientMetadata(url: string): Promise<ClientMetadata
118124
})
119125

120126
inflight.set(url, promise)
121-
return promise
127+
return promise.then((doc) => ({ metadata: doc, fromCache: false }))
122128
}
123129

124130
export async function upsertCimdClient(metadata: ClientMetadataDocument): Promise<void> {

0 commit comments

Comments
 (0)