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

Function performTokenRefresh

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

Source from the content-addressed store, hash-verified

1802
1803 // Perform the actual refresh-token grant and persist the rotated material.
1804 const performTokenRefresh = (
1805 row: ConnectionRow,
1806 provider: CredentialProvider,
1807 trigger: RefreshTrigger,
1808 ): Effect.Effect<string | null, StorageFailure | CredentialResolutionError> =>
1809 Effect.gen(function* () {
1810 const owner = row.owner as Owner;
1811 const reauth = (message: string): CredentialResolutionError =>
1812 new CredentialResolutionError({
1813 owner,
1814 integration: IntegrationSlug.make(row.integration),
1815 name: ConnectionName.make(row.name),
1816 message,
1817 reauthRequired: true,
1818 });
1819
1820 // A recorded invalid_grant is the AS's standing verdict on this grant:
1821 // re-sending it cannot succeed, so don't. Fail as reauth-required
1822 // without a token request — the reconnect mint rewrites
1823 // `provider_state` and thereby re-arms refresh. Without this gate a
1824 // dead connection re-sent its dead grant on every proactive cycle,
1825 // indefinitely (owner.com's Datadog connections: 100+ identical
1826 // rejections over two days, surfacing nothing).
1827 const reauthState = oauthReauthRequiredFromProviderState(row.provider_state);
1828 if (reauthState !== null) {
1829 yield* Effect.annotateCurrentSpan({ "executor.oauth.refresh.skipped_known_dead": true });
1830 const recordedHealth = Option.getOrNull(decodeLastHealth(row.last_health));
1831 const recordedDetail =
1832 reauthState.oauthReauthRequiredDetail ??
1833 (recordedHealth?.status === "expired" ? recordedHealth.detail : undefined);
1834 const detail =
1835 recordedDetail === undefined
1836 ? "The authorization server rejected this connection's refresh token (invalid_grant). Reconnect to continue."
1837 : recordedDetail.endsWith("Reconnect to continue.")
1838 ? recordedDetail
1839 : `${recordedDetail} Reconnect to continue.`;
1840 return yield* reauth(detail);
1841 }
1842
1843 // Load the backing app by the owner STORED on the connection (a Personal
1844 // connection may be backed by a shared Workspace app) — no derivation.
1845 const clientOwner = (row.oauth_client_owner ?? row.owner) as Owner;
1846 const clientRow = yield* loadOAuthClientRow(clientOwner, String(row.oauth_client));
1847 if (!clientRow) {
1848 return yield* reauth(`OAuth client "${row.oauth_client}" is no longer registered.`);
1849 }
1850
1851 // The secret is stored in the provider (a vault item id), not inline.
1852 const clientSecret = clientRow.client_secret_item_id
1853 ? ((yield* provider.get(ProviderItemId.make(String(clientRow.client_secret_item_id)))) ??
1854 "")
1855 : "";
1856 // Re-request the scopes this connection was GRANTED (RFC 6749 §6: a
1857 // refresh must not exceed the originally-granted scope). Empty → omit
1858 // the param, which the AS treats as "same scopes as granted".
1859 const grantedScopes = row.oauth_scope
1860 ? String(row.oauth_scope).split(/\s+/).filter(Boolean)
1861 : [];

Callers 1

refreshConnectionTokenFunction · 0.85

Calls 10

refreshAccessTokenFunction · 0.90
reauthFunction · 0.85
loadOAuthClientRowFunction · 0.85
markRefreshGrantDeadFunction · 0.85
connectionItemIdsFunction · 0.85
byOwnerFunction · 0.85
setMethod · 0.80
getMethod · 0.65

Tested by

no test coverage detected