@absolutejs/auth 0.26.0-beta.1 → 0.26.0-beta.3

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.
Files changed (41) hide show
  1. package/dist/audit/config.d.ts +2 -1
  2. package/dist/audit/types.d.ts +1 -1
  3. package/dist/authorization/config.d.ts +19 -0
  4. package/dist/authorization/protectPermission.d.ts +52 -0
  5. package/dist/compliance/cipher.d.ts +5 -0
  6. package/dist/compliance/config.d.ts +18 -0
  7. package/dist/compliance/redaction.d.ts +8 -0
  8. package/dist/compliance/routes.d.ts +89 -0
  9. package/dist/htmx/index.js +494 -98
  10. package/dist/htmx/index.js.map +3 -3
  11. package/dist/index.d.ts +2539 -344
  12. package/dist/index.js +3679 -1619
  13. package/dist/index.js.map +33 -13
  14. package/dist/lockout/redisLockoutStore.d.ts +3 -0
  15. package/dist/providers/clients.d.ts +3 -3
  16. package/dist/routes/authorize.d.ts +2 -2
  17. package/dist/routes/protectRoute.d.ts +2 -2
  18. package/dist/scim/config.d.ts +55 -0
  19. package/dist/scim/inMemoryScimTokenStore.d.ts +2 -0
  20. package/dist/scim/postgresScimTokenStore.d.ts +102 -0
  21. package/dist/scim/routes.d.ts +296 -0
  22. package/dist/scim/serialize.d.ts +45 -0
  23. package/dist/scim/types.d.ts +52 -0
  24. package/dist/session/promote.d.ts +9 -2
  25. package/dist/sso/config.d.ts +104 -0
  26. package/dist/sso/discoveryRoute.d.ts +63 -0
  27. package/dist/sso/inMemorySsoConnectionStore.d.ts +2 -0
  28. package/dist/sso/oidcRoutes.d.ts +97 -0
  29. package/dist/sso/postgresSsoConnectionStore.d.ts +139 -0
  30. package/dist/sso/samlRoutes.d.ts +176 -0
  31. package/dist/sso/types.d.ts +39 -0
  32. package/dist/stores/redis.d.ts +5 -0
  33. package/dist/typebox.d.ts +1 -1
  34. package/dist/types.d.ts +36 -0
  35. package/dist/webauthn/adapter.d.ts +59 -0
  36. package/dist/webauthn/config.d.ts +35 -0
  37. package/dist/webauthn/inMemoryWebAuthnCredentialStore.d.ts +2 -0
  38. package/dist/webauthn/postgresWebAuthnCredentialStore.d.ts +172 -0
  39. package/dist/webauthn/routes.d.ts +155 -0
  40. package/dist/webauthn/types.d.ts +17 -0
  41. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // node_modules/citra/dist/index.js
3
- var NUM_GENERATOR_BYTES = 32;
4
3
  var BASE64_BLOCK_SIZE = 4;
4
+ var NUM_GENERATOR_BYTES = 32;
5
5
  var anilistProfileQuery = `query {
6
6
  Viewer {
7
7
  id
@@ -227,6 +227,25 @@ var providers = defineProviders({
227
227
  url: "https://auth.atlassian.com/oauth/token"
228
228
  }
229
229
  },
230
+ attio: {
231
+ authorizationUrl: "https://app.attio.com/authorize",
232
+ isOIDC: false,
233
+ isRefreshable: true,
234
+ profileRequest: {
235
+ authIn: "header",
236
+ encoding: "application/json",
237
+ method: "GET",
238
+ url: "https://api.attio.com/v2/self"
239
+ },
240
+ scopeRequired: true,
241
+ subject: ["workspace_id"],
242
+ subjectType: "string",
243
+ tokenRequest: {
244
+ authIn: "body",
245
+ encoding: "application/x-www-form-urlencoded",
246
+ url: "https://app.attio.com/oauth/token"
247
+ }
248
+ },
230
249
  auth0: {
231
250
  authorizationUrl: (config) => `https://${config.domain}/authorize`,
232
251
  isOIDC: true,
@@ -391,6 +410,25 @@ var providers = defineProviders({
391
410
  url: "https://www.bungie.net/Platform/App/OAuth/token"
392
411
  }
393
412
  },
