MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / performTokenRefresh

Function performTokenRefresh

packages/core/sdk/src/executor.ts:2271–2589  ·  view source on GitHub ↗
(
      row: ConnectionRow,
      provider: CredentialProvider,
      trigger: RefreshTrigger,
    )

Source from the content-addressed store, hash-verified

2269
2270 // Perform the actual refresh-token grant and persist the rotated material.
2271 const performTokenRefresh = (
2272 row: ConnectionRow,
2273 provider: CredentialProvider,
2274 trigger: RefreshTrigger,
2275 ): Effect.Effect<string | null, StorageFailure | CredentialResolutionError> =>
2276 Effect.gen(function* () {
2277 const owner = row.owner as Owner;
2278 const reauth = (message: string): CredentialResolutionError =>
2279 new CredentialResolutionError({
2280 owner,
2281 integration: IntegrationSlug.make(row.integration),
2282 name: ConnectionName.make(row.name),
2283 message,
2284 reauthRequired: true,
2285 });
2286
2287 // A recorded invalid_grant is the AS's standing verdict on this grant:
2288 // re-sending it cannot succeed, so don't. Fail as reauth-required
2289 // without a token request — the reconnect mint rewrites
2290 // `provider_state` and thereby re-arms refresh. Without this gate a
2291 // dead connection re-sent its dead grant on every proactive cycle,
2292 // indefinitely (owner.com's Datadog connections: 100+ identical
2293 // rejections over two days, surfacing nothing).
2294 const reauthState = oauthReauthRequiredFromProviderState(row.provider_state);
2295 if (reauthState !== null) {
2296 yield* Effect.annotateCurrentSpan({ "executor.oauth.refresh.skipped_known_dead": true });
2297 const recordedHealth = Option.getOrNull(decodeLastHealth(row.last_health));
2298 const recordedDetail =
2299 reauthState.oauthReauthRequiredDetail ??
2300 (recordedHealth?.status === "expired" ? recordedHealth.detail : undefined);
2301 const detail =
2302 recordedDetail === undefined
2303 ? "The authorization server rejected this connection's refresh token (invalid_grant). Reconnect to continue."
2304 : recordedDetail.endsWith("Reconnect to continue.")
2305 ? recordedDetail
2306 : `${recordedDetail} Reconnect to continue.`;
2307 return yield* reauth(detail);
2308 }
2309
2310 // Load the backing app. A `first-party:` slug resolves from host config
2311 // (deployment-owned identity, in-memory secret); a stored slug loads by
2312 // the owner STORED on the connection (a Personal connection may be
2313 // backed by a shared Workspace app) — no derivation — with its secret
2314 // resolved out of the credential provider by item id.
2315 const clientSlug = String(row.oauth_client);
2316 const clientRow: RefreshClient | null = yield* Effect.gen(function* () {
2317 if (isFirstPartyOAuthClientSlug(clientSlug)) {
2318 const firstParty = firstPartyOAuthBySlug.get(clientSlug);
2319 if (!firstParty) return null;
2320 return {
2321 clientId: firstParty.clientId,
2322 clientSecret: firstParty.clientSecret,
2323 tokenUrl: firstParty.tokenUrl,
2324 grant: "authorization_code",
2325 // RFC 8707: the SAME resource the authorize/exchange path sent
2326 // (`loadedFirstPartyClient`), so the refreshed token keeps the
2327 // audience the original grant was bound to. Dropping it here
2328 // made refresh asymmetric with authorize for first-party apps.

Callers 1

refreshConnectionTokenFunction · 0.85

Calls 14

refreshAccessTokenFunction · 0.90
reauthFunction · 0.85
loadOAuthClientRowFunction · 0.85
persistRefreshedTokenFunction · 0.85
markRefreshGrantDeadFunction · 0.85

Tested by

no test coverage detected