MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / validateWorkOSBearerJWT

Function validateWorkOSBearerJWT

server/src/middleware/auth.ts:302–368  ·  view source on GitHub ↗
(req: Request)

Source from the content-addressed store, hash-verified

300 * `enrichUserWithMembership` resolves real membership via the DB.
301 */
302export async function validateWorkOSBearerJWT(req: Request): Promise<ValidatedBearerJWT | null> {
303 const authHeader = req.headers.authorization;
304 if (!authHeader?.startsWith('Bearer ')) return null;
305 const token = authHeader.slice(7);
306
307 if (isWorkOSApiKeyFormat(token)) return null; // handled by validateWorkOSApiKey
308 if (ADMIN_API_KEY && token === ADMIN_API_KEY) return null; // handled by hasValidAdminApiKey
309 if (!looksLikeJWT(token)) return null;
310
311 const cacheKey = hashBearerToken(token);
312 const now = Date.now();
313 const cached = bearerJwtCache.get(cacheKey);
314 if (cached && cached.expiresAt > now) {
315 return { user: cached.user, rawToken: token, orgId: cached.orgId };
316 }
317
318 let verified: Awaited<ReturnType<typeof verifyWorkOSJWT>>;
319 try {
320 verified = await verifyWorkOSJWT(token);
321 } catch (err) {
322 logger.debug({ err }, 'Bearer JWT verification failed');
323 return null;
324 }
325
326 if (verified.isM2M || !verified.sub) return null;
327
328 // Confirm the subject corresponds to a real local user. This catches
329 // tokens from WorkOS accounts that have been deleted or never synced,
330 // and gives us names for the synthesized WorkOSUser.
331 const pool = getPool();
332 const localUser = await pool.query<{
333 first_name: string | null;
334 last_name: string | null;
335 email: string | null;
336 }>(
337 `SELECT first_name, last_name, email FROM users WHERE workos_user_id = $1`,
338 [verified.sub],
339 );
340 if (localUser.rowCount === 0) {
341 logger.warn({ sub: verified.sub }, 'Bearer JWT verified but user not found in local DB');
342 return null;
343 }
344
345 const row = localUser.rows[0];
346 const email = verified.email ?? row.email ?? '';
347 const user: WorkOSUser = {
348 id: verified.sub,
349 email,
350 firstName: row.first_name?.trim() || undefined,
351 lastName: row.last_name?.trim() || undefined,
352 emailVerified: true,
353 createdAt: new Date().toISOString(),
354 updatedAt: new Date().toISOString(),
355 };
356
357 const tokenExpMs = verified.expiresAt ? verified.expiresAt * 1000 : Infinity;
358 const cacheUntil = Math.min(now + BEARER_JWT_CACHE_TTL_MS, tokenExpMs);
359 if (cacheUntil > now) {

Callers 1

requireAuthFunction · 0.85

Calls 12

isWorkOSApiKeyFormatFunction · 0.85
looksLikeJWTFunction · 0.85
hashBearerTokenFunction · 0.85
verifyWorkOSJWTFunction · 0.85
getPoolFunction · 0.85
nowMethod · 0.80
warnMethod · 0.80
nextMethod · 0.80
deleteMethod · 0.80
trimMethod · 0.65
getMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected