@tangle-network/agent-integrations 0.53.49 → 0.53.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog.js +4 -4
- package/dist/{chunk-H5UCSRF4.js → chunk-2JRYKWYX.js} +441 -216
- package/dist/{chunk-H5UCSRF4.js.map → chunk-2JRYKWYX.js.map} +1 -1
- package/dist/{chunk-5UCHLQ3D.js → chunk-EP6EDAPV.js} +2 -2
- package/dist/{chunk-ZSXRS7D7.js → chunk-QE4WFYSK.js} +2 -2
- package/dist/{chunk-GUZA3U6T.js → chunk-T3WH6MMA.js} +26 -24
- package/dist/chunk-T3WH6MMA.js.map +1 -0
- package/dist/connectors/adapters/index.js +1 -1
- package/dist/connectors/index.d.ts +5 -1
- package/dist/connectors/index.js +10 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -4
- package/dist/mcp.js +4 -4
- package/dist/registry.js +4 -4
- package/dist/runtime.js +4 -4
- package/dist/specs.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-GUZA3U6T.js.map +0 -1
- /package/dist/{chunk-5UCHLQ3D.js.map → chunk-EP6EDAPV.js.map} +0 -0
- /package/dist/{chunk-ZSXRS7D7.js.map → chunk-QE4WFYSK.js.map} +0 -0
|
@@ -1645,7 +1645,325 @@ function membershipCapability(name, method, description) {
|
|
|
1645
1645
|
}
|
|
1646
1646
|
|
|
1647
1647
|
// src/connectors/adapters/client-credentials-rest.ts
|
|
1648
|
-
import { createHash as
|
|
1648
|
+
import { createHash as createHash3 } from "crypto";
|
|
1649
|
+
|
|
1650
|
+
// src/connectors/oauth.ts
|
|
1651
|
+
import { createHash as createHash2, randomBytes } from "crypto";
|
|
1652
|
+
var PENDING_TTL_MS = 10 * 60 * 1e3;
|
|
1653
|
+
var InMemoryOAuthFlowStore = class {
|
|
1654
|
+
pendingFlows = /* @__PURE__ */ new Map();
|
|
1655
|
+
put(state, flow) {
|
|
1656
|
+
this.pendingFlows.set(state, flow);
|
|
1657
|
+
}
|
|
1658
|
+
consume(state) {
|
|
1659
|
+
const flow = this.pendingFlows.get(state);
|
|
1660
|
+
this.pendingFlows.delete(state);
|
|
1661
|
+
if (!flow || flow.expiresAt <= Date.now()) return void 0;
|
|
1662
|
+
return flow;
|
|
1663
|
+
}
|
|
1664
|
+
sweep(now) {
|
|
1665
|
+
for (const [k, v] of this.pendingFlows) {
|
|
1666
|
+
if (v.expiresAt <= now) this.pendingFlows.delete(k);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
clear() {
|
|
1670
|
+
this.pendingFlows.clear();
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
var defaultFlowStore = new InMemoryOAuthFlowStore();
|
|
1674
|
+
function startOAuthFlow(input) {
|
|
1675
|
+
const store = input.store ?? defaultFlowStore;
|
|
1676
|
+
const now = input.now ?? Date.now();
|
|
1677
|
+
store.sweep?.(now);
|
|
1678
|
+
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
1679
|
+
const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
|
|
1680
|
+
const codeChallenge = codeVerifier ? base64Url(createHash2("sha256").update(codeVerifier).digest()) : void 0;
|
|
1681
|
+
const state = base64Url(randomBytes(24));
|
|
1682
|
+
store.put(state, {
|
|
1683
|
+
codeVerifier,
|
|
1684
|
+
state,
|
|
1685
|
+
projectId: input.projectId,
|
|
1686
|
+
kind: input.kind,
|
|
1687
|
+
label: input.label,
|
|
1688
|
+
redirectUri: input.redirectUri,
|
|
1689
|
+
expiresAt: now + PENDING_TTL_MS
|
|
1690
|
+
});
|
|
1691
|
+
const url = new URL(input.authorizationUrl);
|
|
1692
|
+
url.searchParams.set("response_type", "code");
|
|
1693
|
+
url.searchParams.set(
|
|
1694
|
+
oauthParameterName(input.authorizationClientIdParam, "client_id"),
|
|
1695
|
+
input.clientId
|
|
1696
|
+
);
|
|
1697
|
+
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
1698
|
+
url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
|
|
1699
|
+
url.searchParams.set("state", state);
|
|
1700
|
+
if (input.extraAuthParams) {
|
|
1701
|
+
for (const [k, v] of Object.entries(input.extraAuthParams)) {
|
|
1702
|
+
url.searchParams.set(k, v);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
if (codeChallenge) {
|
|
1706
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
1707
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
1708
|
+
} else {
|
|
1709
|
+
url.searchParams.delete("code_challenge");
|
|
1710
|
+
url.searchParams.delete("code_challenge_method");
|
|
1711
|
+
}
|
|
1712
|
+
return { authorizationUrl: url.toString(), state };
|
|
1713
|
+
}
|
|
1714
|
+
async function consumePendingFlow(state, store = defaultFlowStore) {
|
|
1715
|
+
await store.sweep?.(Date.now());
|
|
1716
|
+
const flow = await store.consume(state);
|
|
1717
|
+
if (!flow) {
|
|
1718
|
+
throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
|
|
1719
|
+
}
|
|
1720
|
+
return flow;
|
|
1721
|
+
}
|
|
1722
|
+
async function exchangeAuthorizationCode(input) {
|
|
1723
|
+
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
1724
|
+
if (usePkce && !input.codeVerifier) {
|
|
1725
|
+
throw new Error("OAuth token exchange requires a PKCE code_verifier");
|
|
1726
|
+
}
|
|
1727
|
+
const body = new URLSearchParams({
|
|
1728
|
+
grant_type: "authorization_code",
|
|
1729
|
+
code: input.code,
|
|
1730
|
+
redirect_uri: input.redirectUri
|
|
1731
|
+
});
|
|
1732
|
+
if (usePkce) body.set("code_verifier", input.codeVerifier);
|
|
1733
|
+
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
1734
|
+
applyTokenClientAuthentication(input, body, headers);
|
|
1735
|
+
const redactionValues = [
|
|
1736
|
+
input.code,
|
|
1737
|
+
...input.codeVerifier ? [input.codeVerifier] : [],
|
|
1738
|
+
...oauthClientCredentialRedactionValues(
|
|
1739
|
+
input.clientId,
|
|
1740
|
+
input.clientSecret,
|
|
1741
|
+
headers.authorization
|
|
1742
|
+
)
|
|
1743
|
+
];
|
|
1744
|
+
let res;
|
|
1745
|
+
try {
|
|
1746
|
+
res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
1747
|
+
method: "POST",
|
|
1748
|
+
headers,
|
|
1749
|
+
body,
|
|
1750
|
+
signal: input.signal
|
|
1751
|
+
});
|
|
1752
|
+
} catch (cause) {
|
|
1753
|
+
const detail = redactOAuthSensitiveText(
|
|
1754
|
+
cause?.message ?? "unknown",
|
|
1755
|
+
redactionValues
|
|
1756
|
+
);
|
|
1757
|
+
throw new Error(`OAuth token exchange transport error: ${detail}`);
|
|
1758
|
+
}
|
|
1759
|
+
if (!res.ok) {
|
|
1760
|
+
const text = await res.text().catch(() => "");
|
|
1761
|
+
const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
|
|
1762
|
+
const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
|
|
1763
|
+
throw new Error(
|
|
1764
|
+
`OAuth token exchange failed: ${res.status} ${statusText} \u2014 ${detail}`
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
let json;
|
|
1768
|
+
try {
|
|
1769
|
+
json = await res.json();
|
|
1770
|
+
} catch {
|
|
1771
|
+
throw new Error("OAuth token exchange returned invalid JSON");
|
|
1772
|
+
}
|
|
1773
|
+
return {
|
|
1774
|
+
accessToken: json.access_token,
|
|
1775
|
+
refreshToken: json.refresh_token,
|
|
1776
|
+
expiresIn: json.expires_in,
|
|
1777
|
+
scope: json.scope,
|
|
1778
|
+
tokenType: json.token_type,
|
|
1779
|
+
idToken: json.id_token
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
async function refreshAccessToken(input) {
|
|
1783
|
+
const body = new URLSearchParams({
|
|
1784
|
+
grant_type: "refresh_token",
|
|
1785
|
+
refresh_token: input.refreshToken
|
|
1786
|
+
});
|
|
1787
|
+
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
1788
|
+
applyTokenClientAuthentication(input, body, headers);
|
|
1789
|
+
const redactionValues = [
|
|
1790
|
+
input.refreshToken,
|
|
1791
|
+
...oauthClientCredentialRedactionValues(
|
|
1792
|
+
input.clientId,
|
|
1793
|
+
input.clientSecret,
|
|
1794
|
+
headers.authorization
|
|
1795
|
+
)
|
|
1796
|
+
];
|
|
1797
|
+
let res;
|
|
1798
|
+
try {
|
|
1799
|
+
res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
1800
|
+
method: "POST",
|
|
1801
|
+
headers,
|
|
1802
|
+
body,
|
|
1803
|
+
signal: input.signal
|
|
1804
|
+
});
|
|
1805
|
+
} catch (cause) {
|
|
1806
|
+
const detail = redactOAuthSensitiveText(
|
|
1807
|
+
cause?.message ?? "unknown",
|
|
1808
|
+
redactionValues
|
|
1809
|
+
);
|
|
1810
|
+
throw new Error(`OAuth refresh transport error: ${detail}`);
|
|
1811
|
+
}
|
|
1812
|
+
if (!res.ok) {
|
|
1813
|
+
const text = await res.text().catch(() => "");
|
|
1814
|
+
const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
|
|
1815
|
+
const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
|
|
1816
|
+
throw new Error(`OAuth refresh failed: ${res.status} ${statusText} \u2014 ${detail}`);
|
|
1817
|
+
}
|
|
1818
|
+
let json;
|
|
1819
|
+
try {
|
|
1820
|
+
json = await res.json();
|
|
1821
|
+
} catch {
|
|
1822
|
+
throw new Error("OAuth refresh returned invalid JSON");
|
|
1823
|
+
}
|
|
1824
|
+
return {
|
|
1825
|
+
accessToken: json.access_token,
|
|
1826
|
+
// Some providers omit refresh_token on refresh — keep the previous one
|
|
1827
|
+
// in that case (caller passes through if undefined).
|
|
1828
|
+
refreshToken: json.refresh_token,
|
|
1829
|
+
expiresIn: json.expires_in,
|
|
1830
|
+
scope: json.scope,
|
|
1831
|
+
tokenType: json.token_type,
|
|
1832
|
+
idToken: json.id_token
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
function createOAuthTokenRequestHeaders(additional) {
|
|
1836
|
+
const headers = new Headers(additional);
|
|
1837
|
+
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
1838
|
+
headers.set("accept", "application/json");
|
|
1839
|
+
headers.delete("authorization");
|
|
1840
|
+
return Object.fromEntries(headers.entries());
|
|
1841
|
+
}
|
|
1842
|
+
function formEncodeOAuthClientCredential(value) {
|
|
1843
|
+
return new URLSearchParams({ value }).toString().slice("value=".length);
|
|
1844
|
+
}
|
|
1845
|
+
function createOAuthBasicAuthorizationHeader(clientId, clientSecret, encodeBase64 = defaultOAuthBase64Encode) {
|
|
1846
|
+
const encodedClientId = formEncodeOAuthClientCredential(clientId);
|
|
1847
|
+
const encodedClientSecret = formEncodeOAuthClientCredential(clientSecret);
|
|
1848
|
+
return `Basic ${encodeBase64(`${encodedClientId}:${encodedClientSecret}`)}`;
|
|
1849
|
+
}
|
|
1850
|
+
function defaultOAuthBase64Encode(value) {
|
|
1851
|
+
const encode = globalThis.btoa;
|
|
1852
|
+
if (typeof encode !== "function") {
|
|
1853
|
+
throw new Error(
|
|
1854
|
+
"OAuth client_secret_basic requires a base64 encoder in this runtime."
|
|
1855
|
+
);
|
|
1856
|
+
}
|
|
1857
|
+
return encode(value);
|
|
1858
|
+
}
|
|
1859
|
+
function oauthClientCredentialRedactionValues(clientId, clientSecret, authorization) {
|
|
1860
|
+
return [
|
|
1861
|
+
clientId,
|
|
1862
|
+
...clientSecret ? [clientSecret] : [],
|
|
1863
|
+
...authorization ? [
|
|
1864
|
+
authorization,
|
|
1865
|
+
...authorization.startsWith("Basic ") ? [authorization.slice("Basic ".length)] : []
|
|
1866
|
+
] : []
|
|
1867
|
+
];
|
|
1868
|
+
}
|
|
1869
|
+
function redactOAuthSensitiveText(text, secrets) {
|
|
1870
|
+
const matchers = /* @__PURE__ */ new Map();
|
|
1871
|
+
for (const secret of new Set(secrets)) {
|
|
1872
|
+
if (secret.length === 0) continue;
|
|
1873
|
+
addOAuthRedactionMatcher(matchers, escapeRegExp(secret), secret.length);
|
|
1874
|
+
const jsonEscaped = JSON.stringify(secret).slice(1, -1);
|
|
1875
|
+
addOAuthRedactionMatcher(
|
|
1876
|
+
matchers,
|
|
1877
|
+
escapeRegExp(jsonEscaped),
|
|
1878
|
+
jsonEscaped.length
|
|
1879
|
+
);
|
|
1880
|
+
const formEncoded = formEncodeOAuthClientCredential(secret);
|
|
1881
|
+
addOAuthRedactionMatcher(
|
|
1882
|
+
matchers,
|
|
1883
|
+
formEncodedRedactionPattern(formEncoded),
|
|
1884
|
+
Math.max(formEncoded.length, formEncoded.replaceAll("+", "%20").length)
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1887
|
+
return [...matchers.values()].sort((left, right) => right.representedLength - left.representedLength).reduce(
|
|
1888
|
+
(redacted, matcher) => redacted.replace(matcher.pattern, "[REDACTED]"),
|
|
1889
|
+
text
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
function addOAuthRedactionMatcher(matchers, source, representedLength) {
|
|
1893
|
+
const existing = matchers.get(source);
|
|
1894
|
+
if (existing && existing.representedLength >= representedLength) return;
|
|
1895
|
+
matchers.set(source, {
|
|
1896
|
+
pattern: new RegExp(source, "g"),
|
|
1897
|
+
representedLength
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
function formEncodedRedactionPattern(formEncoded) {
|
|
1901
|
+
let pattern = "";
|
|
1902
|
+
for (let index = 0; index < formEncoded.length; index += 1) {
|
|
1903
|
+
const character = formEncoded[index];
|
|
1904
|
+
const encodedByte = formEncoded.slice(index + 1, index + 3);
|
|
1905
|
+
if (character === "%" && /^[0-9A-F]{2}$/.test(encodedByte)) {
|
|
1906
|
+
pattern += `%${percentEncodedBytePattern(encodedByte)}`;
|
|
1907
|
+
index += 2;
|
|
1908
|
+
continue;
|
|
1909
|
+
}
|
|
1910
|
+
if (character === "+") {
|
|
1911
|
+
pattern += "(?:\\+|%20)";
|
|
1912
|
+
continue;
|
|
1913
|
+
}
|
|
1914
|
+
pattern += escapeRegExp(character);
|
|
1915
|
+
}
|
|
1916
|
+
return pattern;
|
|
1917
|
+
}
|
|
1918
|
+
function percentEncodedBytePattern(encodedByte) {
|
|
1919
|
+
return [...encodedByte].map(
|
|
1920
|
+
(character) => /[A-F]/.test(character) ? `[${character}${character.toLowerCase()}]` : character
|
|
1921
|
+
).join("");
|
|
1922
|
+
}
|
|
1923
|
+
function escapeRegExp(value) {
|
|
1924
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1925
|
+
}
|
|
1926
|
+
function applyTokenClientAuthentication(input, body, headers) {
|
|
1927
|
+
const method = input.tokenClientAuthMethod ?? "client_secret_post";
|
|
1928
|
+
if (method === "none") {
|
|
1929
|
+
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
if (!input.clientSecret) {
|
|
1933
|
+
throw new Error(`OAuth ${method} client authentication requires a client secret`);
|
|
1934
|
+
}
|
|
1935
|
+
if (method === "client_secret_post") {
|
|
1936
|
+
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
1937
|
+
body.set(
|
|
1938
|
+
oauthParameterName(input.tokenClientSecretParam, "client_secret"),
|
|
1939
|
+
input.clientSecret
|
|
1940
|
+
);
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
if (method === "client_secret_basic") {
|
|
1944
|
+
headers.authorization = createOAuthBasicAuthorizationHeader(
|
|
1945
|
+
input.clientId,
|
|
1946
|
+
input.clientSecret
|
|
1947
|
+
);
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
throw new Error("Unsupported OAuth token client authentication method");
|
|
1951
|
+
}
|
|
1952
|
+
function base64Url(buf) {
|
|
1953
|
+
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1954
|
+
}
|
|
1955
|
+
function oauthParameterName(value, fallback) {
|
|
1956
|
+
const name = value ?? fallback;
|
|
1957
|
+
if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
|
|
1958
|
+
throw new Error("Invalid OAuth parameter name");
|
|
1959
|
+
}
|
|
1960
|
+
return name;
|
|
1961
|
+
}
|
|
1962
|
+
function _resetPendingFlowsForTests() {
|
|
1963
|
+
defaultFlowStore.clear?.();
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
// src/connectors/adapters/client-credentials-rest.ts
|
|
1649
1967
|
function clientCredentialsRestConnector(spec) {
|
|
1650
1968
|
const regionMetadataKey = spec.regionMetadataKey ?? "region";
|
|
1651
1969
|
const delegated = declarativeRestConnector({
|
|
@@ -1764,7 +2082,7 @@ function readRegionName(bundle, metadata, metadataKey, fallback) {
|
|
|
1764
2082
|
return (bundle.region ?? metadataRegion ?? fallback).toLowerCase().trim();
|
|
1765
2083
|
}
|
|
1766
2084
|
function credentialFingerprint(bundle, region, scope) {
|
|
1767
|
-
return
|
|
2085
|
+
return createHash3("sha256").update(bundle.clientId).update("\0").update(bundle.clientSecret).update("\0").update(region.tokenUrl).update("\0").update(scope ?? "").digest("hex");
|
|
1768
2086
|
}
|
|
1769
2087
|
function renderConnectionMetadata(template, metadata) {
|
|
1770
2088
|
const rendered = template.replace(/\{connection\.([a-zA-Z0-9_.-]+)\}/g, (_match, key) => {
|
|
@@ -1795,7 +2113,10 @@ async function exchangeClientCredentials(displayName, sourceId, bundle, region,
|
|
|
1795
2113
|
"content-type": "application/x-www-form-urlencoded"
|
|
1796
2114
|
};
|
|
1797
2115
|
if (credentialPlacement === "basic") {
|
|
1798
|
-
headers.authorization =
|
|
2116
|
+
headers.authorization = createOAuthBasicAuthorizationHeader(
|
|
2117
|
+
bundle.clientId,
|
|
2118
|
+
bundle.clientSecret
|
|
2119
|
+
);
|
|
1799
2120
|
}
|
|
1800
2121
|
const response = await fetch(region.tokenUrl, {
|
|
1801
2122
|
method: "POST",
|
|
@@ -16148,187 +16469,6 @@ var pushbulletConnector = declarativeRestConnector({
|
|
|
16148
16469
|
]
|
|
16149
16470
|
});
|
|
16150
16471
|
|
|
16151
|
-
// src/connectors/oauth.ts
|
|
16152
|
-
import { createHash as createHash3, randomBytes } from "crypto";
|
|
16153
|
-
var PENDING_TTL_MS = 10 * 60 * 1e3;
|
|
16154
|
-
var InMemoryOAuthFlowStore = class {
|
|
16155
|
-
pendingFlows = /* @__PURE__ */ new Map();
|
|
16156
|
-
put(state, flow) {
|
|
16157
|
-
this.pendingFlows.set(state, flow);
|
|
16158
|
-
}
|
|
16159
|
-
consume(state) {
|
|
16160
|
-
const flow = this.pendingFlows.get(state);
|
|
16161
|
-
this.pendingFlows.delete(state);
|
|
16162
|
-
if (!flow || flow.expiresAt <= Date.now()) return void 0;
|
|
16163
|
-
return flow;
|
|
16164
|
-
}
|
|
16165
|
-
sweep(now) {
|
|
16166
|
-
for (const [k, v] of this.pendingFlows) {
|
|
16167
|
-
if (v.expiresAt <= now) this.pendingFlows.delete(k);
|
|
16168
|
-
}
|
|
16169
|
-
}
|
|
16170
|
-
clear() {
|
|
16171
|
-
this.pendingFlows.clear();
|
|
16172
|
-
}
|
|
16173
|
-
};
|
|
16174
|
-
var defaultFlowStore = new InMemoryOAuthFlowStore();
|
|
16175
|
-
function startOAuthFlow(input) {
|
|
16176
|
-
const store = input.store ?? defaultFlowStore;
|
|
16177
|
-
const now = input.now ?? Date.now();
|
|
16178
|
-
store.sweep?.(now);
|
|
16179
|
-
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
16180
|
-
const codeVerifier = usePkce ? base64Url(randomBytes(48)) : void 0;
|
|
16181
|
-
const codeChallenge = codeVerifier ? base64Url(createHash3("sha256").update(codeVerifier).digest()) : void 0;
|
|
16182
|
-
const state = base64Url(randomBytes(24));
|
|
16183
|
-
store.put(state, {
|
|
16184
|
-
codeVerifier,
|
|
16185
|
-
state,
|
|
16186
|
-
projectId: input.projectId,
|
|
16187
|
-
kind: input.kind,
|
|
16188
|
-
label: input.label,
|
|
16189
|
-
redirectUri: input.redirectUri,
|
|
16190
|
-
expiresAt: now + PENDING_TTL_MS
|
|
16191
|
-
});
|
|
16192
|
-
const url = new URL(input.authorizationUrl);
|
|
16193
|
-
url.searchParams.set("response_type", "code");
|
|
16194
|
-
url.searchParams.set(
|
|
16195
|
-
oauthParameterName(input.authorizationClientIdParam, "client_id"),
|
|
16196
|
-
input.clientId
|
|
16197
|
-
);
|
|
16198
|
-
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
16199
|
-
url.searchParams.set("scope", input.scopes.join(input.scopeSeparator ?? " "));
|
|
16200
|
-
url.searchParams.set("state", state);
|
|
16201
|
-
if (input.extraAuthParams) {
|
|
16202
|
-
for (const [k, v] of Object.entries(input.extraAuthParams)) {
|
|
16203
|
-
url.searchParams.set(k, v);
|
|
16204
|
-
}
|
|
16205
|
-
}
|
|
16206
|
-
if (codeChallenge) {
|
|
16207
|
-
url.searchParams.set("code_challenge", codeChallenge);
|
|
16208
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
16209
|
-
} else {
|
|
16210
|
-
url.searchParams.delete("code_challenge");
|
|
16211
|
-
url.searchParams.delete("code_challenge_method");
|
|
16212
|
-
}
|
|
16213
|
-
return { authorizationUrl: url.toString(), state };
|
|
16214
|
-
}
|
|
16215
|
-
async function consumePendingFlow(state, store = defaultFlowStore) {
|
|
16216
|
-
await store.sweep?.(Date.now());
|
|
16217
|
-
const flow = await store.consume(state);
|
|
16218
|
-
if (!flow) {
|
|
16219
|
-
throw new Error("Unknown or expired OAuth state: possible CSRF, replay, or stale flow");
|
|
16220
|
-
}
|
|
16221
|
-
return flow;
|
|
16222
|
-
}
|
|
16223
|
-
async function exchangeAuthorizationCode(input) {
|
|
16224
|
-
const usePkce = (input.pkce ?? "required") !== "unsupported";
|
|
16225
|
-
if (usePkce && !input.codeVerifier) {
|
|
16226
|
-
throw new Error("OAuth token exchange requires a PKCE code_verifier");
|
|
16227
|
-
}
|
|
16228
|
-
const body = new URLSearchParams({
|
|
16229
|
-
grant_type: "authorization_code",
|
|
16230
|
-
code: input.code,
|
|
16231
|
-
redirect_uri: input.redirectUri
|
|
16232
|
-
});
|
|
16233
|
-
if (usePkce) body.set("code_verifier", input.codeVerifier);
|
|
16234
|
-
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
16235
|
-
applyTokenClientAuthentication(input, body, headers);
|
|
16236
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
16237
|
-
method: "POST",
|
|
16238
|
-
headers,
|
|
16239
|
-
body,
|
|
16240
|
-
signal: input.signal
|
|
16241
|
-
});
|
|
16242
|
-
if (!res.ok) {
|
|
16243
|
-
const text = await res.text().catch(() => "");
|
|
16244
|
-
throw new Error(`OAuth token exchange failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
16245
|
-
}
|
|
16246
|
-
const json = await res.json();
|
|
16247
|
-
return {
|
|
16248
|
-
accessToken: json.access_token,
|
|
16249
|
-
refreshToken: json.refresh_token,
|
|
16250
|
-
expiresIn: json.expires_in,
|
|
16251
|
-
scope: json.scope,
|
|
16252
|
-
tokenType: json.token_type,
|
|
16253
|
-
idToken: json.id_token
|
|
16254
|
-
};
|
|
16255
|
-
}
|
|
16256
|
-
async function refreshAccessToken(input) {
|
|
16257
|
-
const body = new URLSearchParams({
|
|
16258
|
-
grant_type: "refresh_token",
|
|
16259
|
-
refresh_token: input.refreshToken
|
|
16260
|
-
});
|
|
16261
|
-
const headers = createOAuthTokenRequestHeaders(input.tokenRequestHeaders);
|
|
16262
|
-
applyTokenClientAuthentication(input, body, headers);
|
|
16263
|
-
const res = await (input.fetchImpl ?? fetch)(input.tokenUrl, {
|
|
16264
|
-
method: "POST",
|
|
16265
|
-
headers,
|
|
16266
|
-
body,
|
|
16267
|
-
signal: input.signal
|
|
16268
|
-
});
|
|
16269
|
-
if (!res.ok) {
|
|
16270
|
-
const text = await res.text().catch(() => "");
|
|
16271
|
-
throw new Error(`OAuth refresh failed: ${res.status} ${res.statusText} \u2014 ${text.slice(0, 200)}`);
|
|
16272
|
-
}
|
|
16273
|
-
const json = await res.json();
|
|
16274
|
-
return {
|
|
16275
|
-
accessToken: json.access_token,
|
|
16276
|
-
// Some providers omit refresh_token on refresh — keep the previous one
|
|
16277
|
-
// in that case (caller passes through if undefined).
|
|
16278
|
-
refreshToken: json.refresh_token,
|
|
16279
|
-
expiresIn: json.expires_in,
|
|
16280
|
-
scope: json.scope,
|
|
16281
|
-
tokenType: json.token_type,
|
|
16282
|
-
idToken: json.id_token
|
|
16283
|
-
};
|
|
16284
|
-
}
|
|
16285
|
-
function createOAuthTokenRequestHeaders(additional) {
|
|
16286
|
-
const headers = new Headers(additional);
|
|
16287
|
-
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
16288
|
-
headers.set("accept", "application/json");
|
|
16289
|
-
headers.delete("authorization");
|
|
16290
|
-
return Object.fromEntries(headers.entries());
|
|
16291
|
-
}
|
|
16292
|
-
function applyTokenClientAuthentication(input, body, headers) {
|
|
16293
|
-
const method = input.tokenClientAuthMethod ?? "client_secret_post";
|
|
16294
|
-
if (method === "none") {
|
|
16295
|
-
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
16296
|
-
return;
|
|
16297
|
-
}
|
|
16298
|
-
if (!input.clientSecret) {
|
|
16299
|
-
throw new Error(`OAuth ${method} client authentication requires a client secret`);
|
|
16300
|
-
}
|
|
16301
|
-
if (method === "client_secret_post") {
|
|
16302
|
-
body.set(oauthParameterName(input.tokenClientIdParam, "client_id"), input.clientId);
|
|
16303
|
-
body.set(
|
|
16304
|
-
oauthParameterName(input.tokenClientSecretParam, "client_secret"),
|
|
16305
|
-
input.clientSecret
|
|
16306
|
-
);
|
|
16307
|
-
return;
|
|
16308
|
-
}
|
|
16309
|
-
if (method === "client_secret_basic") {
|
|
16310
|
-
headers.authorization = `Basic ${Buffer.from(
|
|
16311
|
-
`${input.clientId}:${input.clientSecret}`,
|
|
16312
|
-
"utf8"
|
|
16313
|
-
).toString("base64")}`;
|
|
16314
|
-
return;
|
|
16315
|
-
}
|
|
16316
|
-
throw new Error("Unsupported OAuth token client authentication method");
|
|
16317
|
-
}
|
|
16318
|
-
function base64Url(buf) {
|
|
16319
|
-
return buf.toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
16320
|
-
}
|
|
16321
|
-
function oauthParameterName(value, fallback) {
|
|
16322
|
-
const name = value ?? fallback;
|
|
16323
|
-
if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name)) {
|
|
16324
|
-
throw new Error("Invalid OAuth parameter name");
|
|
16325
|
-
}
|
|
16326
|
-
return name;
|
|
16327
|
-
}
|
|
16328
|
-
function _resetPendingFlowsForTests() {
|
|
16329
|
-
defaultFlowStore.clear?.();
|
|
16330
|
-
}
|
|
16331
|
-
|
|
16332
16472
|
// src/connectors/adapters/reddit.ts
|
|
16333
16473
|
var REDDIT_USER_AGENT = "web:tools.tangle.integration-hub:v1.0 (contact: https://tangle.tools)";
|
|
16334
16474
|
var REDDIT_TOKEN_URL = "https://www.reddit.com/api/v1/access_token";
|
|
@@ -56026,6 +56166,7 @@ var NOTION_SPEC = {
|
|
|
56026
56166
|
scopes: [],
|
|
56027
56167
|
clientIdEnv: "NOTION_OAUTH_CLIENT_ID",
|
|
56028
56168
|
clientSecretEnv: "NOTION_OAUTH_CLIENT_SECRET",
|
|
56169
|
+
tokenClientAuthMethod: "client_secret_basic",
|
|
56029
56170
|
extraAuthParams: { owner: "user" }
|
|
56030
56171
|
},
|
|
56031
56172
|
category: "doc",
|
|
@@ -56348,11 +56489,9 @@ function notion(opts) {
|
|
|
56348
56489
|
...withNotionOverrides(declarativeRestConnector(NOTION_SPEC)),
|
|
56349
56490
|
/**
|
|
56350
56491
|
* Notion's token endpoint follows RFC 6749 with one twist — it REQUIRES
|
|
56351
|
-
* HTTP Basic auth
|
|
56352
|
-
*
|
|
56353
|
-
*
|
|
56354
|
-
* back in the response and we stash them in `metadata` so the agent can
|
|
56355
|
-
* address resources by workspace where useful.
|
|
56492
|
+
* HTTP Basic auth and returns workspace metadata with the grant. We use
|
|
56493
|
+
* the shared Basic encoding and redaction primitives, then retain that
|
|
56494
|
+
* metadata for resource selection.
|
|
56356
56495
|
*/
|
|
56357
56496
|
async exchangeOAuth(input) {
|
|
56358
56497
|
if (!clientId || !clientSecret) {
|
|
@@ -56367,22 +56506,62 @@ function notion(opts) {
|
|
|
56367
56506
|
redirect_uri: input.redirectUri,
|
|
56368
56507
|
code_verifier: input.codeVerifier
|
|
56369
56508
|
});
|
|
56370
|
-
const
|
|
56371
|
-
|
|
56372
|
-
|
|
56373
|
-
|
|
56374
|
-
|
|
56375
|
-
|
|
56376
|
-
|
|
56377
|
-
|
|
56378
|
-
|
|
56379
|
-
|
|
56380
|
-
|
|
56509
|
+
const authorization = createOAuthBasicAuthorizationHeader(
|
|
56510
|
+
clientId,
|
|
56511
|
+
clientSecret
|
|
56512
|
+
);
|
|
56513
|
+
const redactionValues = [
|
|
56514
|
+
input.code,
|
|
56515
|
+
input.codeVerifier,
|
|
56516
|
+
...oauthClientCredentialRedactionValues(
|
|
56517
|
+
clientId,
|
|
56518
|
+
clientSecret,
|
|
56519
|
+
authorization
|
|
56520
|
+
)
|
|
56521
|
+
];
|
|
56522
|
+
let res;
|
|
56523
|
+
try {
|
|
56524
|
+
res = await fetch(TOKEN_URL13, {
|
|
56525
|
+
method: "POST",
|
|
56526
|
+
headers: {
|
|
56527
|
+
authorization,
|
|
56528
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
56529
|
+
accept: "application/json",
|
|
56530
|
+
"Notion-Version": NOTION_VERSION
|
|
56531
|
+
},
|
|
56532
|
+
body,
|
|
56533
|
+
signal: AbortSignal.timeout(15e3)
|
|
56534
|
+
});
|
|
56535
|
+
} catch (cause) {
|
|
56536
|
+
const detail = redactOAuthSensitiveText(
|
|
56537
|
+
cause?.message ?? "unknown",
|
|
56538
|
+
redactionValues
|
|
56539
|
+
);
|
|
56540
|
+
throw new Error(`Notion OAuth token exchange transport error: ${detail}`);
|
|
56541
|
+
}
|
|
56381
56542
|
if (!res.ok) {
|
|
56382
56543
|
const text = await res.text().catch(() => "");
|
|
56383
|
-
|
|
56544
|
+
const statusText = redactOAuthSensitiveText(
|
|
56545
|
+
res.statusText,
|
|
56546
|
+
redactionValues
|
|
56547
|
+
);
|
|
56548
|
+
const detail = redactOAuthSensitiveText(text, redactionValues).slice(
|
|
56549
|
+
0,
|
|
56550
|
+
200
|
|
56551
|
+
);
|
|
56552
|
+
throw new Error(
|
|
56553
|
+
`Notion OAuth token exchange failed: ${res.status} ${statusText} \u2014 ${detail}`
|
|
56554
|
+
);
|
|
56555
|
+
}
|
|
56556
|
+
let json;
|
|
56557
|
+
try {
|
|
56558
|
+
json = await res.json();
|
|
56559
|
+
} catch {
|
|
56560
|
+
throw new Error("Notion OAuth token exchange returned invalid JSON");
|
|
56561
|
+
}
|
|
56562
|
+
if (!json.access_token) {
|
|
56563
|
+
throw new Error("Notion OAuth token exchange returned no access_token");
|
|
56384
56564
|
}
|
|
56385
|
-
const json = await res.json();
|
|
56386
56565
|
return {
|
|
56387
56566
|
credentials: {
|
|
56388
56567
|
kind: "oauth2",
|
|
@@ -56413,6 +56592,7 @@ function notion(opts) {
|
|
|
56413
56592
|
tokenUrl: TOKEN_URL13,
|
|
56414
56593
|
clientId,
|
|
56415
56594
|
clientSecret,
|
|
56595
|
+
tokenClientAuthMethod: "client_secret_basic",
|
|
56416
56596
|
refreshToken: creds.refreshToken
|
|
56417
56597
|
});
|
|
56418
56598
|
return {
|
|
@@ -69359,7 +69539,8 @@ var TWITTER_SPEC = {
|
|
|
69359
69539
|
tokenUrl: TOKEN_URL19,
|
|
69360
69540
|
scopes: SCOPES13,
|
|
69361
69541
|
clientIdEnv: "TWITTER_OAUTH_CLIENT_ID",
|
|
69362
|
-
clientSecretEnv: "TWITTER_OAUTH_CLIENT_SECRET"
|
|
69542
|
+
clientSecretEnv: "TWITTER_OAUTH_CLIENT_SECRET",
|
|
69543
|
+
tokenClientAuthMethod: "client_secret_basic"
|
|
69363
69544
|
},
|
|
69364
69545
|
{
|
|
69365
69546
|
kind: "api-key",
|
|
@@ -69656,21 +69837,61 @@ function twitter(opts) {
|
|
|
69656
69837
|
};
|
|
69657
69838
|
}
|
|
69658
69839
|
async function twitterTokenRequest(clientId, clientSecret, params) {
|
|
69659
|
-
const
|
|
69660
|
-
|
|
69661
|
-
|
|
69662
|
-
|
|
69663
|
-
|
|
69664
|
-
|
|
69665
|
-
|
|
69666
|
-
|
|
69667
|
-
|
|
69668
|
-
|
|
69840
|
+
const authorization = createOAuthBasicAuthorizationHeader(
|
|
69841
|
+
clientId,
|
|
69842
|
+
clientSecret
|
|
69843
|
+
);
|
|
69844
|
+
const requestSecrets = [
|
|
69845
|
+
params.code,
|
|
69846
|
+
params.code_verifier,
|
|
69847
|
+
params.refresh_token
|
|
69848
|
+
].filter((value) => typeof value === "string" && value.length > 0);
|
|
69849
|
+
const redactionValues = [
|
|
69850
|
+
...requestSecrets,
|
|
69851
|
+
...oauthClientCredentialRedactionValues(
|
|
69852
|
+
clientId,
|
|
69853
|
+
clientSecret,
|
|
69854
|
+
authorization
|
|
69855
|
+
)
|
|
69856
|
+
];
|
|
69857
|
+
let res;
|
|
69858
|
+
try {
|
|
69859
|
+
res = await fetch(TOKEN_URL19, {
|
|
69860
|
+
method: "POST",
|
|
69861
|
+
headers: {
|
|
69862
|
+
authorization,
|
|
69863
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
69864
|
+
accept: "application/json"
|
|
69865
|
+
},
|
|
69866
|
+
body: new URLSearchParams(params),
|
|
69867
|
+
signal: AbortSignal.timeout(15e3)
|
|
69868
|
+
});
|
|
69869
|
+
} catch (cause) {
|
|
69870
|
+
const detail = redactOAuthSensitiveText(
|
|
69871
|
+
cause?.message ?? "unknown",
|
|
69872
|
+
redactionValues
|
|
69873
|
+
);
|
|
69874
|
+
throw new Error(
|
|
69875
|
+
`twitter ${params.grant_type} token transport error: ${detail}`
|
|
69876
|
+
);
|
|
69877
|
+
}
|
|
69669
69878
|
if (!res.ok) {
|
|
69670
69879
|
const text = await res.text().catch(() => "");
|
|
69671
|
-
|
|
69880
|
+
const statusText = redactOAuthSensitiveText(res.statusText, redactionValues);
|
|
69881
|
+
const detail = redactOAuthSensitiveText(text, redactionValues).slice(0, 200);
|
|
69882
|
+
throw new Error(
|
|
69883
|
+
`twitter ${params.grant_type} token request failed: ${res.status} ${statusText} \u2014 ${detail}`
|
|
69884
|
+
);
|
|
69885
|
+
}
|
|
69886
|
+
let json;
|
|
69887
|
+
try {
|
|
69888
|
+
json = await res.json();
|
|
69889
|
+
} catch {
|
|
69890
|
+
throw new Error(`twitter ${params.grant_type} token request returned invalid JSON`);
|
|
69891
|
+
}
|
|
69892
|
+
if (!json.access_token) {
|
|
69893
|
+
throw new Error(`twitter ${params.grant_type} token request returned no access_token`);
|
|
69672
69894
|
}
|
|
69673
|
-
const json = await res.json();
|
|
69674
69895
|
return {
|
|
69675
69896
|
accessToken: json.access_token,
|
|
69676
69897
|
refreshToken: json.refresh_token,
|
|
@@ -148876,6 +149097,10 @@ export {
|
|
|
148876
149097
|
exchangeAuthorizationCode,
|
|
148877
149098
|
refreshAccessToken,
|
|
148878
149099
|
createOAuthTokenRequestHeaders,
|
|
149100
|
+
formEncodeOAuthClientCredential,
|
|
149101
|
+
createOAuthBasicAuthorizationHeader,
|
|
149102
|
+
oauthClientCredentialRedactionValues,
|
|
149103
|
+
redactOAuthSensitiveText,
|
|
148879
149104
|
_resetPendingFlowsForTests,
|
|
148880
149105
|
declarativeRestConnector,
|
|
148881
149106
|
oktaConnector,
|
|
@@ -149533,4 +149758,4 @@ export {
|
|
|
149533
149758
|
getresponseConnector,
|
|
149534
149759
|
adapters_exports
|
|
149535
149760
|
};
|
|
149536
|
-
//# sourceMappingURL=chunk-
|
|
149761
|
+
//# sourceMappingURL=chunk-2JRYKWYX.js.map
|