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

Function fetchSapConcurAccessToken

apps/sim/app/api/tools/sap_concur/shared.ts:199–274  ·  view source on GitHub ↗
(
  auth: SapConcurAuth,
  requestId: string
)

Source from the content-addressed store, hash-verified

197 * Validates that the geolocation returned by Concur is a safe external URL.
198 */
199export async function fetchSapConcurAccessToken(
200 auth: SapConcurAuth,
201 requestId: string
202): Promise<{ accessToken: string; geolocation: string }> {
203 if (auth.grantType === 'password') {
204 if (!auth.username) throw new Error('username is required for password grant')
205 if (!auth.password) throw new Error('password is required for password grant')
206 }
207
208 const cacheKey = tokenCacheKey(auth)
209 const cached = TOKEN_CACHE.get(cacheKey)
210 if (cached && cached.expiresAt - TOKEN_SAFETY_WINDOW_MS > Date.now()) {
211 return { accessToken: cached.accessToken, geolocation: cached.geolocation }
212 }
213
214 const tokenUrl = assertSafeExternalUrl(
215 `https://${auth.datacenter}/oauth2/v0/token`,
216 'tokenUrl'
217 ).toString()
218
219 const params = new URLSearchParams()
220 params.set('client_id', auth.clientId)
221 params.set('client_secret', auth.clientSecret)
222 params.set('grant_type', auth.grantType)
223 if (auth.grantType === 'password') {
224 params.set('username', auth.username ?? '')
225 params.set('password', auth.password ?? '')
226 if (auth.companyUuid) params.set('credtype', 'authtoken')
227 }
228
229 const response = await secureFetchWithValidation(
230 tokenUrl,
231 {
232 method: 'POST',
233 headers: {
234 'Content-Type': 'application/x-www-form-urlencoded',
235 Accept: 'application/json',
236 },
237 body: params.toString(),
238 timeout: SAP_CONCUR_OUTBOUND_FETCH_TIMEOUT_MS,
239 },
240 'tokenUrl'
241 )
242
243 if (!response.ok) {
244 const text = await response.text().catch(() => '')
245 logger.warn(`[${requestId}] Concur token fetch failed (${response.status}): ${text}`)
246 throw new Error(`Concur token request failed: HTTP ${response.status}`)
247 }
248
249 const data = (await response.json()) as {
250 access_token?: string
251 expires_in?: number
252 geolocation?: string
253 }
254
255 if (!data.access_token) {
256 throw new Error('Concur token response missing access_token')

Callers 2

route.tsFile · 0.90
route.tsFile · 0.90

Calls 10

assertSafeExternalUrlFunction · 0.85
normalizeGeolocationFunction · 0.85
textMethod · 0.80
tokenCacheKeyFunction · 0.70
rememberTokenFunction · 0.70
getMethod · 0.65
setMethod · 0.65
warnMethod · 0.65
toStringMethod · 0.45

Tested by

no test coverage detected