@supertokens-plugins/rownd-nodejs 0.3.0-beta.6 → 0.3.0-beta.7

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/index.mjs CHANGED
@@ -701,6 +701,7 @@ var DEFAULT_ROWND_SCHEMA = {
701
701
  };
702
702
  var HUB_LOGIN_PAGE_PATH = "/account/login";
703
703
  var HUB_VERIFY_EMAIL_PAGE_PATH = "/account/verify-email";
704
+ var PASSWORDLESS_BYPASS_DEVICE_CONFIRMATION_PARAM = "bypassDeviceConfirmation";
704
705
 
705
706
  // src/logger.ts
706
707
  var { logDebugMessage, enableDebugLogs } = buildLogger(
@@ -943,6 +944,109 @@ function getStringList(value) {
943
944
  function getErrorMessage(error) {
944
945
  return error instanceof Error ? error.message : "Unknown error";
945
946
  }
947
+ function getAppInfoString(value) {
948
+ return value.getAsStringDangerous();
949
+ }
950
+ function getWebsiteDomain(input) {
951
+ return getAppInfoString(input.stConfig.appInfo.getOrigin({
952
+ request: input.request,
953
+ userContext: input.userContext ?? {}
954
+ }));
955
+ }
956
+ function normalizeClientDomain(value) {
957
+ if (value.endsWith("://")) {
958
+ return value;
959
+ }
960
+ const parsed = new URL(value);
961
+ if (parsed.protocol === "http:" || parsed.protocol === "https:") {
962
+ return parsed.origin;
963
+ }
964
+ return `${parsed.protocol}//${parsed.host}`;
965
+ }
966
+ function resolveClientDomain(input) {
967
+ if (!input.clientDomain) {
968
+ return input.websiteDomain;
969
+ }
970
+ const resolved = input.pluginConfig.clientDomains?.[input.clientDomain];
971
+ if (!resolved) {
972
+ throw new Error(`Unknown clientDomain key: ${input.clientDomain}`);
973
+ }
974
+ return resolved;
975
+ }
976
+ function resolveAllowedClientDomain(input) {
977
+ const websiteDomain = getWebsiteDomain(input);
978
+ const resolvedClientDomain = resolveClientDomain({
979
+ clientDomain: input.clientDomain,
980
+ pluginConfig: input.pluginConfig,
981
+ websiteDomain
982
+ });
983
+ const normalizedClientDomain = normalizeClientDomain(resolvedClientDomain);
984
+ const allowed = [
985
+ websiteDomain,
986
+ ...Object.values(input.pluginConfig.clientDomains ?? {})
987
+ ].map(normalizeClientDomain);
988
+ if (!allowed.includes(normalizedClientDomain)) {
989
+ throw new Error(`clientDomain is not allowed: ${resolvedClientDomain}`);
990
+ }
991
+ return normalizedClientDomain;
992
+ }
993
+ function normalizeRedirectToPathForClientDomain(redirectToPath, clientDomain) {
994
+ if (!redirectToPath) {
995
+ return void 0;
996
+ }
997
+ if (redirectToPath === "NATIVE_APP") {
998
+ return redirectToPath;
999
+ }
1000
+ if (redirectToPath.startsWith("//")) {
1001
+ throw new Error("redirectToPath cannot be schemaless");
1002
+ }
1003
+ const normalizedClientDomain = normalizeClientDomain(clientDomain);
1004
+ const redirectUrl = new URL(
1005
+ redirectToPath,
1006
+ normalizedClientDomain.endsWith("://") ? "http://localhost" : normalizedClientDomain
1007
+ );
1008
+ const hasExplicitScheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(redirectToPath);
1009
+ if (hasExplicitScheme) {
1010
+ if (redirectUrl.protocol !== "http:" && redirectUrl.protocol !== "https:") {
1011
+ throw new Error("redirectToPath must be http(s) or relative");
1012
+ }
1013
+ if (redirectUrl.origin !== normalizedClientDomain) {
1014
+ throw new Error("redirectToPath must match clientDomain");
1015
+ }
1016
+ }
1017
+ return `${redirectUrl.pathname}${redirectUrl.search}${redirectUrl.hash}`;
1018
+ }
1019
+ function assertAllowedBypassRedirectPath(pluginConfig2, redirectToPath) {
1020
+ if (!redirectToPath) {
1021
+ throw new Error("redirectToPath is required for confirmation bypass magic links");
1022
+ }
1023
+ const allowedRedirectPaths = pluginConfig2.crossDeviceConfirmationBypass?.allowedRedirectPaths ?? [];
1024
+ if (allowedRedirectPaths.length === 0) {
1025
+ throw new Error("crossDeviceConfirmationBypass.allowedRedirectPaths must be configured");
1026
+ }
1027
+ if (!allowedRedirectPaths.includes(redirectToPath)) {
1028
+ throw new Error(`redirectToPath is not allowed for confirmation bypass: ${redirectToPath}`);
1029
+ }
1030
+ }
1031
+ function getMagicLinkBootstrapParams(input) {
1032
+ return {
1033
+ appKey: input.appKey,
1034
+ apiDomain: input.apiDomain,
1035
+ apiBasePath: input.apiBasePath,
1036
+ ...input.appVariantId ? { appVariantId: input.appVariantId } : {},
1037
+ ...input.displayContext ? { displayContext: input.displayContext } : {},
1038
+ ...input.redirectToPath ? { redirectToPath: input.redirectToPath } : {},
1039
+ ...input.clientDomainKey ? { clientDomain: input.clientDomainKey } : {}
1040
+ };
1041
+ }
1042
+ function rewriteMagicLink(input) {
1043
+ return rewriteLinkToBaseUrl(
1044
+ input.magicLink,
1045
+ HUB_LOGIN_PAGE_PATH,
1046
+ input.clientDomain,
1047
+ input.bootstrapParams
1048
+ );
1049
+ }
946
1050
  function getRequestedAppVariantIdFromRequest(req) {
947
1051
  return req.getKeyValueFromQuery("app_variant_id");
948
1052
  }
@@ -961,12 +1065,19 @@ function getRequestedRedirectToPathFromRequest(req) {
961
1065
 
962
1066
  // src/config.ts
963
1067
  var pluginConfig;
1068
+ var superTokensConfig;
964
1069
  function setPluginConfig(config2) {
965
1070
  pluginConfig = config2;
966
1071
  }
967
1072
  function getPluginConfig() {
968
1073
  return pluginConfig;
969
1074
  }
1075
+ function setSuperTokensConfig(config2) {
1076
+ superTokensConfig = config2;
1077
+ }
1078
+ function getSuperTokensConfig() {
1079
+ return superTokensConfig;
1080
+ }
970
1081
  function assertRowndAppVariantIsConfigured(appVariantId) {
971
1082
  if (!appVariantId) {
972
1083
  return;
@@ -1047,7 +1158,10 @@ function buildSignInMethodsConfig(methodsArray) {
1047
1158
  },
1048
1159
  apple: {
1049
1160
  enabled: !!appleMethod,
1050
- client_id: getStringMethodProperty(appleMethod, "clientId") ?? ""
1161
+ client_id: getStringMethodProperty(appleMethod, "clientId") ?? "",
1162
+ ...getStringMethodProperty(appleMethod, "webClientType") !== void 0 ? { web_client_type: getStringMethodProperty(appleMethod, "webClientType") } : {},
1163
+ ...getStringMethodProperty(appleMethod, "iosClientType") !== void 0 ? { ios_client_type: getStringMethodProperty(appleMethod, "iosClientType") } : {},
1164
+ ...getStringMethodProperty(appleMethod, "androidClientType") !== void 0 ? { android_client_type: getStringMethodProperty(appleMethod, "androidClientType") } : {}
1051
1165
  },
1052
1166
  anonymous: {
1053
1167
  enabled: !!anonymousMethod && anonymousType !== "instant",
@@ -1321,6 +1435,7 @@ function buildAuthMobileConfig(authMobile) {
1321
1435
 
1322
1436
  // src/rownd-compatibility.ts
1323
1437
  import SuperTokens from "supertokens-node";
1438
+ import UserMetadata2 from "supertokens-node/recipe/usermetadata";
1324
1439
  var IDENTITY_USER_DATA_FIELDS = /* @__PURE__ */ new Set([
1325
1440
  "user_id",
1326
1441
  "email",
@@ -1495,6 +1610,140 @@ function buildRowndSessionClaimPayload(input) {
1495
1610
  ...anonymousId ? { anonymous_id: anonymousId } : {}
1496
1611
  };
1497
1612
  }
1613
+ function normalizeRowndOAuthScopes(scopes) {
1614
+ return [...new Set(scopes.filter((scope) => scope.length > 0))];
1615
+ }
1616
+ function getRowndOAuthAudience(input) {
1617
+ const requested = input.requestedResource ?? input.requestedAudience;
1618
+ if (requested?.startsWith("app:")) {
1619
+ return requested;
1620
+ }
1621
+ return void 0;
1622
+ }
1623
+ function applyRowndOAuthResourceParams(input) {
1624
+ const resource = firstString(input.params.resource);
1625
+ const audience = firstString(input.params.audience);
1626
+ const rowndAudience = getRowndOAuthAudience({
1627
+ requestedResource: resource,
1628
+ requestedAudience: audience
1629
+ });
1630
+ if (!rowndAudience) {
1631
+ return;
1632
+ }
1633
+ input.userContext.rowndOAuthAudience = rowndAudience;
1634
+ input.params.audience = audience ?? rowndAudience;
1635
+ delete input.params.resource;
1636
+ }
1637
+ async function buildRowndOAuthPayload(input) {
1638
+ const currentPayload = input.currentPayload ?? {};
1639
+ const standardClaims = input.user ? await buildStandardOAuthClaims(input.user, input.scopes) : {};
1640
+ const rowndClaims = input.user ? await buildRowndOAuthSessionClaims(input.user, currentPayload) : {};
1641
+ const audience = getRowndOAuthAudience({
1642
+ requestedAudience: typeof input.userContext?.rowndOAuthAudience === "string" ? input.userContext.rowndOAuthAudience : void 0
1643
+ });
1644
+ return {
1645
+ ...currentPayload,
1646
+ ...standardClaims,
1647
+ ...rowndClaims,
1648
+ ...audience ? { aud: audience } : {}
1649
+ };
1650
+ }
1651
+ async function buildRowndOAuthUserInfo(input) {
1652
+ const standardClaims = await buildStandardOAuthClaims(
1653
+ input.user,
1654
+ input.scopes
1655
+ );
1656
+ const rowndClaims = pickOAuthUserInfoRowndClaims(input.accessTokenPayload);
1657
+ return {
1658
+ ...input.currentPayload,
1659
+ ...standardClaims,
1660
+ ...rowndClaims
1661
+ };
1662
+ }
1663
+ async function buildStandardOAuthClaims(user, scopes) {
1664
+ const claims = {};
1665
+ const metadata = await getRowndMetadata(user.id);
1666
+ const rowndData = isJsonRecord(metadata.original_rownd_user?.data) ? metadata.original_rownd_user.data : {};
1667
+ const verifiedData = isJsonRecord(metadata.original_rownd_user?.verified_data) ? metadata.original_rownd_user.verified_data : {};
1668
+ if (scopes.includes("email")) {
1669
+ const email = firstString(rowndData.email) ?? user.emails[0];
1670
+ if (email) {
1671
+ claims.email = email;
1672
+ claims.email_verified = isOAuthClaimVerified(
1673
+ verifiedData.email,
1674
+ email,
1675
+ user.loginMethods.some(
1676
+ (method) => method.hasSameEmailAs(email) && method.verified
1677
+ )
1678
+ );
1679
+ }
1680
+ }
1681
+ if (scopes.includes("phone")) {
1682
+ const phoneNumber = firstString(rowndData.phone_number) ?? user.phoneNumbers[0];
1683
+ if (phoneNumber) {
1684
+ claims.phone_number = phoneNumber;
1685
+ claims.phone_number_verified = isOAuthClaimVerified(
1686
+ verifiedData.phone_number,
1687
+ phoneNumber,
1688
+ user.loginMethods.some(
1689
+ (method) => method.hasSamePhoneNumberAs(phoneNumber) && method.verified
1690
+ )
1691
+ );
1692
+ }
1693
+ }
1694
+ if (scopes.includes("profile")) {
1695
+ const givenName = firstString(rowndData.first_name);
1696
+ const familyName = firstString(rowndData.last_name);
1697
+ const name = [givenName, familyName].filter(Boolean).join(" ");
1698
+ if (name) claims.name = name;
1699
+ if (givenName) claims.given_name = givenName;
1700
+ if (familyName) claims.family_name = familyName;
1701
+ if (typeof metadata.original_rownd_user?.data?.updated_at === "string") {
1702
+ claims.updated_at = metadata.original_rownd_user.data.updated_at;
1703
+ }
1704
+ }
1705
+ return claims;
1706
+ }
1707
+ async function getRowndMetadata(userId) {
1708
+ const metadata = await UserMetadata2.getUserMetadata(userId);
1709
+ return metadata.metadata || {};
1710
+ }
1711
+ function pickOAuthUserInfoRowndClaims(payload) {
1712
+ const claims = {};
1713
+ for (const key of [
1714
+ "app_user_id",
1715
+ "auth_level",
1716
+ "is_verified_user",
1717
+ "is_anonymous",
1718
+ "anonymous_id",
1719
+ "https://auth.rownd.io/app_user_id",
1720
+ "https://auth.rownd.io/auth_level",
1721
+ "https://auth.rownd.io/is_verified_user",
1722
+ "https://auth.rownd.io/is_anonymous"
1723
+ ]) {
1724
+ if (payload[key] !== void 0) {
1725
+ claims[key] = payload[key];
1726
+ }
1727
+ }
1728
+ return claims;
1729
+ }
1730
+ function firstString(value) {
1731
+ if (Array.isArray(value)) {
1732
+ return value.find((entry) => typeof entry === "string");
1733
+ }
1734
+ return typeof value === "string" && value.length > 0 ? value : void 0;
1735
+ }
1736
+ function isOAuthClaimVerified(value, expectedValue, fallback) {
1737
+ return value === true || value === expectedValue || fallback;
1738
+ }
1739
+ async function buildRowndOAuthSessionClaims(user, currentPayload) {
1740
+ return buildRowndSessionClaimPayload({
1741
+ userId: user.id,
1742
+ user,
1743
+ metadata: await getRowndMetadata(user.id),
1744
+ currentPayload
1745
+ });
1746
+ }
1498
1747
  async function shouldLinkRowndAccounts(input) {
1499
1748
  const [newAccountInfo, , session] = input;
1500
1749
  if (!session) {
@@ -1642,7 +1891,7 @@ import EmailVerification from "supertokens-node/recipe/emailverification";
1642
1891
  import Passwordless from "supertokens-node/recipe/passwordless";
1643
1892
  import Session from "supertokens-node/recipe/session";
1644
1893
  import { BooleanClaim } from "supertokens-node/recipe/session/claims";
1645
- import UserMetadata2 from "supertokens-node/recipe/usermetadata";
1894
+ import UserMetadata3 from "supertokens-node/recipe/usermetadata";
1646
1895
  async function importUser(stUser, config2) {
1647
1896
  const headers = {
1648
1897
  "Content-Type": "application/json"
@@ -1681,7 +1930,7 @@ async function recordRowndAppVariantForUser(userId, appVariantId) {
1681
1930
  if (appVariants.includes(appVariantId)) {
1682
1931
  return;
1683
1932
  }
1684
- await UserMetadata2.updateUserMetadata(userId, {
1933
+ await UserMetadata3.updateUserMetadata(userId, {
1685
1934
  ...metadata,
1686
1935
  original_rownd_user: {
1687
1936
  ...originalRowndUser,
@@ -1713,8 +1962,78 @@ async function buildRowndSessionClaims(userId, currentPayload = {}, appVariantId
1713
1962
  appVariantId
1714
1963
  });
1715
1964
  }
1965
+ async function createMagicLinkWithConfirmationBypass(input) {
1966
+ const hasEmail = typeof input.email === "string" && input.email.length > 0;
1967
+ const hasPhoneNumber = typeof input.phoneNumber === "string" && input.phoneNumber.length > 0;
1968
+ if (hasEmail === hasPhoneNumber) {
1969
+ throw new Error("Exactly one of email or phoneNumber is required");
1970
+ }
1971
+ const stConfig = getSuperTokensConfig();
1972
+ if (!stConfig) {
1973
+ throw new Error("SuperTokens config is not initialized");
1974
+ }
1975
+ const pluginConfig2 = getPluginConfig();
1976
+ if (!pluginConfig2) {
1977
+ throw new Error("Rownd plugin config is not initialized");
1978
+ }
1979
+ const tenantId = input.tenantId ?? PUBLIC_TENANT_ID;
1980
+ const appVariantId = input.appVariantId;
1981
+ assertRowndAppVariantIsConfigured(appVariantId);
1982
+ const clientDomain = resolveAllowedClientDomain({
1983
+ clientDomain: input.clientDomain,
1984
+ pluginConfig: pluginConfig2,
1985
+ stConfig,
1986
+ request: input.request,
1987
+ userContext: input.userContext
1988
+ });
1989
+ const redirectToPath = normalizeRedirectToPathForClientDomain(input.redirectToPath, clientDomain);
1990
+ assertAllowedBypassRedirectPath(pluginConfig2, redirectToPath);
1991
+ const userContext = {
1992
+ ...input.userContext ?? {},
1993
+ ...input.displayContext ? { rowndDisplayContext: input.displayContext } : {},
1994
+ rowndRedirectToPath: redirectToPath,
1995
+ ...input.clientDomain ? { rowndClientDomain: input.clientDomain } : {},
1996
+ ...appVariantId ? { rowndAppVariantId: appVariantId } : {}
1997
+ };
1998
+ const codeInfo = hasEmail ? await Passwordless.createCode({
1999
+ email: input.email,
2000
+ tenantId,
2001
+ session: input.session,
2002
+ userContext
2003
+ }) : await Passwordless.createCode({
2004
+ phoneNumber: input.phoneNumber,
2005
+ tenantId,
2006
+ session: input.session,
2007
+ userContext
2008
+ });
2009
+ if (codeInfo.status !== "OK") {
2010
+ throw new Error("Failed to create magic link");
2011
+ }
2012
+ const magicLink = `${getWebsiteDomain({
2013
+ stConfig,
2014
+ request: input.request,
2015
+ userContext
2016
+ })}${getAppInfoString(stConfig.appInfo.websiteBasePath)}/verify?preAuthSessionId=${encodeURIComponent(
2017
+ codeInfo.preAuthSessionId
2018
+ )}&tenantId=${encodeURIComponent(tenantId)}#${encodeURIComponent(codeInfo.linkCode)}`;
2019
+ const rewrittenUrl = new URL(rewriteMagicLink({
2020
+ magicLink,
2021
+ clientDomain,
2022
+ bootstrapParams: getMagicLinkBootstrapParams({
2023
+ appKey: pluginConfig2.rowndAppKey,
2024
+ apiDomain: getAppInfoString(stConfig.appInfo.apiDomain),
2025
+ apiBasePath: getAppInfoString(stConfig.appInfo.apiBasePath),
2026
+ appVariantId,
2027
+ displayContext: input.displayContext,
2028
+ redirectToPath,
2029
+ clientDomainKey: input.clientDomain
2030
+ })
2031
+ }));
2032
+ rewrittenUrl.searchParams.set(PASSWORDLESS_BYPASS_DEVICE_CONFIRMATION_PARAM, "true");
2033
+ return rewrittenUrl.toString();
2034
+ }
1716
2035
  async function getUserMetadata(userId) {
1717
- const metadata = await UserMetadata2.getUserMetadata(userId);
2036
+ const metadata = await UserMetadata3.getUserMetadata(userId);
1718
2037
  return metadata.metadata || {};
1719
2038
  }
1720
2039
  function getPendingVerifications(metadata) {
@@ -1871,7 +2190,7 @@ async function updateUserData(userId, inputData) {
1871
2190
  ...metadata,
1872
2191
  ...inputData
1873
2192
  };
1874
- await UserMetadata2.updateUserMetadata(userId, updatedMetadata);
2193
+ await UserMetadata3.updateUserMetadata(userId, updatedMetadata);
1875
2194
  return getUserById(userId);
1876
2195
  }
1877
2196
  async function startPendingEmailVerification(input) {
@@ -1891,7 +2210,7 @@ async function startPendingEmailVerification(input) {
1891
2210
  );
1892
2211
  }
1893
2212
  if (pendingEmailVerifications.length > 0) {
1894
- await UserMetadata2.updateUserMetadata(input.userId, {
2213
+ await UserMetadata3.updateUserMetadata(input.userId, {
1895
2214
  ...metadata,
1896
2215
  rownd_pending_verification: pendingVerifications.filter(
1897
2216
  (pendingVerification2) => pendingVerification2.field !== "email"
@@ -1914,7 +2233,7 @@ async function startPendingEmailVerification(input) {
1914
2233
  value: input.email,
1915
2234
  created_at: (/* @__PURE__ */ new Date()).toISOString()
1916
2235
  };
1917
- await UserMetadata2.updateUserMetadata(input.userId, {
2236
+ await UserMetadata3.updateUserMetadata(input.userId, {
1918
2237
  ...metadata,
1919
2238
  rownd_pending_verification: [
1920
2239
  ...pendingVerifications.filter(
@@ -2035,7 +2354,7 @@ async function completePendingEmailVerification(input) {
2035
2354
  )
2036
2355
  )
2037
2356
  };
2038
- await UserMetadata2.updateUserMetadata(metadataUserId, updatedMetadata);
2357
+ await UserMetadata3.updateUserMetadata(metadataUserId, updatedMetadata);
2039
2358
  }
2040
2359
  function isMatchingPendingEmailVerification(verification, email) {
2041
2360
  return verification.field === "email" && verification.value === email;
@@ -2046,7 +2365,7 @@ async function updateUserMetadata(userId, inputMeta) {
2046
2365
  ...metadata,
2047
2366
  ...inputMeta
2048
2367
  };
2049
- await UserMetadata2.updateUserMetadata(userId, updatedMetadata);
2368
+ await UserMetadata3.updateUserMetadata(userId, updatedMetadata);
2050
2369
  return {
2051
2370
  id: userId,
2052
2371
  meta: Object.fromEntries(
@@ -2067,6 +2386,9 @@ import { randomUUID } from "crypto";
2067
2386
  import SuperTokens3 from "supertokens-node";
2068
2387
  import Session2 from "supertokens-node/recipe/session";
2069
2388
  import ThirdParty from "supertokens-node/recipe/thirdparty";
2389
+ function isBodyString(body, key) {
2390
+ return isRecord(body) && typeof body[key] === "string" && body[key].length > 0;
2391
+ }
2070
2392
  function handleGetAppConfig(deps) {
2071
2393
  return async (req) => {
2072
2394
  const appVariantId = getRequestedAppVariantIdFromRequest(req);
@@ -2087,6 +2409,43 @@ function handleGetAppConfig(deps) {
2087
2409
  };
2088
2410
  };
2089
2411
  }
2412
+ function handleValidatePasswordlessConfirmationBypass(deps) {
2413
+ return async (req) => {
2414
+ try {
2415
+ const body = await getJsonBody(req);
2416
+ const clientDomain = isBodyString(body, "clientDomain") ? body.clientDomain : void 0;
2417
+ const redirectToPath = isBodyString(body, "redirectToPath") ? body.redirectToPath : void 0;
2418
+ const appVariantId = isBodyString(body, "appVariantId") ? body.appVariantId : void 0;
2419
+ assertRowndAppVariantIsConfigured(appVariantId);
2420
+ const resolvedClientDomain = resolveAllowedClientDomain({
2421
+ clientDomain,
2422
+ pluginConfig: deps.pluginConfig,
2423
+ stConfig: deps.stConfig,
2424
+ request: req
2425
+ });
2426
+ const normalizedRedirectToPath = normalizeRedirectToPathForClientDomain(
2427
+ redirectToPath,
2428
+ resolvedClientDomain
2429
+ );
2430
+ assertAllowedBypassRedirectPath(
2431
+ deps.pluginConfig,
2432
+ normalizedRedirectToPath
2433
+ );
2434
+ return {
2435
+ status: "OK",
2436
+ bypass: true
2437
+ };
2438
+ } catch (error) {
2439
+ logDebugMessage(
2440
+ `Passwordless confirmation bypass validation failed. Error: ${getErrorMessage(error)}`
2441
+ );
2442
+ return {
2443
+ status: "ERROR",
2444
+ bypass: false
2445
+ };
2446
+ }
2447
+ };
2448
+ }
2090
2449
  function handleGuestLogin(deps) {
2091
2450
  return async (req, res, _session, userContext) => {
2092
2451
  const startedAt = Date.now();
@@ -2484,6 +2843,7 @@ var init = createPluginInitFunction(
2484
2843
  }
2485
2844
  },
2486
2845
  routeHandlers(stConfig) {
2846
+ setSuperTokensConfig(stConfig);
2487
2847
  const apiBasePath = stConfig.appInfo.apiBasePath.getAsStringDangerous();
2488
2848
  hubBootstrapParams = {
2489
2849
  apiDomain: stConfig.appInfo.apiDomain.getAsStringDangerous(),
@@ -2514,6 +2874,13 @@ var init = createPluginInitFunction(
2514
2874
  method: "post",
2515
2875
  handler: withRequestHandler(handleMigrate(routeHandlerDeps))
2516
2876
  },
2877
+ {
2878
+ path: `${apiBasePath}/plugin/passwordless-cross-device-confirmation/validate`,
2879
+ method: "post",
2880
+ handler: withRequestHandler(
2881
+ handleValidatePasswordlessConfirmationBypass(routeHandlerDeps)
2882
+ )
2883
+ },
2517
2884
  {
2518
2885
  path: `${apiBasePath}/plugin/migrate-session`,
2519
2886
  method: "post",
@@ -2574,6 +2941,74 @@ var init = createPluginInitFunction(
2574
2941
  };
2575
2942
  },
2576
2943
  overrideMap: {
2944
+ oauth2provider: {
2945
+ recipeInitRequired: false,
2946
+ functions: (originalImplementation) => ({
2947
+ ...originalImplementation,
2948
+ getRequestedScopes: async (input) => {
2949
+ const scopes = await originalImplementation.getRequestedScopes(
2950
+ input
2951
+ );
2952
+ return normalizeRowndOAuthScopes(scopes);
2953
+ },
2954
+ buildAccessTokenPayload: async (input) => {
2955
+ const payload = await originalImplementation.buildAccessTokenPayload(
2956
+ input
2957
+ );
2958
+ return buildRowndOAuthPayload({
2959
+ user: input.user,
2960
+ client: input.client,
2961
+ scopes: input.scopes,
2962
+ currentPayload: payload,
2963
+ userContext: input.userContext
2964
+ });
2965
+ },
2966
+ buildIdTokenPayload: async (input) => {
2967
+ const payload = await originalImplementation.buildIdTokenPayload(
2968
+ input
2969
+ );
2970
+ return buildRowndOAuthPayload({
2971
+ user: input.user,
2972
+ client: input.client,
2973
+ scopes: input.scopes,
2974
+ currentPayload: payload,
2975
+ userContext: input.userContext
2976
+ });
2977
+ },
2978
+ buildUserInfo: async (input) => {
2979
+ const payload = await originalImplementation.buildUserInfo(input);
2980
+ return buildRowndOAuthUserInfo({
2981
+ user: input.user,
2982
+ accessTokenPayload: input.accessTokenPayload,
2983
+ scopes: input.scopes,
2984
+ currentPayload: payload
2985
+ });
2986
+ }
2987
+ }),
2988
+ apis: (originalImplementation) => ({
2989
+ ...originalImplementation,
2990
+ authGET: async (input) => {
2991
+ if (originalImplementation.authGET === void 0) {
2992
+ throw new Error("OAuth2Provider authGET is unavailable");
2993
+ }
2994
+ applyRowndOAuthResourceParams({
2995
+ params: input.params,
2996
+ userContext: input.userContext
2997
+ });
2998
+ return originalImplementation.authGET(input);
2999
+ },
3000
+ tokenPOST: async (input) => {
3001
+ if (originalImplementation.tokenPOST === void 0) {
3002
+ throw new Error("OAuth2Provider tokenPOST is unavailable");
3003
+ }
3004
+ applyRowndOAuthResourceParams({
3005
+ params: input.body,
3006
+ userContext: input.userContext
3007
+ });
3008
+ return originalImplementation.tokenPOST(input);
3009
+ }
3010
+ })
3011
+ },
2577
3012
  passwordless: {
2578
3013
  config: (config2) => {
2579
3014
  const originalEmailDeliveryOverride = config2.emailDelivery?.override;
@@ -2836,6 +3271,7 @@ var init = createPluginInitFunction(
2836
3271
  rowndAppSecret: config2.rowndAppSecret,
2837
3272
  enableDebugLogs: config2.enableDebugLogs,
2838
3273
  clientDomains: config2.clientDomains,
3274
+ crossDeviceConfirmationBypass: config2.crossDeviceConfirmationBypass,
2839
3275
  telemetry: config2.telemetry,
2840
3276
  schema: config2.schema,
2841
3277
  appConfig: config2.appConfig,
@@ -2863,6 +3299,7 @@ export {
2863
3299
  HUB_LOGIN_PAGE_PATH,
2864
3300
  HUB_VERIFY_EMAIL_PAGE_PATH,
2865
3301
  INSTANT_AUTH_METHOD_ID,
3302
+ PASSWORDLESS_BYPASS_DEVICE_CONFIRMATION_PARAM,
2866
3303
  PLUGIN_ID,
2867
3304
  PLUGIN_SDK_VERSION,
2868
3305
  PLUGIN_VERSION,
@@ -2870,6 +3307,7 @@ export {
2870
3307
  ROWND_JWT_CLAIMS,
2871
3308
  ROWND_PLUGIN_ERROR_MESSAGES,
2872
3309
  RowndPluginError,
3310
+ createMagicLinkWithConfirmationBypass,
2873
3311
  index_default as default,
2874
3312
  getRowndClient,
2875
3313
  init,