(protectedHeader, token)
| 369 | }; |
| 370 | |
| 371 | const get: JWTVerifyGetKey = async (protectedHeader, token) => { |
| 372 | const current = await ensureFresh(false); |
| 373 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: jose JWTVerifyGetKey retry path is defined by thrown resolver failures |
| 374 | try { |
| 375 | const resolveStartedAt = Date.now(); |
| 376 | const key = await current.resolver(protectedHeader, token); |
| 377 | lastResolveMs = Date.now() - resolveStartedAt; |
| 378 | return key; |
| 379 | } catch (error) { |
| 380 | // Likely cause: keys rotated upstream after our TTL window started, or |
| 381 | // we answered from a stale entry. Refetch once and try again. Anything |
| 382 | // still failing bubbles up so jose can classify it (we do not silently |
| 383 | // swallow real failures). |
| 384 | if (!isJwksNoMatchingKey(error)) { |
| 385 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: jose JWTVerifyGetKey requires preserving upstream resolver rejection |
| 386 | throw error; |
| 387 | } |
| 388 | const refreshed = await ensureFresh(true); |
| 389 | return refreshed.resolver(protectedHeader, token); |
| 390 | } |
| 391 | }; |
| 392 | |
| 393 | const result = get as CachedRemoteJWKSet; |
| 394 | Object.defineProperty(result, "forceRefresh", { |
nothing calls this directly
no test coverage detected