MCPcopy Index your code
hub / github.com/sourcebot-dev/sourcebot / jwt

Function jwt

packages/web/src/auth.ts:349–418  ·  view source on GitHub ↗
({ token, user: _user })

Source from the content-addressed store, hash-verified

347 return baseUrl;
348 },
349 async jwt({ token, user: _user }) {
350 const user = _user as User | undefined;
351 // @note: `user` will be available on signUp or signIn triggers.
352 // Cache the userId in the JWT for later use.
353 if (user) {
354 token.userId = user.id;
355 token.sessionVersion = user.sessionVersion ?? 0;
356 }
357
358 if (token.userId) {
359 // Single query: fetch the user's current sessionVersion for
360 // the cross-check below, plus any accounts that still need
361 // the issuerUrl lazy migration.
362 //
363 // @see https://github.com/sourcebot-dev/sourcebot/pull/993
364 const dbUser = await __unsafePrisma.user.findUnique({
365 where: {
366 id: token.userId as string,
367 },
368 select: {
369 sessionVersion: true,
370 accounts: {
371 where: {
372 issuerUrl: null,
373 },
374 },
375 },
376 });
377
378 // The user row was removed (e.g., deleted via /api/ee/user
379 // or org-removal cascade). Treat the JWT as invalid so
380 // /api/auth/session reports logged-out and @auth/core clears
381 // the cookie from the browser.
382 if (!dbUser) {
383 return null;
384 }
385
386 // On every non-login request, cross-check the JWT's
387 // sessionVersion against the user's current sessionVersion in
388 // the database. A mismatch means the user signed out, was
389 // removed from the org, or their sessions were otherwise
390 // invalidated since the JWT was minted. Returning null here
391 // is what makes invalidation visible at /api/auth/session,
392 // not just at withAuth-gated endpoints.
393 const tokenSessionVersion = token.sessionVersion ?? 0;
394 if (!user && tokenSessionVersion !== dbUser.sessionVersion) {
395 return null;
396 }
397
398 // Lazy migration of issuerUrl on accounts created before
399 // the column was introduced in v4.15.4. The where clause
400 // above scopes this to only accounts that still need it,
401 // so the loop is a no-op once everyone is backfilled.
402 for (const account of dbUser.accounts) {
403 const issuerUrl = await getIssuerUrlForProviderId(account.providerId);
404 if (issuerUrl) {
405 await __unsafePrisma.account.update({
406 where: {

Callers

nothing calls this directly

Calls 1

Tested by

no test coverage detected