MCPcopy Index your code
hub / github.com/simstudioai/sim / getServiceAccountToken

Function getServiceAccountToken

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

Source from the content-addressed store, hash-verified

124 * authenticates directly with its own IAM permissions.
125 */
126export async function getServiceAccountToken(
127 credentialId: string,
128 scopes: string[],
129 impersonateEmail?: string
130): Promise<string> {
131 const [credentialRow] = await db
132 .select({
133 encryptedServiceAccountKey: credential.encryptedServiceAccountKey,
134 })
135 .from(credential)
136 .where(eq(credential.id, credentialId))
137 .limit(1)
138
139 if (!credentialRow?.encryptedServiceAccountKey) {
140 throw new Error('Service account key not found')
141 }
142
143 const { decrypted } = await decryptSecret(credentialRow.encryptedServiceAccountKey)
144 const keyData = JSON.parse(decrypted) as {
145 client_email: string
146 private_key: string
147 token_uri?: string
148 }
149
150 const filteredScopes = scopes.filter((s) => !SA_EXCLUDED_SCOPES.has(s))
151
152 const now = Math.floor(Date.now() / 1000)
153 const ALLOWED_TOKEN_URIS = new Set(['https://oauth2.googleapis.com/token'])
154 const tokenUri =
155 keyData.token_uri && ALLOWED_TOKEN_URIS.has(keyData.token_uri)
156 ? keyData.token_uri
157 : 'https://oauth2.googleapis.com/token'
158
159 const header = { alg: 'RS256', typ: 'JWT' }
160 const payload: Record<string, unknown> = {
161 iss: keyData.client_email,
162 scope: filteredScopes.join(' '),
163 aud: tokenUri,
164 iat: now,
165 exp: now + 3600,
166 }
167
168 if (impersonateEmail) {
169 payload.sub = impersonateEmail
170 }
171
172 logger.info('Service account JWT payload', {
173 iss: keyData.client_email,
174 sub: impersonateEmail || '(none)',
175 scopes: filteredScopes.join(' '),
176 aud: tokenUri,
177 })
178
179 const toBase64Url = (obj: unknown) => Buffer.from(JSON.stringify(obj)).toString('base64url')
180
181 const signingInput = `${toBase64Url(header)}.${toBase64Url(payload)}`
182
183 const signer = createSign('RSA-SHA256')

Callers 5

route.tsFile · 0.90
resolveVertexCredentialFunction · 0.90
route.tsFile · 0.90
resolveVertexCredentialFunction · 0.90

Calls 8

decryptSecretFunction · 0.90
parseMethod · 0.80
joinMethod · 0.80
infoMethod · 0.80
textMethod · 0.80
errorMethod · 0.80
toBase64UrlFunction · 0.70
eqFunction · 0.50

Tested by

no test coverage detected