413
+ close: {
414
+ authorizationUrl: "https://app.close.com/oauth2/authorize/",
415
+ isOIDC: false,
416
+ isRefreshable: true,
417
+ profileRequest: {
418
+ authIn: "header",
419
+ encoding: "application/json",
420
+ method: "GET",
421
+ url: "https://api.close.com/api/v1/me/"
422
+ },
423
+ scopeRequired: true,
424
+ subject: ["id"],
425
+ subjectType: "string",
426
+ tokenRequest: {
427
+ authIn: "body",
428
+ encoding: "application/x-www-form-urlencoded",
429
+ url: "https://api.close.com/oauth2/token/"
430
+ }
431
+ },
394
432
  coinbase: {
395
433
  authorizationUrl: "https://www.coinbase.com/oauth/authorize",
396
434
  isOIDC: false,
@@ -660,6 +698,25 @@ var providers = defineProviders({
660
698
  url: (config) => `${config.baseURL}/oauth/token`
661
699
  }
662
700
  },
701
+ gohighlevel: {
702
+ authorizationUrl: "https://marketplace.gohighlevel.com/oauth/chooselocation",
703
+ isOIDC: false,
704
+ isRefreshable: true,
705
+ profileRequest: {
706
+ authIn: "header",
707
+ encoding: "application/json",
708
+ method: "GET",
709
+ url: "https://services.leadconnectorhq.com/users/me"
710
+ },
711
+ scopeRequired: true,
712
+ subject: ["id"],
713
+ subjectType: "string",
714
+ tokenRequest: {
715
+ authIn: "body",
716
+ encoding: "application/x-www-form-urlencoded",
717
+ url: "https://services.leadconnectorhq.com/oauth/token"
718
+ }
719
+ },
663
720
  google: {
664
721
  authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
665
722
  email: ["email"],
@@ -695,6 +752,25 @@ var providers = defineProviders({
695
752
  url: "https://oauth2.googleapis.com/token"
696
753
  }
697
754
  },
755
+ hubspot: {
756
+ authorizationUrl: "https://app.hubspot.com/oauth/authorize",
757
+ isOIDC: false,
758
+ isRefreshable: true,
759
+ profileRequest: {
760
+ authIn: "header",
761
+ encoding: "application/json",
762
+ method: "GET",
763
+ url: "https://api.hubapi.com/oauth/v1/access-tokens/me"
764
+ },
765
+ scopeRequired: true,
766
+ subject: ["hub_id"],
767
+ subjectType: "number",
768
+ tokenRequest: {
769
+ authIn: "body",
770
+ encoding: "application/x-www-form-urlencoded",
771
+ url: "https://api.hubapi.com/oauth/v1/token"
772
+ }
773
+ },
698
774
  intuit: {
699
775
  authorizationUrl: "https://appcenter.intuit.com/connect/oauth2",
700
776
  isOIDC: true,
@@ -975,6 +1051,31 @@ var providers = defineProviders({
975
1051
  url: (config) => `https://${config.tenantId}.b2clogin.com/${config.tenantId}/oauth2/v2.0/token`
976
1052
  }
977
1053
  },
1054
+ monday: {
1055
+ authorizationUrl: "https://auth.monday.com/oauth2/authorize",
1056
+ isOIDC: false,
1057
+ isRefreshable: true,
1058
+ profileRequest: {
1059
+ authIn: "header",
1060
+ body: {
1061
+ query: "query { me { id name email } }"
1062
+ },
1063
+ encoding: "application/json",
1064
+ headers: {
1065
+ "Content-Type": "application/json"
1066
+ },
1067
+ method: "POST",
1068
+ url: "https://api.monday.com/v2"
1069
+ },
1070
+ scopeRequired: true,
1071
+ subject: ["data", "me", "id"],
1072
+ subjectType: "number",
1073
+ tokenRequest: {
1074
+ authIn: "body",
1075
+ encoding: "application/x-www-form-urlencoded",
1076
+ url: "https://auth.monday.com/oauth2/token"
1077
+ }
1078
+ },
978
1079
  myanimelist: {
979
1080
  authorizationUrl: "https://myanimelist.net/v1/oauth2/authorize",
980
1081
  isOIDC: false,
@@ -1106,6 +1207,25 @@ var providers = defineProviders({
1106
1207
  url: "https://www.patreon.com/api/oauth2/token"
1107
1208
  }
1108
1209
  },
1210
+ pipedrive: {
1211
+ authorizationUrl: "https://oauth.pipedrive.com/oauth/authorize",
1212
+ isOIDC: false,
1213
+ isRefreshable: true,
1214
+ profileRequest: {
1215
+ authIn: "header",
1216
+ encoding: "application/json",
1217
+ method: "GET",
1218
+ url: "https://api.pipedrive.com/v1/users/me"
1219
+ },
1220
+ scopeRequired: true,
1221
+ subject: ["data", "id"],
1222
+ subjectType: "number",
1223
+ tokenRequest: {
1224
+ authIn: "body",
1225
+ encoding: "application/x-www-form-urlencoded",
1226
+ url: "https://oauth.pipedrive.com/oauth/token"
1227
+ }
1228
+ },
1109
1229
  polar: {
1110
1230
  authorizationUrl: "https://polar.sh/oauth2/authorize",
1111
1231
  isOIDC: true,
@@ -1673,6 +1793,32 @@ var providers = defineProviders({
1673
1793
  url: "https://oauth.yandex.com/token"
1674
1794
  }
1675
1795
  },
1796
+ zoho: {
1797
+ authorizationUrl: (config) => `https://accounts.zoho.${config.region ?? "com"}/oauth/v2/auth`,
1798
+ isOIDC: false,
1799
+ isRefreshable: true,
1800
+ PKCEMethod: "S256",
1801
+ profileRequest: {
1802
+ authIn: "header",
1803
+ encoding: "application/json",
1804
+ method: "GET",
1805
+ url: (config) => `https://accounts.zoho.${config.region ?? "com"}/oauth/user/info`
1806
+ },
1807
+ revocationRequest: {
1808
+ authIn: "query",
1809
+ encoding: "application/x-www-form-urlencoded",
1810
+ tokenParamName: "token",
1811
+ url: (config) => `https://accounts.zoho.${config.region ?? "com"}/oauth/v2/token/revoke`
1812
+ },
1813
+ scopeRequired: true,
1814
+ subject: ["ZUID"],
1815
+ subjectType: "string",
1816
+ tokenRequest: {
1817
+ authIn: "body",
1818
+ encoding: "application/x-www-form-urlencoded",
1819
+ url: (config) => `https://accounts.zoho.${config.region ?? "com"}/oauth/v2/token`
1820
+ }
1821
+ },
1676
1822
  zoom: {
1677
1823
  authorizationUrl: "https://zoom.us/oauth/authorize",
1678
1824
  email: ["email"],
@@ -1707,18 +1853,32 @@ var providers = defineProviders({
1707
1853
  }
1708
1854
  }
1709
1855
  });
1710
- var isValidProviderOption = (option) => Object.hasOwn(providers, option);
1711
- var isRefreshableProviderOption = (option) => {
1712
- if (!isValidProviderOption(option))
1856
+ var hasClientSecret = (credentials) => {
1857
+ if (typeof credentials !== "object" || credentials === null)
1713
1858
  return false;
1714
- const provider = providers[option];
1715
- return provider.isRefreshable;
1859
+ const secret = Reflect.get(credentials, "clientSecret");
1860
+ return typeof secret === "string";
1716
1861
  };
1717
- var isRevocableProviderOption = (option) => {
1862
+ var isExpectedType = (value, kind) => {
1863
+ switch (kind) {
1864
+ case "string":
1865
+ return typeof value === "string";
1866
+ case "number":
1867
+ return typeof value === "number";
1868
+ case "boolean":
1869
+ return typeof value === "boolean";
1870
+ case "object":
1871
+ return typeof value === "object" && value !== null;
1872
+ default:
1873
+ return false;
1874
+ }
1875
+ };
1876
+ var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
1877
+ var isOIDCProviderOption = (option) => {
1718
1878
  if (!isValidProviderOption(option))
1719
1879
  return false;
1720
1880
  const provider = providers[option];
1721
- return provider.revocationRequest !== undefined;
1881
+ return provider.isOIDC;
1722
1882
  };
1723
1883
  var isPKCEProviderOption = (option) => {
1724
1884
  if (!isValidProviderOption(option))
@@ -1726,39 +1886,27 @@ var isPKCEProviderOption = (option) => {
1726
1886
  const provider = providers[option];
1727
1887
  return provider.PKCEMethod !== undefined;
1728
1888
  };
1729
- var isOIDCProviderOption = (option) => {
1889
+ var isRefreshableOAuth2Client = (providerName, _client) => isRefreshableProviderOption(providerName);
1890
+ var isRefreshableProviderOption = (option) => {
1730
1891
  if (!isValidProviderOption(option))
1731
1892
  return false;
1732
1893
  const provider = providers[option];
1733
- return provider.isOIDC;
1894
+ return provider.isRefreshable;
1734
1895
  };
1735
- var isScopeRequiredProviderOption = (option) => {
1896
+ var isRevocableOAuth2Client = (providerName, _client) => isRevocableProviderOption(providerName);
1897
+ var isRevocableProviderOption = (option) => {
1736
1898
  if (!isValidProviderOption(option))
1737
1899
  return false;
1738
1900
  const provider = providers[option];
1739
- return provider.scopeRequired;
1901
+ return provider.revocationRequest !== undefined;
1740
1902
  };
1741
- var isRefreshableOAuth2Client = (providerName, client) => isRefreshableProviderOption(providerName);
1742
- var isRevocableOAuth2Client = (providerName, client) => isRevocableProviderOption(providerName);
1743
- var hasClientSecret = (credentials) => {
1744
- if (typeof credentials !== "object" || credentials === null)
1903
+ var isScopeRequiredProviderOption = (option) => {
1904
+ if (!isValidProviderOption(option))
1745
1905
  return false;
1746
- const secret = Reflect.get(credentials, "clientSecret");
1747
- return typeof secret === "string";
1748
- };
1749
- var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x) && Object.prototype.toString.call(x) === "[object Object]";
1750
- var isExpectedType = (value, kind) => {
1751
- switch (kind) {
1752
- case "string":
1753
- return typeof value === "string";
1754
- case "number":
1755
- return typeof value === "number";
1756
- case "boolean":
1757
- return typeof value === "boolean";
1758
- case "object":
1759
- return typeof value === "object" && value !== null;
1760
- }
1906
+ const provider = providers[option];
1907
+ return provider.scopeRequired;
1761
1908
  };
1909
+ var isValidProviderOption = (option) => Object.hasOwn(providers, option);
1762
1910
  var createOAuth2FetchError = async (response) => {
1763
1911
  const clone = response.clone();
1764
1912
  const prefix = `HTTP ${response.status} ${response.statusText} for ${response.url}`;
@@ -1774,15 +1922,44 @@ ${text}`);
1774
1922
  }
1775
1923
  return new Error(prefix);
1776
1924
  };
1777
- var encodeBase64 = (input) => {
1778
- let raw;
1779
- if (typeof input === "string") {
1780
- raw = input;
1781
- } else {
1782
- const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);
1783
- raw = bytes.reduce((acc, byte) => acc + String.fromCharCode(byte), "");
1925
+ var createOAuth2Request = ({
1926
+ url,
1927
+ body,
1928
+ authIn,
1929
+ headers,
1930
+ encoding,
1931
+ clientId,
1932
+ clientSecret
1933
+ }) => {
1934
+ const oauthHeaders = new Headers(headers);
1935
+ oauthHeaders.set("Accept", "application/json");
1936
+ oauthHeaders.set("User-Agent", "citra");
1937
+ if (authIn === "header") {
1938
+ if (!clientSecret) {
1939
+ throw new Error("clientSecret required for header auth");
1940
+ }
1941
+ oauthHeaders.set("Authorization", `Basic ${encodeBase64(`${clientId}:${clientSecret}`)}`);
1784
1942
  }
1785
- return btoa(raw);
1943
+ if (encoding === "application/json") {
1944
+ oauthHeaders.set("Content-Type", "application/json");
1945
+ return new Request(url, {
1946
+ body: JSON.stringify(body),
1947
+ headers: oauthHeaders,
1948
+ method: "POST"
1949
+ });
1950
+ }
1951
+ oauthHeaders.set("Content-Type", "application/x-www-form-urlencoded");
1952
+ const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body).filter((entry) => typeof entry[1] === "string");
1953
+ const params = new URLSearchParams(entries);
1954
+ if (authIn === "body") {
1955
+ params.set("client_id", clientId);
1956
+ clientSecret && params.set("client_secret", clientSecret);
1957
+ }
1958
+ return new Request(url, {
1959
+ body: params.toString(),
1960
+ headers: oauthHeaders,
1961
+ method: "POST"
1962
+ });
1786
1963
  };
1787
1964
  var decodeBase64 = (input, toUint8Array = false) => {
1788
1965
  const b64 = input.replace(/-/g, "+").replace(/_/g, "/") + "==".slice(0, (BASE64_BLOCK_SIZE - input.length % BASE64_BLOCK_SIZE) % BASE64_BLOCK_SIZE);
@@ -1796,12 +1973,6 @@ var decodeBase64 = (input, toUint8Array = false) => {
1796
1973
  }
1797
1974
  return bytes;
1798
1975
  };
1799
- var hmacSha256 = async (message, secret) => {
1800
- const encoder = new TextEncoder;
1801
- const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
1802
- const sigBuffer = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
1803
- return Array.from(new Uint8Array(sigBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
1804
- };
1805
1976
  var decodeJWT = (tokenString) => {
1806
1977
  const [headerSegment, payloadSegment, signatureSegment] = tokenString.split(".");
1807
1978
  if (!headerSegment || !payloadSegment || !signatureSegment) {
@@ -1811,7 +1982,18 @@ var decodeJWT = (tokenString) => {
1811
1982
  if (typeof decodedPayload !== "string") {
1812
1983
  throw new Error("Expected JWT payload to be a UTF-8 string");
1813
1984
  }
1814
- return JSON.parse(decodedPayload);
1985
+ const claims = JSON.parse(decodedPayload);
1986
+ return claims;
1987
+ };
1988
+ var encodeBase64 = (input) => {
1989
+ let raw;
1990
+ if (typeof input === "string") {
1991
+ raw = input;
1992
+ } else {
1993
+ const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);
1994
+ raw = bytes.reduce((acc, byte) => acc + String.fromCharCode(byte), "");
1995
+ }
1996
+ return btoa(raw);
1815
1997
  };
1816
1998
  var getWithingsProps = async (config) => {
1817
1999
  const timestamp = Math.floor(Date.now() / 1000);
@@ -1822,7 +2004,9 @@ var getWithingsProps = async (config) => {
1822
2004
  nonceUrl.searchParams.set("client_id", config.clientId);
1823
2005
  nonceUrl.searchParams.set("timestamp", timestamp.toString());
1824
2006
  nonceUrl.searchParams.set("signature", hashedSignature);
1825
- const nonceResponse = await fetch(nonceUrl.toString(), {
2007
+ const nonceTarget = nonceUrl.toString();
2008
+ const nonceResponse = await fetch(nonceTarget, {
2009
+ ...h2IfHttps(nonceTarget),
1826
2010
  method: "POST"
1827
2011
  });
1828
2012
  const nonceData = await nonceResponse.json();
@@ -1834,44 +2018,15 @@ var getWithingsProps = async (config) => {
1834
2018
  }
1835
2019
  return;
1836
2020
  };
1837
- var createOAuth2Request = ({
1838
- url,
1839
- body,
1840
- authIn,
1841
- headers,
1842
- encoding,
1843
- clientId,
1844
- clientSecret
1845
- }) => {
1846
- const oauthHeaders = new Headers(headers);
1847
- oauthHeaders.set("Accept", "application/json");
1848
- oauthHeaders.set("User-Agent", "citra");
1849
- if (authIn === "header") {
1850
- if (!clientSecret) {
1851
- throw new Error("clientSecret required for header auth");
1852
- }
1853
- oauthHeaders.set("Authorization", `Basic ${encodeBase64(`${clientId}:${clientSecret}`)}`);
1854
- }
1855
- if (encoding === "application/json") {
1856
- oauthHeaders.set("Content-Type", "application/json");
1857
- return new Request(url, {
1858
- body: JSON.stringify(body),
1859
- headers: oauthHeaders,
1860
- method: "POST"
1861
- });
1862
- }
1863
- oauthHeaders.set("Content-Type", "application/x-www-form-urlencoded");
1864
- const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body).filter((entry) => typeof entry[1] === "string");
1865
- const params = new URLSearchParams(entries);
1866
- if (authIn === "body") {
1867
- params.set("client_id", clientId);
1868
- clientSecret && params.set("client_secret", clientSecret);
1869
- }
1870
- return new Request(url, {
1871
- body: params.toString(),
1872
- headers: oauthHeaders,
1873
- method: "POST"
1874
- });
2021
+ var h2IfHttps = (url) => {
2022
+ const init = url.startsWith("https://") ? { protocol: "http2" } : {};
2023
+ return init;
2024
+ };
2025
+ var hmacSha256 = async (message, secret) => {
2026
+ const encoder = new TextEncoder;
2027
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
2028
+ const sigBuffer = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
2029
+ return Array.from(new Uint8Array(sigBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
1875
2030
  };
1876
2031
  var extractPropFromIdentity = (identity, keys, propType) => {
1877
2032
  let value = identity;
@@ -1896,9 +2051,7 @@ var setPropInIdentity = (identity, keys, value) => {
1896
2051
  let cursor = identity;
1897
2052
  for (const key of keys.slice(0, -1)) {
1898
2053
  const next = cursor[key];
1899
- if (!isObject(next)) {
1900
- cursor[key] = {};
1901
- }
2054
+ cursor[key] = isObject(next) ? next : {};
1902
2055
  cursor = cursor[key];
1903
2056
  }
1904
2057
  cursor[keys[keys.length - 1]] = value;
@@ -1930,18 +2083,251 @@ var createRandomBase64UrlGenerator = (length) => () => {
1930
2083
  var generateCodeVerifier = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
1931
2084
  var generateState = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
1932
2085
  var base64Url = (input) => encodeBase64(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2086
+ var ALG_ES256 = "ES256";
2087
+ var ALG_RS256 = "RS256";
2088
+ var CLOCK_SKEW_SECONDS = 60;
2089
+ var DEFAULT_SCOPES = ["openid", "email", "profile"];
2090
+ var JWKS_REFETCH_COOLDOWN_MS = 60000;
2091
+ var JWT_SEGMENT_COUNT = 3;
2092
+ var MILLISECONDS_PER_SECOND = 1000;
2093
+ var trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
2094
+ var fetchJson = async (url) => {
2095
+ const response = await fetch(url, {
2096
+ headers: { accept: "application/json" }
2097
+ });
2098
+ if (!response.ok) {
2099
+ throw new Error(`Request to ${url} failed with status ${response.status}`);
2100
+ }
2101
+ return response.json();
2102
+ };
2103
+ var decodeJsonSegment = (segment) => {
2104
+ const decoded = decodeBase64(segment);
2105
+ if (typeof decoded !== "string") {
2106
+ throw new Error("Expected a base64url-encoded JWT segment");
2107
+ }
2108
+ const parsed = JSON.parse(decoded);
2109
+ if (typeof parsed !== "object" || parsed === null) {
2110
+ throw new Error("Expected a JWT segment to decode to a JSON object");
2111
+ }
2112
+ return parsed;
2113
+ };
2114
+ var importVerificationKey = (jwk, alg) => {
2115
+ if (alg === ALG_RS256) {
2116
+ return crypto.subtle.importKey("jwk", jwk, { hash: "SHA-256", name: "RSASSA-PKCS1-v1_5" }, false, ["verify"]);
2117
+ }
2118
+ if (alg === ALG_ES256) {
2119
+ return crypto.subtle.importKey("jwk", jwk, { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"]);
2120
+ }
2121
+ throw new Error(`Unsupported id_token signing algorithm "${alg}"`);
2122
+ };
2123
+ var verifySignature = (key, alg, signingInput, signature) => {
2124
+ const algorithm = alg === ALG_ES256 ? { hash: "SHA-256", name: "ECDSA" } : { name: "RSASSA-PKCS1-v1_5" };
2125
+ return crypto.subtle.verify(algorithm, key, new Uint8Array(signature), new TextEncoder().encode(signingInput));
2126
+ };
2127
+ var selectKey = (jwks, kid) => jwks.find((jwk) => kid === undefined || jwk.kid === kid);
2128
+ var assertClaims = (payload, expected) => {
2129
+ const aud = Reflect.get(payload, "aud");
2130
+ const exp = Reflect.get(payload, "exp");
2131
+ const iss = Reflect.get(payload, "iss");
2132
+ const sub = Reflect.get(payload, "sub");
2133
+ const audiences = Array.isArray(aud) ? aud : [aud];
2134
+ const nowSeconds = Math.floor(Date.now() / MILLISECONDS_PER_SECOND);
2135
+ if (iss !== expected.issuer) {
2136
+ throw new Error('id_token "iss" does not match the provider issuer');
2137
+ }
2138
+ if (typeof sub !== "string" || sub.length === 0) {
2139
+ throw new Error('id_token is missing "sub"');
2140
+ }
2141
+ if (!audiences.includes(expected.audience)) {
2142
+ throw new Error('id_token "aud" does not include the client id');
2143
+ }
2144
+ if (typeof exp !== "number" || exp + CLOCK_SKEW_SECONDS < nowSeconds) {
2145
+ throw new Error("id_token has expired");
2146
+ }
2147
+ if (expected.nonce !== undefined && Reflect.get(payload, "nonce") !== expected.nonce) {
2148
+ throw new Error('id_token "nonce" does not match');
2149
+ }
2150
+ const claims = { ...payload, aud, exp, iss, sub };
2151
+ return claims;
2152
+ };
2153
+ var verifyIdToken = async ({
2154
+ audience,
2155
+ idToken,
2156
+ issuer,
2157
+ jwks,
2158
+ nonce
2159
+ }) => {
2160
+ const segments = idToken.split(".");
2161
+ const [headerSegment, payloadSegment, signatureSegment] = segments;
2162
+ if (segments.length !== JWT_SEGMENT_COUNT || headerSegment === undefined || payloadSegment === undefined || signatureSegment === undefined) {
2163
+ throw new Error("Invalid id_token: expected three segments");
2164
+ }
2165
+ const header = decodeJsonSegment(headerSegment);
2166
+ const alg = Reflect.get(header, "alg");
2167
+ const kid = Reflect.get(header, "kid");
2168
+ if (typeof alg !== "string") {
2169
+ throw new Error('id_token header is missing "alg"');
2170
+ }
2171
+ const jwk = selectKey(jwks, typeof kid === "string" ? kid : undefined);
2172
+ if (jwk === undefined) {
2173
+ throw new Error('No JWKS key matches the id_token "kid"');
2174
+ }
2175
+ const key = await importVerificationKey(jwk, alg);
2176
+ const signature = decodeBase64(signatureSegment, true);
2177
+ if (typeof signature === "string") {
2178
+ throw new Error("Failed to decode the id_token signature");
2179
+ }
2180
+ const isValid = await verifySignature(key, alg, `${headerSegment}.${payloadSegment}`, signature);
2181
+ if (!isValid) {
2182
+ throw new Error("id_token signature verification failed");
2183
+ }
2184
+ return assertClaims(decodeJsonSegment(payloadSegment), {
2185
+ audience,
2186
+ issuer,
2187
+ nonce
2188
+ });
2189
+ };
2190
+ var toDiscoveryDocument = (value, expectedIssuer) => {
2191
+ if (typeof value !== "object" || value === null) {
2192
+ throw new Error("OIDC discovery document is not a JSON object");
2193
+ }
2194
+ const issuer = Reflect.get(value, "issuer");
2195
+ const authorizationEndpoint = Reflect.get(value, "authorization_endpoint");
2196
+ const tokenEndpoint = Reflect.get(value, "token_endpoint");
2197
+ const jwksUri = Reflect.get(value, "jwks_uri");
2198
+ const userinfoEndpoint = Reflect.get(value, "userinfo_endpoint");
2199
+ if (typeof issuer !== "string" || typeof authorizationEndpoint !== "string" || typeof tokenEndpoint !== "string" || typeof jwksUri !== "string") {
2200
+ throw new Error("OIDC discovery document is missing required endpoints");
2201
+ }
2202
+ if (trimTrailingSlash(issuer) !== trimTrailingSlash(expectedIssuer)) {
2203
+ throw new Error(`OIDC discovery issuer "${issuer}" does not match configured issuer "${expectedIssuer}"`);
2204
+ }
2205
+ return {
2206
+ authorization_endpoint: authorizationEndpoint,
2207
+ issuer,
2208
+ jwks_uri: jwksUri,
2209
+ token_endpoint: tokenEndpoint,
2210
+ userinfo_endpoint: typeof userinfoEndpoint === "string" ? userinfoEndpoint : undefined
2211
+ };
2212
+ };
2213
+ var fetchDiscoveryDocument = async (issuer) => {
2214
+ const base = trimTrailingSlash(issuer);
2215
+ const document = await fetchJson(`${base}/.well-known/openid-configuration`);
2216
+ return toDiscoveryDocument(document, issuer);
2217
+ };
2218
+ var fetchJwks = async (jwksUri) => {
2219
+ const body = await fetchJson(jwksUri);
2220
+ const value = Reflect.get(body ?? {}, "keys");
2221
+ if (!Array.isArray(value)) {
2222
+ throw new Error('JWKS response is missing a "keys" array');
2223
+ }
2224
+ const keys = value;
2225
+ return keys;
2226
+ };
2227
+ var createOIDCClient = async (config) => {
2228
+ const discovery = await fetchDiscoveryDocument(config.issuer);
2229
+ const scopes = config.scopes !== undefined && config.scopes.length > 0 ? config.scopes : DEFAULT_SCOPES;
2230
+ let cachedJwks;
2231
+ let jwksFetchedAtMs = 0;
2232
+ const resolveJwks = async (forceRefresh) => {
2233
+ const isStale = Date.now() - jwksFetchedAtMs > JWKS_REFETCH_COOLDOWN_MS;
2234
+ if (cachedJwks === undefined || forceRefresh && isStale) {
2235
+ cachedJwks = await fetchJwks(discovery.jwks_uri);
2236
+ jwksFetchedAtMs = Date.now();
2237
+ }
2238
+ return cachedJwks;
2239
+ };
2240
+ const createAuthorizationUrl = async (options) => {
2241
+ const url = new URL(discovery.authorization_endpoint);
2242
+ const challenge = await createS256CodeChallenge(options.codeVerifier);
2243
+ const { searchParams } = url;
2244
+ searchParams.set("client_id", config.clientId);
2245
+ searchParams.set("code_challenge", challenge);
2246
+ searchParams.set("code_challenge_method", "S256");
2247
+ searchParams.set("redirect_uri", config.redirectUri);
2248
+ searchParams.set("response_type", "code");
2249
+ searchParams.set("scope", (options.scope ?? scopes).join(" "));
2250
+ searchParams.set("state", options.state);
2251
+ if (options.nonce !== undefined) {
2252
+ searchParams.set("nonce", options.nonce);
2253
+ }
2254
+ return url;
2255
+ };
2256
+ const validateAuthorizationCode = async (options) => {
2257
+ const body = new URLSearchParams;
2258
+ body.set("client_id", config.clientId);
2259
+ body.set("client_secret", config.clientSecret);
2260
+ body.set("code", options.code);
2261
+ body.set("code_verifier", options.codeVerifier);
2262
+ body.set("grant_type", "authorization_code");
2263
+ body.set("redirect_uri", config.redirectUri);
2264
+ const response = await fetch(discovery.token_endpoint, {
2265
+ body,
2266
+ headers: {
2267
+ accept: "application/json",
2268
+ "content-type": "application/x-www-form-urlencoded"
2269
+ },
2270
+ method: "POST"
2271
+ });
2272
+ if (!response.ok) {
2273
+ throw new Error(`OIDC token request failed with status ${response.status}`);
2274
+ }
2275
+ const tokens = await response.json();
2276
+ return tokens;
2277
+ };
2278
+ const verifyToken = async (idToken, options) => {
2279
+ const jwks = await resolveJwks(false);
2280
+ const params = {
2281
+ audience: config.clientId,
2282
+ idToken,
2283
+ issuer: discovery.issuer,
2284
+ nonce: options?.nonce
2285
+ };
2286
+ try {
2287
+ return await verifyIdToken({ ...params, jwks });
2288
+ } catch (error) {
2289
+ const refreshed = await resolveJwks(true);
2290
+ if (refreshed === jwks)
2291
+ throw error;
2292
+ return verifyIdToken({ ...params, jwks: refreshed });
2293
+ }
2294
+ };
2295
+ const fetchUserProfile = async (accessToken) => {
2296
+ if (discovery.userinfo_endpoint === undefined) {
2297
+ throw new Error("OIDC provider does not expose a userinfo endpoint");
2298
+ }
2299
+ const response = await fetch(discovery.userinfo_endpoint, {
2300
+ headers: {
2301
+ accept: "application/json",
2302
+ authorization: `Bearer ${accessToken}`
2303
+ }
2304
+ });
2305
+ if (!response.ok) {
2306
+ throw new Error(`OIDC userinfo request failed with status ${response.status}`);
2307
+ }
2308
+ const profile = await response.json();
2309
+ return profile;
2310
+ };
2311
+ return {
2312
+ createAuthorizationUrl,
2313
+ discovery,
2314
+ fetchUserProfile,
2315
+ validateAuthorizationCode,
2316
+ verifyIdToken: verifyToken
2317
+ };
2318
+ };
2319
+ var oidcProviderOptions = Object.keys(providers).filter(isOIDCProviderOption);
2320
+ var pkceProviderOptions = Object.keys(providers).filter(isPKCEProviderOption);
1933
2321
  var providerOptions = Object.keys(providers).filter(isValidProviderOption);
1934
2322
  var refreshableProviderOptions = Object.keys(providers).filter(isRefreshableProviderOption);
1935
- var oidcProviderOptions = Object.keys(providers).filter(isOIDCProviderOption);
1936
2323
  var revocableProviderOptions = Object.keys(providers).filter(isRevocableProviderOption);
1937
2324
  var scopeRequiredProviderOptions = Object.keys(providers).filter(isScopeRequiredProviderOption);
1938
- var pkceProviderOptions = Object.keys(providers).filter(isPKCEProviderOption);
1939
2325
  var createOAuth2Client = async (providerName, config) => {
1940
2326
  const meta = providers[providerName];
1941
2327
  const isConfigPropertyFunction = (cfgProp) => typeof cfgProp === "function";
1942
2328
  const resolveConfigProp = async (cfgProp) => {
1943
2329
  const result = isConfigPropertyFunction(cfgProp) ? cfgProp(config) : cfgProp;
1944
- return await result;
2330
+ return result;
1945
2331
  };
1946
2332
  const authorizationUrl = await resolveConfigProp(meta.authorizationUrl);
1947
2333
  const tokenUrl = await resolveConfigProp(meta.tokenRequest.url);
@@ -1993,18 +2379,22 @@ var createOAuth2Client = async (providerName, config) => {
1993
2379
  headerEntries = rawHeaders;
1994
2380
  else if (rawHeaders && typeof rawHeaders === "object")
1995
2381
  headerEntries = Object.entries(rawHeaders);
1996
- const profileHeaders = Object.fromEntries(headerEntries.filter(([, v]) => v !== ""));
2382
+ const profileHeaders = Object.fromEntries(headerEntries.filter(([, value]) => value !== ""));
1997
2383
  if (authIn === "header") {
1998
2384
  profileHeaders.Authorization = `Bearer ${accessToken}`;
1999
2385
  } else {
2000
2386
  endpoint.searchParams.append("access_token", accessToken);
2001
2387
  }
2002
2388
  const init = { headers: profileHeaders, method };
2003
- if (method === "POST" && resolvedBody != null) {
2389
+ if (method === "POST" && resolvedBody !== undefined) {
2004
2390
  profileHeaders["Content-Type"] = encoding;
2005
2391
  init.body = encoding === "application/json" ? JSON.stringify(resolvedBody) : new URLSearchParams(resolvedBody).toString();
2006
2392
  }
2007
- const response = await fetch(endpoint.toString(), init);
2393
+ const profileTarget = endpoint.toString();
2394
+ const response = await fetch(profileTarget, {
2395
+ ...h2IfHttps(profileTarget),
2396
+ ...init
2397
+ });
2008
2398
  if (!response.ok)
2009
2399
  throw await createOAuth2FetchError(response);
2010
2400
  return response.json();
@@ -2029,7 +2419,9 @@ var createOAuth2Client = async (providerName, config) => {
2029
2419
  encoding,
2030
2420
  url: tokenUrl
2031
2421
  });
2032
- const response = await fetch(request);
2422
+ const response = await fetch(request, {
2423
+ ...h2IfHttps(request.url)
2424
+ });
2033
2425
  if (!response.ok)
2034
2426
  throw await createOAuth2FetchError(response);
2035
2427
  return response.json();
@@ -2083,7 +2475,9 @@ var createOAuth2Client = async (providerName, config) => {
2083
2475
  url: `${endpoint.toString()}?${tokenParamName}=${token}`
2084
2476
  });
2085
2477
  }
2086
- const response = await fetch(request);
2478
+ const response = await fetch(request, {
2479
+ ...h2IfHttps(request.url)
2480
+ });
2087
2481
  if (!response.ok)
2088
2482
  throw await createOAuth2FetchError(response);
2089
2483
  },
@@ -2115,7 +2509,9 @@ var createOAuth2Client = async (providerName, config) => {
2115
2509
  encoding,
2116
2510
  url: tokenUrl
2117
2511
  });
2118
- const response = await fetch(request);
2512
+ const response = await fetch(request, {
2513
+ ...h2IfHttps(request.url)
2514
+ });
2119
2515
  if (!response.ok)
2120
2516
  throw await createOAuth2FetchError(response);
2121
2517
  return response.json();
@@ -2208,5 +2604,5 @@ export {
2208
2604
  escapeHtml
2209
2605
  };
2210
2606
 
2211
- //# debugId=B47ECE588E07832964756E2164756E21
2607
+ //# debugId=E36225136305103F64756E2164756E21
2212
2608
  //# sourceMappingURL=index.js.map