MCPcopy
hub / github.com/simstudioai/sim / refreshAccessTokenIfNeeded

Function refreshAccessTokenIfNeeded

apps/sim/app/api/auth/oauth/utils.ts:501–586  ·  view source on GitHub ↗
(
  credentialId: string,
  userId: string,
  requestId: string,
  scopes?: string[],
  impersonateEmail?: string
)

Source from the content-addressed store, hash-verified

499 * @returns The valid access token or null if refresh fails
500 */
501export async function refreshAccessTokenIfNeeded(
502 credentialId: string,
503 userId: string,
504 requestId: string,
505 scopes?: string[],
506 impersonateEmail?: string
507): Promise<string | null> {
508 const resolved = await resolveOAuthAccountId(credentialId)
509 if (!resolved) {
510 return null
511 }
512
513 if (resolved.credentialType === 'service_account' && resolved.credentialId) {
514 if (resolved.providerId === ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID) {
515 logger.info(`[${requestId}] Using Atlassian service account token for credential`)
516 return getAtlassianServiceAccountToken(resolved.credentialId)
517 }
518 if (!scopes?.length) {
519 throw new Error('Scopes are required for service account credentials')
520 }
521 logger.info(`[${requestId}] Using service account token for credential`)
522 return getServiceAccountToken(resolved.credentialId, scopes, impersonateEmail)
523 }
524
525 // Use the already-resolved account ID to avoid a redundant resolveOAuthAccountId query
526 const credential = await getCredentialByAccountId(requestId, resolved.accountId, userId)
527
528 if (!credential) {
529 return null
530 }
531
532 // Decide if we should refresh: token missing OR expired
533 const accessTokenExpiresAt = credential.accessTokenExpiresAt
534 const refreshTokenExpiresAt = credential.refreshTokenExpiresAt
535 const now = new Date()
536
537 // Check if access token needs refresh (missing or expired)
538 const accessTokenNeedsRefresh =
539 !!credential.refreshToken &&
540 (!credential.accessToken || (accessTokenExpiresAt && accessTokenExpiresAt <= now))
541
542 // Check if we should proactively refresh to prevent refresh token expiry
543 // This applies to Microsoft providers whose refresh tokens expire after 90 days of inactivity
544 const proactiveRefreshThreshold = new Date(
545 now.getTime() + PROACTIVE_REFRESH_THRESHOLD_DAYS * 24 * 60 * 60 * 1000
546 )
547 const refreshTokenNeedsProactiveRefresh =
548 !!credential.refreshToken &&
549 isMicrosoftProvider(credential.providerId) &&
550 refreshTokenExpiresAt &&
551 refreshTokenExpiresAt <= proactiveRefreshThreshold
552
553 const shouldRefresh = accessTokenNeedsRefresh || refreshTokenNeedsProactiveRefresh
554
555 const accessToken = credential.accessToken
556
557 if (shouldRefresh) {
558 const resolvedCredentialId =

Callers 15

resolveAccessTokenFunction · 0.90
resolveAccessTokenFunction · 0.90
deleteSubscriptionFunction · 0.90
createSubscriptionFunction · 0.90
deleteSubscriptionFunction · 0.90
createSubscriptionFunction · 0.90
deleteSubscriptionFunction · 0.90
createSubscriptionFunction · 0.90
deleteSubscriptionFunction · 0.90
createSubscriptionFunction · 0.90

Calls 8

isMicrosoftProviderFunction · 0.90
resolveOAuthAccountIdFunction · 0.85
getServiceAccountTokenFunction · 0.85
getCredentialByAccountIdFunction · 0.85
performCoalescedRefreshFunction · 0.85
infoMethod · 0.80
errorMethod · 0.80

Tested by

no test coverage detected