diff --git a/.storybook/main.ts b/.storybook/main.ts
index eeae939f3..e894225d5 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -8,8 +8,8 @@ const config: StorybookConfig = {
"@storybook/addon-actions",
"@storybook/addon-links",
"@storybook/addon-interactions",
- "@storybook/addon-designs",
// "@storybook/addon-actions/register",
+ "@storybook/addon-designs",
],
async webpackFinal(config, { configType }) {
if (config.module?.rules) {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa44ca008..28b9b7ff1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,146 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased]
+## [0.42.0] - 2024-05-24
+
+### Breaking changes
+
+- Removed `ThirdPartyEmailPassword` and `ThirdPartyPasswordless` recipes.
+- `EmailPassword` recipe:
+
+ - Removed embeddable components: `SignInUp`, `SignInAndUpTheme`
+ - Removed overridable components: `EmailPasswordSignIn`, `EmailPasswordSignInFooter`, `EmailPasswordSignInHeader`, `EmailPasswordSignUp`, `EmailPasswordSignUpFooter`, `EmailPasswordSignUpHeader`
+ - Moved `useShadowDom`, `defaultToSignUp`, `privacyPolicyLink`, `termsOfServiceLink` from the config to the root configuration passed to `SuperTokens.init`.
+
+- `Passwordless` recipe:
+
+ - Removed embeddable components: `SignInUp`
+ - Removed overrideable components: `PasswordlessSignInUpHeader_Override`, `PasswordlessSignInUpFooter_Override`
+ - Removed the `guessInternationPhoneNumberFromInputPhoneNumber` configurable callback, since now the user sets if they are entering email or a phone number explicitly
+ - Moved `useShadowDom`, `privacyPolicyLink`, `termsOfServiceLink` from the config to the root configuration passed to `SuperTokens.init`.
+ - Changed the UX of the contactinfo entry form for `EMAIL_OR_PHONE`
+ - Added `defaultToEmail` configuration option, which decides if the contact info input form starts in the email or phone state if the `contactMethod` is set to `EMAIL_OR_PHONE`
+
+- `ThirdParty` recipe:
+
+ - Removed embeddable components: `SignInAndUp`
+ - Removed overridable components: `ThirdPartySignInAndUpHeader`, `ThirdPartySignUpFooter`
+ - Moved `useShadowDom`, `privacyPolicyLink`, `termsOfServiceLink` from the config to the root configuration passed to `SuperTokens.init`.
+
+- Removed `SESSION_ALREADY_EXISTS` event from auth recipes and moved it into the `Session` recipe
+- Added new keys to `data-supertokens` props of several elements
+- Updated some styles to work with the updated UI structure
+- Renamed translation strings to reflect the new component/UI structure:
+ - `EMAIL_PASSWORD_SIGN_IN_FORGOT_PW_LINK` instead of `EMAIL_PASSWORD_SIGN_IN_FOOTER_FORGOT_PW_LINK`
+ - `AUTH_PAGE_HEADER_TITLE_SIGN_IN_AND_UP` instead of `PWLESS_SIGN_IN_UP_HEADER_TITLE` and `THIRD_PARTY_SIGN_IN_AND_UP_HEADER_TITLE`
+ - `AUTH_PAGE_HEADER_TITLE_SIGN_IN` instead of `EMAIL_PASSWORD_SIGN_IN_HEADER_TITLE`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_UP_START` instead of `EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_START`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_UP_SIGN_IN_LINK` instead of `EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_SIGN_UP_LINK`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_UP_END` instead of `EMAIL_PASSWORD_SIGN_IN_HEADER_SUBTITLE_END`
+ - `AUTH_PAGE_HEADER_TITLE_SIGN_UP` instead of `EMAIL_PASSWORD_SIGN_UP_HEADER_TITLE`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_IN_START` instead of `EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_START`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_IN_SIGN_UP_LINK` instead of `EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_SIGN_IN_LINK`
+ - `AUTH_PAGE_HEADER_SUBTITLE_SIGN_IN_END` instead of `EMAIL_PASSWORD_SIGN_UP_HEADER_SUBTITLE_END`
+ - `AUTH_PAGE_FOOTER_START` instead of `EMAIL_PASSWORD_SIGN_UP_FOOTER_START`, `PWLESS_SIGN_IN_UP_FOOTER_START` and `THIRD_PARTY_SIGN_IN_UP_FOOTER_START`
+ - `AUTH_PAGE_FOOTER_TOS` instead of: `EMAIL_PASSWORD_SIGN_UP_FOOTER_TOS`, `PWLESS_SIGN_IN_UP_FOOTER_TOS` and `THIRD_PARTY_SIGN_IN_UP_FOOTER_TOS`
+ - `AUTH_PAGE_FOOTER_AND` instead of `EMAIL_PASSWORD_SIGN_UP_FOOTER_AND`, `PWLESS_SIGN_IN_UP_FOOTER_AND` and `THIRD_PARTY_SIGN_IN_UP_FOOTER_AND`
+ - `AUTH_PAGE_FOOTER_PP` instead of `EMAIL_PASSWORD_SIGN_UP_FOOTER_PP`, `PWLESS_SIGN_IN_UP_FOOTER_PP` and `THIRD_PARTY_SIGN_IN_UP_FOOTER_PP`
+ - `AUTH_PAGE_FOOTER_END` instead of `EMAIL_PASSWORD_SIGN_UP_FOOTER_END`, `PWLESS_SIGN_IN_UP_FOOTER_END` and `THIRD_PARTY_SIGN_IN_UP_FOOTER_END`
+
+### Changes
+
+- Added overrideable components:
+ - General: `AuthPageComponentList`, `AuthPageHeader`, `AuthPageFooter`.
+ - These can be overridden by using `AuthRecipeComponentsOverrideContextProvider`
+ - `Passwordless`: `PasswordlessContinueWithPasswordless_Override`
+- Added new embeddable components:
+ - General: `AuthPage` and `AuthPageTheme`
+ - `EmailPassword`: `SignInTheme`, `SignUpTheme`
+- Added a new `style` prop to the root level config
+
+### Migration guide
+
+#### Removed recipes
+
+- If you were using `ThirdPartyEmailPassword`, you should now init `ThirdParty` and `EmailPassword` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [EmailPassword](https://supertokens.com/docs/emailpassword/introduction) for more information.
+
+- If you were using `ThirdPartyPasswordless`, you should now init `ThirdParty` and `Passwordless` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [Passwordless](https://supertokens.com/docs/passwordless/introduction) for more information.
+
+#### Moved configuration options
+
+Several configuration options (`useShadowDom`, `defaultToSignUp`, `privacyPolicyLink`, `termsOfServiceLink`) were moved to the root configuration (the one passed directly to `SuperTokens.init`) out of recipe specific configs. The function of these props remain identical, the only necessary migration is moving them:
+
+Before:
+
+```tsx
+SuperTokens.init({
+ appInfo: {
+ // appInfo
+ },
+ recipeList: [
+ EmailPassword.init({
+ useShadowDom: false,
+ signInAndUpFeature: {
+ defaultToSignUp: true,
+ signUpForm: {
+ privacyPolicyLink: "http://example.com",
+ termsOfServiceLink: "http://example.com",
+ },
+ },
+ }),
+ Session.init(),
+ ],
+});
+```
+
+After:
+
+```tsx
+SuperTokens.init({
+ appInfo: {
+ // appInfo
+ },
+ useShadowDom: false,
+ defaultToSignUp: true,
+ privacyPolicyLink: "http://example.com",
+ termsOfServiceLink: "http://example.com",
+ recipeList: [EmailPassword.init(), Session.init()],
+});
+```
+
+#### Removed embeddable components
+
+The auth page related embeddable components (`SignInAndUp`, `SignInUp`) and the related theme components were removed. We instead recommend you to use the new `AuthPage` component with the appropriate pre-built UI objects and factorsIds set. For more information check the following [guide](https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/embed-sign-in-up-form)
+
+Before:
+
+```tsx
+import { SignInAndUp } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
+
+const Component = () => {
+ const navigate = useNavigate();
+
+ return ;
+};
+```
+
+After:
+
+```tsx
+import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
+import { AuthPage } from "supertokens-auth-react/ui";
+
+const Component = () => {
+ const navigate = useNavigate();
+
+ return ;
+};
+```
+
+#### Updated styles
+
+Some parts of our default styles have been changed, including some changes to the `data-supertokens` props added to elements. Since customizations can take many forms we cannot give you exact guidance on how/what needs to change. In almost all cases, no updates should be required, but please check that your custom styles still work as you expect.
+
## [0.41.1] - 2024-05-13
### Fixes
diff --git a/examples/for-tests-react-16/src/App.js b/examples/for-tests-react-16/src/App.js
index 321720262..41c323070 100644
--- a/examples/for-tests-react-16/src/App.js
+++ b/examples/for-tests-react-16/src/App.js
@@ -11,8 +11,6 @@ import EmailVerification from "supertokens-auth-react/recipe/emailverification";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Passwordless from "supertokens-auth-react/recipe/passwordless";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
-import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
import UserRoles from "supertokens-auth-react/recipe/userroles";
import Multitenancy from "supertokens-auth-react/recipe/multitenancy";
import MultiFactorAuth from "supertokens-auth-react/recipe/multifactorauth";
@@ -92,12 +90,6 @@ if (getQueryParams("passwordlessDefaultCountry")) {
const passwordlessDefaultCountry = window.localStorage.getItem("passwordlessDefaultCountry") || undefined;
-if (getQueryParams("passwordlessDisablePhoneGuess")) {
- window.localStorage.setItem("passwordlessDisablePhoneGuess", getQueryParams("passwordlessDisablePhoneGuess"));
-}
-
-const passwordlessDisablePhoneGuess = window.localStorage.getItem("passwordlessDisablePhoneGuess") || undefined;
-
if (getQueryParams("authRecipe")) {
window.localStorage.setItem("authRecipe", getQueryParams("authRecipe"));
}
@@ -255,22 +247,19 @@ let recipeList = [
let enabledRecipes = getEnabledRecipes();
-if (enabledRecipes.includes("thirdparty")) {
+if (
+ enabledRecipes.includes("thirdparty") ||
+ enabledRecipes.includes("thirdpartyemailpassword") ||
+ enabledRecipes.includes("thirdpartypasswordless")
+) {
recipeList = [getThirdPartyConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("emailpassword")) {
+if (enabledRecipes.includes("emailpassword") || enabledRecipes.includes("thirdpartyemailpassword")) {
recipeList = [getEmailPasswordConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipeList = [getThirdPartyEmailPasswordConfigs(testContext), ...recipeList];
-}
-if (enabledRecipes.includes("passwordless")) {
+if (enabledRecipes.includes("passwordless") || enabledRecipes.includes("thirdpartypasswordless")) {
recipeList = [getPasswordlessConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipeList = [getThirdPartyPasswordlessConfigs(testContext), ...recipeList];
-}
-
if (emailVerificationMode !== "OFF") {
recipeList.push(getEmailVerificationConfigs(testContext));
}
@@ -295,10 +284,10 @@ SuperTokens.init({
languageTranslations: {
translations: {
en: {
- PWLESS_SIGN_IN_UP_FOOTER_TOS: "TOS",
+ AUTH_PAGE_FOOTER_TOS: "TOS",
},
hu: {
- PWLESS_SIGN_IN_UP_FOOTER_TOS: "ÁSZF",
+ AUTH_PAGE_FOOTER_TOS: "ÁSZF",
},
},
},
@@ -308,8 +297,6 @@ SuperTokens.init({
emailpassword: "EMAIL_PASSWORD",
thirdparty: "THIRD_PARTY",
passwordless: "PASSWORDLESS",
- thirdpartypasswordless: "THIRDPARTYPASSWORDLESS",
- thirdpartyemailpassword: "THIRD_PARTY_EMAIL_PASSWORD",
}[context.recipeId];
console.log(`ST_LOGS SUPERTOKENS GET_REDIRECTION_URL SUCCESS ${logId}`);
@@ -322,14 +309,19 @@ SuperTokens.init({
console.log(`ST_LOGS SUPERTOKENS GET_REDIRECTION_URL ${context.action}`);
}
},
+ useShadowDom,
+ privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
+ termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
+ defaultToSignUp,
+ disableAuthRoute: testContext.disableDefaultUI,
recipeList,
});
/* App */
function App() {
useEffect(() => {
- window.addEventListener("TPEP.getAuthorisationURLWithQueryParamsAndSetState", async () => {
- ThirdPartyEmailPassword.getAuthorisationURLWithQueryParamsAndSetState({
+ window.addEventListener("TP.getAuthorisationURLWithQueryParamsAndSetState", async () => {
+ ThirdParty.getAuthorisationURLWithQueryParamsAndSetState({
providerId: "google",
authorisationURL: "",
userContext: {
@@ -447,18 +439,8 @@ export function DashboardHelper({ redirectOnLogout, ...props } = {}) {
const [sessionInfoUsingFetch, setSessionInfoUsingFetch] = useState(undefined);
async function logout() {
- const useRecipe = getQueryParams("rid") || authRecipe;
- if (useRecipe === "thirdparty") {
- await ThirdParty.signOut();
- } else if (useRecipe === "thirdpartyemailpassword") {
- await ThirdPartyEmailPassword.signOut();
- } else if (useRecipe === "passwordless") {
- await Passwordless.signOut();
- } else if (useRecipe === "thirdpartypasswordless") {
- await ThirdPartyPasswordless.signOut();
- } else {
- await EmailPassword.signOut();
- }
+ await Session.signOut();
+
if (redirectOnLogout) {
if (props.history === undefined) {
window.location.href = "/auth";
@@ -546,7 +528,6 @@ function SessionInfoTable({ sessionInfo }) {
function getEmailVerificationConfigs({ disableDefaultUI }) {
return EmailVerification.init({
- useShadowDom,
disableDefaultUI,
sendVerifyEmailScreen: {
style: theme,
@@ -617,10 +598,6 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
log(`DOES_EMAIL_EXIST`);
return implementation.doesEmailExist(...args);
},
- sendPasswordResetEmail(...args) {
- log(`SEND_PASSWORD_RESET_EMAIL`);
- return implementation.sendPasswordResetEmail(...args);
- },
signIn(...args) {
log(`SIGN_IN`);
return implementation.signIn(...args);
@@ -629,9 +606,28 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
log(`SIGN_UP`);
return implementation.signUp(...args);
},
- submitNewPassword(...args) {
+ sendPasswordResetEmail(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`SEND_PASSWORD_RESET_EMAIL RECEIVED_USER_CONTEXT`);
+ }
+
+ log(`SEND_PASSWORD_RESET_EMAIL`);
+ return implementation.sendPasswordResetEmail(input);
+ },
+ getResetPasswordTokenFromURL(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`GET_RESET_TOKEN_FROM_URL RECEIVED_USER_CONTEXT`);
+ }
+
+ return implementation.getResetPasswordTokenFromURL(input);
+ },
+ submitNewPassword(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`SUBMIT_NEW_PASSWORD RECEIVED_USER_CONTEXT`);
+ }
+
log(`SUBMIT_NEW_PASSWORD`);
- return implementation.submitNewPassword(...args);
+ return implementation.submitNewPassword(input);
},
};
},
@@ -646,7 +642,6 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
onHandleEvent: async (context) => {
console.log(`ST_LOGS EMAIL_PASSWORD ON_HANDLE_EVENT ${context.action}`);
},
- useShadowDom,
resetPasswordUsingTokenFeature: {
disableDefaultUI,
enterEmailForm: {
@@ -657,150 +652,18 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
},
},
signInAndUpFeature: {
- disableDefaultUI,
- defaultToSignUp,
signInForm: {
style: theme.style,
},
signUpForm: {
style: theme.style,
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
formFields,
},
},
});
}
-function getThirdPartyPasswordlessConfigs({ staticProviderList, disableDefaultUI, thirdPartyRedirectURL }) {
- let providers = [
- ThirdParty.Github.init(),
- ThirdParty.Google.init(),
- ThirdParty.Facebook.init(),
- ThirdParty.Apple.init(),
- {
- id: "custom",
- name: "Custom",
- },
- {
- id: "auth0",
- name: "Auth0",
- getRedirectURL: thirdPartyRedirectURL !== null ? () => thirdPartyRedirectURL : undefined,
- },
- {
- id: "mock-provider",
- name: "Mock Provider",
- },
- ];
- if (staticProviderList) {
- const ids = JSON.parse(staticProviderList);
- providers = ids.map((id) => providers.find((p) => p.id === id) || { id, name: id });
- }
-
- return ThirdPartyPasswordless.init({
- override: {
- functions: (implementation) => {
- const log = logWithPrefix(`ST_LOGS THIRDPARTYPASSWORDLESS OVERRIDE`);
-
- return {
- ...implementation,
- doesPasswordlessUserEmailExist(...args) {
- log(`DOES_PASSWORDLESS_USER_EMAIL_EXIST`);
- return implementation.doesPasswordlessUserEmailExist(...args);
- },
- doesPasswordlessUserPhoneNumberExist(...args) {
- log(`DOES_PASSWORDLESS_USER_PHONE_NUMBER_EXIST`);
- return implementation.doesPasswordlessUserPhoneNumberExist(...args);
- },
- createPasswordlessCode(...args) {
- log(`CREATE_CODE`);
- return implementation.createPasswordlessCode(...args);
- },
- resendPasswordlessCode(...args) {
- log(`RESEND_CODE`);
- return implementation.resendPasswordlessCode(...args);
- },
- consumePasswordlessCode(...args) {
- log(`CONSUME_CODE`);
- return implementation.consumePasswordlessCode(...args);
- },
- getPasswordlessLoginAttemptInfo(...args) {
- log(`GET_LOGIN_ATTEMPT_INFO`);
- return implementation.getPasswordlessLoginAttemptInfo(...args);
- },
- setPasswordlessLoginAttemptInfo(...args) {
- log(`SET_LOGIN_ATTEMPT_INFO`);
- return implementation.setPasswordlessLoginAttemptInfo(...args);
- },
- clearPasswordlessLoginAttemptInfo(...args) {
- log(`CLEAR_LOGIN_ATTEMPT_INFO`);
- return implementation.clearPasswordlessLoginAttemptInfo(...args);
- },
- getAuthorisationURLFromBackend(...args) {
- log(`GET_OAUTH_AUTHORISATION_URL`);
- return implementation.getAuthorisationURLFromBackend(...args);
- },
- getThirdPartyStateAndOtherInfoFromStorage(...args) {
- log(`GET_OAUTH_STATE`);
- return implementation.getThirdPartyStateAndOtherInfoFromStorage(...args);
- },
- getThirdPartyAuthorisationURLWithQueryParamsAndSetState(...args) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getThirdPartyAuthorisationURLWithQueryParamsAndSetState(...args);
- },
- setThirdPartyStateAndOtherInfoToStorage(...args) {
- log(`SET_OAUTH_STATE`);
- return implementation.setThirdPartyStateAndOtherInfoToStorage(...args);
- },
- thirdPartySignInAndUp(...args) {
- log(`THIRD_PARTY_SIGN_IN_AND_UP`);
- return implementation.thirdPartySignInAndUp(...args);
- },
- };
- },
- },
- preAPIHook: async (context) => {
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS PRE_API_HOOKS ${context.action}`);
- return context;
- },
- getRedirectionURL: async (context) => {
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS GET_REDIRECTION_URL ${context.action}`);
- },
- onHandleEvent: async (context) => {
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS ON_HANDLE_EVENT ${context.action}`);
- },
- useShadowDom,
- contactMethod: passwordlessContactMethodType,
- disablePasswordless: false,
- signInUpFeature: {
- disableDefaultUI,
- style: theme.style,
- thirdPartyProviderAndEmailOrPhoneFormStyle: `
- [data-supertokens~=providerCustom] {
- color: red;
- },
- `,
- privacyPolicyLink: "https://supertokens.io/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.io/legal/terms-and-conditions",
- providers,
- defaultCountry: passwordlessDefaultCountry,
- resendEmailOrSMSGapInSeconds: 2,
- guessInternationPhoneNumberFromInputPhoneNumber: passwordlessDisablePhoneGuess
- ? () => undefined
- : undefined,
- },
- linkClickedScreenFeature: {
- disableDefaultUI,
- style: theme.style,
- },
- mfaFeature: {
- disableDefaultUI,
- style: theme,
- },
- });
-}
-
-function getPasswordlessConfigs({ disableDefaultUI }) {
+function getPasswordlessConfigs({ disableDefaultUI, defaultToEmail }) {
return Passwordless.init({
override: {
functions: (implementation) => {
@@ -853,19 +716,12 @@ function getPasswordlessConfigs({ disableDefaultUI }) {
onHandleEvent: async (context) => {
console.log(`ST_LOGS PASSWORDLESS ON_HANDLE_EVENT ${context.action}`);
},
- useShadowDom,
contactMethod: passwordlessContactMethodType,
signInUpFeature: {
defaultCountry: passwordlessDefaultCountry,
- guessInternationPhoneNumberFromInputPhoneNumber: passwordlessDisablePhoneGuess
- ? () => undefined
- : undefined,
+ defaultToEmail,
resendEmailOrSMSGapInSeconds: 2,
- disableDefaultUI,
style: theme.style,
-
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
},
linkClickedScreenFeature: {
disableDefaultUI,
@@ -925,135 +781,18 @@ function getThirdPartyConfigs({ staticProviderList, disableDefaultUI, thirdParty
return {
...implementation,
- getAuthorisationURLWithQueryParamsAndSetState(...args) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getAuthorisationURLWithQueryParamsAndSetState(...args);
- },
- getAuthorisationURLFromBackend(...args) {
- log(`GET_OAUTH_AUTHORISATION_URL`);
- return implementation.getAuthorisationURLFromBackend(...args);
- },
- getStateAndOtherInfoFromStorage(...args) {
- log(`GET_OAUTH_STATE`);
- return implementation.getStateAndOtherInfoFromStorage(...args);
- },
- setStateAndOtherInfoToStorage(...args) {
- log(`SET_OAUTH_STATE`);
- return implementation.setStateAndOtherInfoToStorage(...args);
- },
- signInAndUp(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.signInAndUp(...args);
- },
- };
- },
- },
- useShadowDom,
- signInAndUpFeature: {
- disableDefaultUI,
- style: theme.style,
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
- providers,
- },
-
- oAuthCallbackScreen: {
- style: theme.style,
- },
- });
-}
-
-function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultUI, thirdPartyRedirectURL }) {
- let providers = [
- ThirdParty.Github.init(),
- ThirdParty.Google.init(),
- ThirdParty.Facebook.init(),
- ThirdParty.Apple.init(),
- {
- id: "custom",
- name: "Custom",
- },
- {
- id: "auth0",
- name: "Auth0",
- getRedirectURL: thirdPartyRedirectURL !== null ? () => thirdPartyRedirectURL : undefined,
- },
- {
- id: "mock-provider",
- name: "Mock Provider",
- },
- ];
- if (staticProviderList) {
- const ids = JSON.parse(staticProviderList);
- providers = ids.map((id) => providers.find((p) => p.id === id) || { id, name: id });
- }
- return ThirdPartyEmailPassword.init({
- preAPIHook: async (context) => {
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD PRE_API_HOOKS ${context.action}`);
- return context;
- },
- getRedirectionURL: async (context) => {
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD GET_REDIRECTION_URL ${context.action}`);
- if (context.action === "SUCCESS") {
- setIsNewUserToStorage("thirdpartyemailpassword", context.isNewRecipeUser);
- return context.redirectToPath || "/dashboard";
- }
- },
- onHandleEvent: async (context) => {
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD ON_HANDLE_EVENT ${context.action}`);
- },
- override: {
- functions: (implementation) => {
- const log = logWithPrefix(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD OVERRIDE`);
-
- return {
- ...implementation,
- getAuthorisationURLWithQueryParamsAndSetState(input) {
- if (input.userContext["key"] !== undefined) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE RECEIVED_USER_CONTEXT`);
- }
-
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getAuthorisationURLWithQueryParamsAndSetState(input);
- },
generateStateToSendToOAuthProvider(input) {
if (input.userContext["key"] !== undefined) {
log(`GENERATE_STATE RECEIVED_USER_CONTEXT`);
}
-
return implementation.generateStateToSendToOAuthProvider(input);
},
- thirdPartySignInAndUp(input) {
- if (input.userContext["key"] !== undefined) {
- log(`SIGN_IN_AND_UP RECEIVED_USER_CONTEXT`);
- }
-
- log(`SIGN_IN_AND_UP`);
- return implementation.thirdPartySignInAndUp(input);
- },
- emailPasswordSignIn(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.emailPasswordSignIn(...args);
- },
- emailPasswordSignUp(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.emailPasswordSignUp(...args);
- },
- setStateAndOtherInfoToStorage(input) {
- if (input.userContext["key"] !== undefined) {
- log(`SET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
- }
-
- log(`SET_OAUTH_STATE`);
- return implementation.setStateAndOtherInfoToStorage(input);
- },
- getStateAndOtherInfoFromStorage(input) {
+ getAuthorisationURLWithQueryParamsAndSetState(input) {
if (input.userContext["key"] !== undefined) {
- log(`GET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
+ log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE RECEIVED_USER_CONTEXT`);
}
-
- log(`GET_OAUTH_STATE`);
- return implementation.getStateAndOtherInfoFromStorage(input);
+ log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
+ return implementation.getAuthorisationURLWithQueryParamsAndSetState(input);
},
getAuthorisationURLFromBackend(input) {
if (input.userContext["key"] !== undefined) {
@@ -1079,33 +818,31 @@ function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultU
return implementation.getAuthorisationURLFromBackend(input);
},
- submitNewPassword(input) {
+ getStateAndOtherInfoFromStorage(input) {
if (input.userContext["key"] !== undefined) {
- log(`SUBMIT_NEW_PASSWORD RECEIVED_USER_CONTEXT`);
+ log(`GET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
}
- log(`SUBMIT_NEW_PASSWORD`);
- return implementation.submitNewPassword(input);
+ log(`GET_OAUTH_STATE`);
+ return implementation.getStateAndOtherInfoFromStorage(input);
},
- sendPasswordResetEmail(input) {
+
+ setStateAndOtherInfoToStorage(input) {
if (input.userContext["key"] !== undefined) {
- log(`SEND_PASSWORD_RESET_EMAIL RECEIVED_USER_CONTEXT`);
+ log(`SET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
}
- log(`SEND_PASSWORD_RESET_EMAIL`);
- return implementation.sendPasswordResetEmail(input);
+ log(`SET_OAUTH_STATE`);
+ return implementation.setStateAndOtherInfoToStorage(input);
},
- getResetPasswordTokenFromURL(input) {
+ signInAndUp(input) {
if (input.userContext["key"] !== undefined) {
- log(`GET_RESET_TOKEN_FROM_URL RECEIVED_USER_CONTEXT`);
+ log(`SIGN_IN_AND_UP RECEIVED_USER_CONTEXT`);
}
-
- return implementation.getResetPasswordTokenFromURL(input);
- },
- doesEmailExist(...args) {
- log(`DOES_EMAIL_EXIST`);
- return implementation.doesEmailExist(...args);
+ log(`SIGN_IN_AND_UP`);
+ return implementation.signInAndUp(input);
},
+
getAuthStateFromURL(input) {
if (input.userContext["key"] !== undefined) {
log(`GET_AUTH_STATE_FROM_URL RECEIVED_USER_CONTEXT`);
@@ -1123,22 +860,10 @@ function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultU
};
},
},
- useShadowDom,
- resetPasswordUsingTokenFeature: {
- disableDefaultUI,
- },
signInAndUpFeature: {
- disableDefaultUI,
- signInForm: {},
- signUpForm: {
- formFields,
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
- },
style: theme.style,
providers,
},
- disableEmailPassword: false,
oAuthCallbackScreen: {
style: theme.style,
diff --git a/examples/for-tests-react-16/src/AppWithReactDomRouter.js b/examples/for-tests-react-16/src/AppWithReactDomRouter.js
index 3dbce5ee8..f24b1ef67 100644
--- a/examples/for-tests-react-16/src/AppWithReactDomRouter.js
+++ b/examples/for-tests-react-16/src/AppWithReactDomRouter.js
@@ -1,20 +1,13 @@
import React, { useState } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
-import { SignInAndUp } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
+import { getSuperTokensRoutesForReactRouterDom, AuthPage } from "supertokens-auth-react/ui";
+import { ResetPasswordUsingToken } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
-import {
- ResetPasswordUsingToken,
- SignInAndUp as TPSignInAndUp,
- ThirdPartySignInAndUpCallback,
-} from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
import { BaseComponent, Home, Contact, Dashboard, DashboardNoAuthRequired } from "./App";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
-import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+import { ThirdPartyPreBuiltUI, SignInAndUpCallback } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
import { MultiFactorAuthPreBuiltUI } from "supertokens-auth-react/recipe/multifactorauth/prebuiltui";
import { TOTPPreBuiltUI } from "supertokens-auth-react/recipe/totp/prebuiltui";
import { AccessDeniedScreen } from "supertokens-auth-react/recipe/session/prebuiltui";
@@ -26,21 +19,15 @@ function AppWithReactDomRouter(props) {
const emailVerificationMode = window.localStorage.getItem("mode") || "OFF";
let recipePreBuiltUIList = [TOTPPreBuiltUI];
- if (enabledRecipes.includes("emailpassword")) {
- recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
- }
- if (enabledRecipes.includes("thirdparty")) {
+ if (enabledRecipes.some((r) => r.startsWith("thirdparty"))) {
recipePreBuiltUIList.push(ThirdPartyPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipePreBuiltUIList.push(ThirdPartyEmailPasswordPreBuiltUI);
+ if (enabledRecipes.some((r) => r.endsWith("emailpassword"))) {
+ recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
}
- if (enabledRecipes.includes("passwordless")) {
+ if (enabledRecipes.some((r) => r.endsWith("passwordless"))) {
recipePreBuiltUIList.push(PasswordlessPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipePreBuiltUIList.push(ThirdPartyPasswordlessPreBuiltUI);
- }
if (emailVerificationMode !== "OFF") {
recipePreBuiltUIList.push(EmailVerificationPreBuiltUI);
@@ -128,7 +115,24 @@ function AppWithReactDomRouter(props) {
/>
} />
- } />
+
+ }
+ />
+
+ }
+ />
{/* User context paths */}
{isForUserContext && (
@@ -147,7 +151,7 @@ function AppWithReactDomRouter(props) {
}
/>
diff --git a/examples/for-tests-react-16/src/AppWithReactDomRouterV5.js b/examples/for-tests-react-16/src/AppWithReactDomRouterV5.js
index b24796bb7..b7c04784f 100644
--- a/examples/for-tests-react-16/src/AppWithReactDomRouterV5.js
+++ b/examples/for-tests-react-16/src/AppWithReactDomRouterV5.js
@@ -1,11 +1,8 @@
import React, { useState } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-domv5";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
+import { getSuperTokensRoutesForReactRouterDom, AuthPage } from "supertokens-auth-react/ui";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
-import { SignInAndUp } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { BaseComponent, Home, Contact, Dashboard, DashboardNoAuthRequired } from "./App";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
@@ -21,22 +18,15 @@ function AppWithReactDomRouter(props) {
const emailVerificationMode = window.localStorage.getItem("mode") || "OFF";
let recipePreBuiltUIList = [TOTPPreBuiltUI];
- if (enabledRecipes.includes("emailpassword")) {
- recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
- }
- if (enabledRecipes.includes("thirdparty")) {
+ if (enabledRecipes.some((r) => r.startsWith("thirdparty"))) {
recipePreBuiltUIList.push(ThirdPartyPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipePreBuiltUIList.push(ThirdPartyEmailPasswordPreBuiltUI);
+ if (enabledRecipes.some((r) => r.endsWith("emailpassword"))) {
+ recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
}
- if (enabledRecipes.includes("passwordless")) {
+ if (enabledRecipes.some((r) => r.endsWith("passwordless"))) {
recipePreBuiltUIList.push(PasswordlessPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipePreBuiltUIList.push(ThirdPartyPasswordlessPreBuiltUI);
- }
-
if (emailVerificationMode !== "OFF") {
recipePreBuiltUIList.push(EmailVerificationPreBuiltUI);
}
@@ -112,8 +102,20 @@ function AppWithReactDomRouter(props) {
-
+
+
+ }
+ />
diff --git a/examples/for-tests-react-16/src/AppWithoutRouter.js b/examples/for-tests-react-16/src/AppWithoutRouter.js
index 7937b2898..859ee1ea3 100644
--- a/examples/for-tests-react-16/src/AppWithoutRouter.js
+++ b/examples/for-tests-react-16/src/AppWithoutRouter.js
@@ -1,8 +1,6 @@
import React, { useEffect, useState } from "react";
import { BaseComponent, Home } from "./App";
import { getRoutingComponent, canHandleRoute } from "supertokens-auth-react/ui";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
@@ -25,21 +23,15 @@ function Routing() {
const emailVerificationMode = window.localStorage.getItem("mode") || "OFF";
let recipePreBuiltUIList = [];
- if (enabledRecipes.includes("thirdparty")) {
+ if (enabledRecipes.some((r) => r.startsWith("thirdparty"))) {
recipePreBuiltUIList.push(ThirdPartyPreBuiltUI);
}
- if (enabledRecipes.includes("emailpassword")) {
+ if (enabledRecipes.some((r) => r.endsWith("emailpassword"))) {
recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipePreBuiltUIList.push(ThirdPartyEmailPasswordPreBuiltUI);
- }
- if (enabledRecipes.includes("passwordless")) {
+ if (enabledRecipes.some((r) => r.endsWith("passwordless"))) {
recipePreBuiltUIList.push(PasswordlessPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipePreBuiltUIList.push(ThirdPartyPasswordlessPreBuiltUI);
- }
if (emailVerificationMode !== "OFF") {
recipePreBuiltUIList.push(EmailVerificationPreBuiltUI);
diff --git a/examples/for-tests-react-16/src/testContext.js b/examples/for-tests-react-16/src/testContext.js
index cbfe55cec..0d1a4caf3 100644
--- a/examples/for-tests-react-16/src/testContext.js
+++ b/examples/for-tests-react-16/src/testContext.js
@@ -20,6 +20,7 @@ export function getTestContext() {
? localStorage.getItem("firstFactors").split(", ")
: undefined,
enableMFA: localStorage.getItem("enableMFA") === "true",
+ defaultToEmail: localStorage.getItem("defaultToEmail") !== "false",
disableRedirectionAfterSuccessfulSignInUp:
localStorage.getItem("disableRedirectionAfterSuccessfulSignInUp") === "true",
};
@@ -31,7 +32,7 @@ export function getEnabledRecipes() {
let enabledRecipes = [];
- if (testContext.enableAllRecipes) {
+ if (testContext.enableAllRecipes || testContext.authRecipe === "all") {
enabledRecipes = [
"emailpassword",
"thirdparty",
diff --git a/examples/for-tests/src/App.js b/examples/for-tests/src/App.js
index 9b28b6d16..048337ec8 100644
--- a/examples/for-tests/src/App.js
+++ b/examples/for-tests/src/App.js
@@ -11,8 +11,6 @@ import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Passwordless from "supertokens-auth-react/recipe/passwordless";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
import Multitenancy from "supertokens-auth-react/recipe/multitenancy";
-import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
import UserRoles from "supertokens-auth-react/recipe/userroles";
import MultiFactorAuth from "supertokens-auth-react/recipe/multifactorauth";
import TOTP from "supertokens-auth-react/recipe/totp";
@@ -88,12 +86,6 @@ if (getQueryParams("passwordlessDefaultCountry")) {
const passwordlessDefaultCountry = window.localStorage.getItem("passwordlessDefaultCountry") || undefined;
-if (getQueryParams("passwordlessDisablePhoneGuess")) {
- window.localStorage.setItem("passwordlessDisablePhoneGuess", getQueryParams("passwordlessDisablePhoneGuess"));
-}
-
-const passwordlessDisablePhoneGuess = window.localStorage.getItem("passwordlessDisablePhoneGuess") || undefined;
-
if (getQueryParams("authRecipe")) {
window.localStorage.setItem("authRecipe", getQueryParams("authRecipe"));
}
@@ -409,7 +401,7 @@ let recipeList = [
console.log(`ST_LOGS SESSION PRE_API_HOOKS ${ctx.action}`);
}
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `SESSION ${ctx.action}`) {
+ if (localStorage.getItem(`SHOW_GENERAL_ERROR`)?.includes(ctx.action)) {
let requestBody = ctx.requestInit.body === undefined ? "{}" : ctx.requestInit.body;
let jsonBody = JSON.parse(requestBody);
jsonBody = {
@@ -431,21 +423,19 @@ let recipeList = [
let enabledRecipes = getEnabledRecipes();
-if (enabledRecipes.includes("thirdparty")) {
+if (
+ enabledRecipes.includes("thirdparty") ||
+ enabledRecipes.includes("thirdpartyemailpassword") ||
+ enabledRecipes.includes("thirdpartypasswordless")
+) {
recipeList = [getThirdPartyConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("emailpassword")) {
+if (enabledRecipes.includes("emailpassword") || enabledRecipes.includes("thirdpartyemailpassword")) {
recipeList = [getEmailPasswordConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipeList = [getThirdPartyEmailPasswordConfigs(testContext), ...recipeList];
-}
-if (enabledRecipes.includes("passwordless")) {
+if (enabledRecipes.includes("passwordless") || enabledRecipes.includes("thirdpartypasswordless")) {
recipeList = [getPasswordlessConfigs(testContext), ...recipeList];
}
-if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipeList = [getThirdPartyPasswordlessConfigs(testContext), ...recipeList];
-}
if (emailVerificationMode !== "OFF") {
recipeList.push(getEmailVerificationConfigs(testContext));
@@ -471,10 +461,10 @@ SuperTokens.init({
languageTranslations: {
translations: {
en: {
- PWLESS_SIGN_IN_UP_FOOTER_TOS: "TOS",
+ AUTH_PAGE_FOOTER_TOS: "TOS",
},
hu: {
- PWLESS_SIGN_IN_UP_FOOTER_TOS: "ÁSZF",
+ AUTH_PAGE_FOOTER_TOS: "ÁSZF",
},
},
},
@@ -499,14 +489,19 @@ SuperTokens.init({
console.log(`ST_LOGS SUPERTOKENS GET_REDIRECTION_URL ${context.action}`);
}
},
+ useShadowDom,
+ privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
+ termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
+ defaultToSignUp,
+ disableAuthRoute: testContext.disableDefaultUI,
recipeList,
});
/* App */
function App() {
useEffect(() => {
- window.addEventListener("TPEP.getAuthorisationURLWithQueryParamsAndSetState", async () => {
- ThirdPartyEmailPassword.getAuthorisationURLWithQueryParamsAndSetState({
+ window.addEventListener("TP.getAuthorisationURLWithQueryParamsAndSetState", async () => {
+ ThirdParty.getAuthorisationURLWithQueryParamsAndSetState({
providerId: "google",
authorisationURL: "",
userContext: {
@@ -705,7 +700,6 @@ function SessionInfoTable({ sessionInfo }) {
function getEmailVerificationConfigs({ disableDefaultUI }) {
return EmailVerification.init({
- useShadowDom,
disableDefaultUI,
sendVerifyEmailScreen: {
style: theme,
@@ -739,7 +733,7 @@ function getEmailVerificationConfigs({ disableDefaultUI }) {
},
},
preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `EMAIL_VERIFICATION ${context.action}`) {
+ if (localStorage.getItem(`SHOW_GENERAL_ERROR`)?.includes(context.action)) {
let errorFromStorage = localStorage.getItem("TRANSLATED_GENERAL_ERROR");
let jsonBody = JSON.parse(context.requestInit.body);
@@ -799,6 +793,14 @@ function getSignInFormFields(formType) {
},
];
default:
+ return [
+ {
+ id: "email",
+ },
+ {
+ id: "test",
+ },
+ ];
return;
}
}
@@ -820,10 +822,6 @@ function getEmailPasswordConfigs({ disableDefaultUI, formFieldType }) {
log(`DOES_EMAIL_EXIST`);
return implementation.doesEmailExist(...args);
},
- sendPasswordResetEmail(...args) {
- log(`SEND_PASSWORD_RESET_EMAIL`);
- return implementation.sendPasswordResetEmail(...args);
- },
signIn(...args) {
log(`SIGN_IN`);
return implementation.signIn(...args);
@@ -832,15 +830,34 @@ function getEmailPasswordConfigs({ disableDefaultUI, formFieldType }) {
log(`SIGN_UP`);
return implementation.signUp(...args);
},
- submitNewPassword(...args) {
+ sendPasswordResetEmail(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`SEND_PASSWORD_RESET_EMAIL RECEIVED_USER_CONTEXT`);
+ }
+
+ log(`SEND_PASSWORD_RESET_EMAIL`);
+ return implementation.sendPasswordResetEmail(input);
+ },
+ getResetPasswordTokenFromURL(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`GET_RESET_TOKEN_FROM_URL RECEIVED_USER_CONTEXT`);
+ }
+
+ return implementation.getResetPasswordTokenFromURL(input);
+ },
+ submitNewPassword(input) {
+ if (input.userContext["key"] !== undefined) {
+ log(`SUBMIT_NEW_PASSWORD RECEIVED_USER_CONTEXT`);
+ }
+
log(`SUBMIT_NEW_PASSWORD`);
- return implementation.submitNewPassword(...args);
+ return implementation.submitNewPassword(input);
},
};
},
},
preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `EMAIL_PASSWORD ${context.action}`) {
+ if (localStorage.getItem(`SHOW_GENERAL_ERROR`)?.includes(context.action)) {
let errorFromStorage = localStorage.getItem("TRANSLATED_GENERAL_ERROR");
if (context.action === "EMAIL_EXISTS") {
@@ -864,7 +881,6 @@ function getEmailPasswordConfigs({ disableDefaultUI, formFieldType }) {
onHandleEvent: async (context) => {
console.log(`ST_LOGS EMAIL_PASSWORD ON_HANDLE_EVENT ${context.action}`);
},
- useShadowDom,
resetPasswordUsingTokenFeature: {
disableDefaultUI,
enterEmailForm: {
@@ -875,163 +891,19 @@ function getEmailPasswordConfigs({ disableDefaultUI, formFieldType }) {
},
},
signInAndUpFeature: {
- disableDefaultUI,
- defaultToSignUp,
signInForm: {
style: theme,
formFields: getSignInFormFields(formFieldType.signIn),
},
signUpForm: {
style: theme,
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
formFields: getSignUpFormFields(formFieldType.signUp),
},
},
});
}
-function getThirdPartyPasswordlessConfigs({ staticProviderList, disableDefaultUI, thirdPartyRedirectURL }) {
- let providers = [
- ThirdParty.Github.init(),
- ThirdParty.Google.init(),
- ThirdParty.Facebook.init(),
- ThirdParty.Apple.init(),
- {
- id: "custom",
- name: "Custom",
- },
- {
- id: "auth0",
- name: "Auth0",
- getRedirectURL: thirdPartyRedirectURL !== null ? () => thirdPartyRedirectURL : undefined,
- },
- {
- id: "mock-provider",
- name: "Mock Provider",
- },
- ];
- if (staticProviderList) {
- const ids = JSON.parse(staticProviderList);
- providers = ids.map((id) => providers.find((p) => p.id === id) || { id, name: id });
- }
- return ThirdPartyPasswordless.init({
- override: {
- functions: (implementation) => {
- const log = logWithPrefix(`ST_LOGS THIRDPARTYPASSWORDLESS OVERRIDE`);
-
- return {
- ...implementation,
- doesPasswordlessUserEmailExist(...args) {
- log(`DOES_PASSWORDLESS_USER_EMAIL_EXIST`);
- return implementation.doesPasswordlessUserEmailExist(...args);
- },
- doesPasswordlessUserPhoneNumberExist(...args) {
- log(`DOES_PASSWORDLESS_USER_PHONE_NUMBER_EXIST`);
- return implementation.doesPasswordlessUserPhoneNumberExist(...args);
- },
- createPasswordlessCode(...args) {
- log(`CREATE_CODE`);
- return implementation.createPasswordlessCode(...args);
- },
- resendPasswordlessCode(...args) {
- log(`RESEND_CODE`);
- return implementation.resendPasswordlessCode(...args);
- },
- consumePasswordlessCode(...args) {
- log(`CONSUME_CODE`);
- return implementation.consumePasswordlessCode(...args);
- },
- getPasswordlessLoginAttemptInfo(...args) {
- log(`GET_LOGIN_ATTEMPT_INFO`);
- return implementation.getPasswordlessLoginAttemptInfo(...args);
- },
- setPasswordlessLoginAttemptInfo(...args) {
- log(`SET_LOGIN_ATTEMPT_INFO`);
- return implementation.setPasswordlessLoginAttemptInfo(...args);
- },
- clearPasswordlessLoginAttemptInfo(...args) {
- log(`CLEAR_LOGIN_ATTEMPT_INFO`);
- return implementation.clearPasswordlessLoginAttemptInfo(...args);
- },
- getAuthorisationURLFromBackend(...args) {
- log(`GET_OAUTH_AUTHORISATION_URL`);
- return implementation.getAuthorisationURLFromBackend(...args);
- },
- getThirdPartyStateAndOtherInfoFromStorage(...args) {
- log(`GET_OAUTH_STATE`);
- return implementation.getThirdPartyStateAndOtherInfoFromStorage(...args);
- },
- getThirdPartyAuthorisationURLWithQueryParamsAndSetState(...args) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getThirdPartyAuthorisationURLWithQueryParamsAndSetState(...args);
- },
- setThirdPartyStateAndOtherInfoToStorage(...args) {
- log(`SET_OAUTH_STATE`);
- return implementation.setThirdPartyStateAndOtherInfoToStorage(...args);
- },
- thirdPartySignInAndUp(...args) {
- log(`THIRD_PARTY_SIGN_IN_AND_UP`);
- return implementation.thirdPartySignInAndUp(...args);
- },
- };
- },
- },
- preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `THIRD_PARTY_PASSWORDLESS ${context.action}`) {
- if (context.action === "GET_AUTHORISATION_URL") {
- context.url += "&generalError=true";
- } else {
- let jsonBody = JSON.parse(context.requestInit.body);
- jsonBody = {
- ...jsonBody,
- generalError: true,
- };
- context.requestInit.body = JSON.stringify(jsonBody);
- }
- }
-
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS PRE_API_HOOKS ${context.action}`);
- return context;
- },
- getRedirectionURL: async (context) => {
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS GET_REDIRECTION_URL ${context.action}`);
- },
- onHandleEvent: async (context) => {
- console.log(`ST_LOGS THIRDPARTYPASSWORDLESS ON_HANDLE_EVENT ${context.action}`);
- },
- useShadowDom,
- contactMethod: passwordlessContactMethodType,
- disablePasswordless: false,
- signInUpFeature: {
- disableDefaultUI,
- style: theme,
- thirdPartyProviderAndEmailOrPhoneFormStyle: `
- [data-supertokens~=providerCustom] {
- color: red;
- },
- `,
- privacyPolicyLink: "https://supertokens.io/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.io/legal/terms-and-conditions",
- providers,
- defaultCountry: passwordlessDefaultCountry,
- resendEmailOrSMSGapInSeconds: 2,
- guessInternationPhoneNumberFromInputPhoneNumber: passwordlessDisablePhoneGuess
- ? () => undefined
- : undefined,
- },
- linkClickedScreenFeature: {
- disableDefaultUI,
- style: theme,
- },
- mfaFeature: {
- disableDefaultUI,
- style: theme,
- },
- });
-}
-
-function getPasswordlessConfigs({ disableDefaultUI }) {
+function getPasswordlessConfigs({ disableDefaultUI, defaultToEmail }) {
return Passwordless.init({
override: {
functions: (implementation) => {
@@ -1075,7 +947,7 @@ function getPasswordlessConfigs({ disableDefaultUI }) {
},
},
preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `PASSWORDLESS ${context.action}`) {
+ if (localStorage.getItem(`SHOW_GENERAL_ERROR`)?.includes(context.action)) {
let jsonBody = JSON.parse(context.requestInit.body);
jsonBody = {
...jsonBody,
@@ -1093,19 +965,12 @@ function getPasswordlessConfigs({ disableDefaultUI }) {
onHandleEvent: async (context) => {
console.log(`ST_LOGS PASSWORDLESS ON_HANDLE_EVENT ${context.action}`);
},
- useShadowDom,
contactMethod: passwordlessContactMethodType,
signInUpFeature: {
defaultCountry: passwordlessDefaultCountry,
- guessInternationPhoneNumberFromInputPhoneNumber: passwordlessDisablePhoneGuess
- ? () => undefined
- : undefined,
+ defaultToEmail,
resendEmailOrSMSGapInSeconds: 2,
- disableDefaultUI,
style: theme,
-
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
},
linkClickedScreenFeature: {
disableDefaultUI,
@@ -1154,7 +1019,8 @@ function getThirdPartyConfigs({ staticProviderList, disableDefaultUI, thirdParty
}
return ThirdParty.init({
preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `THIRD_PARTY ${context.action}`) {
+ if (localStorage.getItem(`SHOW_GENERAL_ERROR`)?.includes(context.action)) {
+ // TODO
if (context.action === "GET_AUTHORISATION_URL") {
context.url += "&generalError=true";
} else {
@@ -1182,153 +1048,19 @@ function getThirdPartyConfigs({ staticProviderList, disableDefaultUI, thirdParty
return {
...implementation,
- getAuthorisationURLWithQueryParamsAndSetState(...args) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getAuthorisationURLWithQueryParamsAndSetState(...args);
- },
- getAuthorisationURLFromBackend(...args) {
- log(`GET_OAUTH_AUTHORISATION_URL`);
- return implementation.getAuthorisationURLFromBackend(...args);
- },
- getStateAndOtherInfoFromStorage(...args) {
- log(`GET_OAUTH_STATE`);
- return implementation.getStateAndOtherInfoFromStorage(...args);
- },
- setStateAndOtherInfoToStorage(...args) {
- log(`SET_OAUTH_STATE`);
- return implementation.setStateAndOtherInfoToStorage(...args);
- },
- signInAndUp(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.signInAndUp(...args);
- },
- };
- },
- },
- useShadowDom,
- signInAndUpFeature: {
- disableDefaultUI,
- style: theme,
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
- providers,
- },
-
- oAuthCallbackScreen: {
- style: theme,
- },
- });
-}
-
-function getThirdPartyEmailPasswordConfigs({
- staticProviderList,
- disableDefaultUI,
- thirdPartyRedirectURL,
- formFieldType,
-}) {
- let providers = [
- ThirdParty.Github.init(),
- ThirdParty.Google.init(),
- ThirdParty.Facebook.init(),
- ThirdParty.Apple.init(),
- {
- id: "custom",
- name: "Custom",
- },
- {
- id: "auth0",
- name: "Auth0",
- getRedirectURL: thirdPartyRedirectURL !== null ? () => thirdPartyRedirectURL : undefined,
- },
- {
- id: "mock-provider",
- name: "Mock Provider",
- },
- ];
- if (staticProviderList) {
- const ids = JSON.parse(staticProviderList);
- providers = ids.map((id) => providers.find((p) => p.id === id) || { id, name: id });
- }
- return ThirdPartyEmailPassword.init({
- preAPIHook: async (context) => {
- if (localStorage.getItem(`SHOW_GENERAL_ERROR`) === `THIRD_PARTY_EMAIL_PASSWORD ${context.action}`) {
- if (context.action === "GET_AUTHORISATION_URL" || context.action === "EMAIL_EXISTS") {
- context.url += "&generalError=true";
- } else {
- let jsonBody = JSON.parse(context.requestInit.body);
- jsonBody = {
- ...jsonBody,
- generalError: true,
- };
- context.requestInit.body = JSON.stringify(jsonBody);
- }
- }
-
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD PRE_API_HOOKS ${context.action}`);
- return context;
- },
- getRedirectionURL: async (context) => {
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD GET_REDIRECTION_URL ${context.action}`);
- if (context.action === "SUCCESS") {
- setIsNewUserToStorage("thirdpartyemailpassword", context.isNewRecipeUser);
- return context.redirectToPath || "/dashboard";
- }
- },
- onHandleEvent: async (context) => {
- console.log(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD ON_HANDLE_EVENT ${context.action}`);
- },
- override: {
- functions: (implementation) => {
- const log = logWithPrefix(`ST_LOGS THIRD_PARTY_EMAIL_PASSWORD OVERRIDE`);
-
- return {
- ...implementation,
- getAuthorisationURLWithQueryParamsAndSetState(input) {
- if (input.userContext["key"] !== undefined) {
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE RECEIVED_USER_CONTEXT`);
- }
- log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
- return implementation.getAuthorisationURLWithQueryParamsAndSetState(input);
- },
generateStateToSendToOAuthProvider(input) {
if (input.userContext["key"] !== undefined) {
log(`GENERATE_STATE RECEIVED_USER_CONTEXT`);
}
-
return implementation.generateStateToSendToOAuthProvider(input);
},
- thirdPartySignInAndUp(input) {
- if (input.userContext["key"] !== undefined) {
- log(`SIGN_IN_AND_UP RECEIVED_USER_CONTEXT`);
- }
-
- log(`SIGN_IN_AND_UP`);
- return implementation.thirdPartySignInAndUp(input);
- },
- emailPasswordSignIn(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.emailPasswordSignIn(...args);
- },
- emailPasswordSignUp(...args) {
- log(`SIGN_IN_AND_UP`);
- return implementation.emailPasswordSignUp(...args);
- },
- setStateAndOtherInfoToStorage(input) {
- if (input.userContext["key"] !== undefined) {
- log(`SET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
- }
-
- log(`SET_OAUTH_STATE`);
- return implementation.setStateAndOtherInfoToStorage(input);
- },
- getStateAndOtherInfoFromStorage(input) {
+ getAuthorisationURLWithQueryParamsAndSetState(input) {
if (input.userContext["key"] !== undefined) {
- log(`GET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
+ log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE RECEIVED_USER_CONTEXT`);
}
-
- log(`GET_OAUTH_STATE`);
- return implementation.getStateAndOtherInfoFromStorage(input);
+ log(`GET_AUTH_URL_WITH_QUERY_PARAMS_AND_SET_STATE`);
+ return implementation.getAuthorisationURLWithQueryParamsAndSetState(input);
},
getAuthorisationURLFromBackend(input) {
if (input.userContext["key"] !== undefined) {
@@ -1354,33 +1086,31 @@ function getThirdPartyEmailPasswordConfigs({
return implementation.getAuthorisationURLFromBackend(input);
},
- submitNewPassword(input) {
+ getStateAndOtherInfoFromStorage(input) {
if (input.userContext["key"] !== undefined) {
- log(`SUBMIT_NEW_PASSWORD RECEIVED_USER_CONTEXT`);
+ log(`GET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
}
- log(`SUBMIT_NEW_PASSWORD`);
- return implementation.submitNewPassword(input);
+ log(`GET_OAUTH_STATE`);
+ return implementation.getStateAndOtherInfoFromStorage(input);
},
- sendPasswordResetEmail(input) {
+
+ setStateAndOtherInfoToStorage(input) {
if (input.userContext["key"] !== undefined) {
- log(`SEND_PASSWORD_RESET_EMAIL RECEIVED_USER_CONTEXT`);
+ log(`SET_OAUTH_STATE RECEIVED_USER_CONTEXT`);
}
- log(`SEND_PASSWORD_RESET_EMAIL`);
- return implementation.sendPasswordResetEmail(input);
+ log(`SET_OAUTH_STATE`);
+ return implementation.setStateAndOtherInfoToStorage(input);
},
- getResetPasswordTokenFromURL(input) {
+ signInAndUp(input) {
if (input.userContext["key"] !== undefined) {
- log(`GET_RESET_TOKEN_FROM_URL RECEIVED_USER_CONTEXT`);
+ log(`SIGN_IN_AND_UP RECEIVED_USER_CONTEXT`);
}
-
- return implementation.getResetPasswordTokenFromURL(input);
- },
- doesEmailExist(...args) {
- log(`DOES_EMAIL_EXIST`);
- return implementation.doesEmailExist(...args);
+ log(`SIGN_IN_AND_UP`);
+ return implementation.signInAndUp(input);
},
+
getAuthStateFromURL(input) {
if (input.userContext["key"] !== undefined) {
log(`GET_AUTH_STATE_FROM_URL RECEIVED_USER_CONTEXT`);
@@ -1398,24 +1128,10 @@ function getThirdPartyEmailPasswordConfigs({
};
},
},
- useShadowDom,
- resetPasswordUsingTokenFeature: {
- disableDefaultUI,
- },
signInAndUpFeature: {
- disableDefaultUI,
- signInForm: {
- formFields: getSignInFormFields(formFieldType.signIn),
- },
- signUpForm: {
- formFields: getSignUpFormFields(formFieldType.signUp),
- privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
- termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
- },
style: theme,
providers,
},
- disableEmailPassword: false,
oAuthCallbackScreen: {
style: theme,
diff --git a/examples/for-tests/src/AppWithReactDomRouter.js b/examples/for-tests/src/AppWithReactDomRouter.js
index 7445724e4..a545bb447 100644
--- a/examples/for-tests/src/AppWithReactDomRouter.js
+++ b/examples/for-tests/src/AppWithReactDomRouter.js
@@ -1,19 +1,12 @@
import React, { useState } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
-import { SignInAndUp } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
+import { ResetPasswordUsingToken } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
-import {
- ResetPasswordUsingToken,
- SignInAndUp as TPSignInAndUp,
- ThirdPartySignInAndUpCallback,
-} from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
+import { getSuperTokensRoutesForReactRouterDom, AuthPage } from "supertokens-auth-react/ui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
-import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+import { ThirdPartyPreBuiltUI, SignInAndUpCallback } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
import { AccessDeniedScreen } from "supertokens-auth-react/recipe/session/prebuiltui";
import { MultiFactorAuthPreBuiltUI } from "supertokens-auth-react/recipe/multifactorauth/prebuiltui";
import { TOTPPreBuiltUI } from "supertokens-auth-react/recipe/totp/prebuiltui";
@@ -38,21 +31,15 @@ function AppWithReactDomRouter(props) {
const websiteBasePath = window.localStorage.getItem("websiteBasePath") || undefined;
let recipePreBuiltUIList = [TOTPPreBuiltUI];
- if (enabledRecipes.includes("emailpassword")) {
- recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
- }
- if (enabledRecipes.includes("thirdparty")) {
+ if (enabledRecipes.some((r) => r.startsWith("thirdparty"))) {
recipePreBuiltUIList.push(ThirdPartyPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipePreBuiltUIList.push(ThirdPartyEmailPasswordPreBuiltUI);
+ if (enabledRecipes.some((r) => r.endsWith("emailpassword"))) {
+ recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
}
- if (enabledRecipes.includes("passwordless")) {
+ if (enabledRecipes.some((r) => r.endsWith("passwordless"))) {
recipePreBuiltUIList.push(PasswordlessPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipePreBuiltUIList.push(ThirdPartyPasswordlessPreBuiltUI);
- }
if (emailVerificationMode !== "OFF") {
recipePreBuiltUIList.push(EmailVerificationPreBuiltUI);
}
@@ -127,7 +114,24 @@ function AppWithReactDomRouter(props) {
/>
} />
- } />
+
+ }
+ />
+
+ }
+ />
{/* User context paths */}
{isForUserContext && (
@@ -146,7 +150,7 @@ function AppWithReactDomRouter(props) {
}
/>
diff --git a/examples/for-tests/src/AppWithoutRouter.js b/examples/for-tests/src/AppWithoutRouter.js
index 7937b2898..859ee1ea3 100644
--- a/examples/for-tests/src/AppWithoutRouter.js
+++ b/examples/for-tests/src/AppWithoutRouter.js
@@ -1,8 +1,6 @@
import React, { useEffect, useState } from "react";
import { BaseComponent, Home } from "./App";
import { getRoutingComponent, canHandleRoute } from "supertokens-auth-react/ui";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
@@ -25,21 +23,15 @@ function Routing() {
const emailVerificationMode = window.localStorage.getItem("mode") || "OFF";
let recipePreBuiltUIList = [];
- if (enabledRecipes.includes("thirdparty")) {
+ if (enabledRecipes.some((r) => r.startsWith("thirdparty"))) {
recipePreBuiltUIList.push(ThirdPartyPreBuiltUI);
}
- if (enabledRecipes.includes("emailpassword")) {
+ if (enabledRecipes.some((r) => r.endsWith("emailpassword"))) {
recipePreBuiltUIList.push(EmailPasswordPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartyemailpassword")) {
- recipePreBuiltUIList.push(ThirdPartyEmailPasswordPreBuiltUI);
- }
- if (enabledRecipes.includes("passwordless")) {
+ if (enabledRecipes.some((r) => r.endsWith("passwordless"))) {
recipePreBuiltUIList.push(PasswordlessPreBuiltUI);
}
- if (enabledRecipes.includes("thirdpartypasswordless")) {
- recipePreBuiltUIList.push(ThirdPartyPasswordlessPreBuiltUI);
- }
if (emailVerificationMode !== "OFF") {
recipePreBuiltUIList.push(EmailVerificationPreBuiltUI);
diff --git a/examples/for-tests/src/testContext.js b/examples/for-tests/src/testContext.js
index 04a3e6b6e..02a14c3a1 100644
--- a/examples/for-tests/src/testContext.js
+++ b/examples/for-tests/src/testContext.js
@@ -21,6 +21,7 @@ export function getTestContext() {
signUp: localStorage.getItem("SIGNUP_SETTING_TYPE"),
},
enableMFA: localStorage.getItem("enableMFA") === "true",
+ defaultToEmail: localStorage.getItem("defaultToEmail") !== "false",
disableRedirectionAfterSuccessfulSignInUp:
localStorage.getItem("disableRedirectionAfterSuccessfulSignInUp") === "true",
};
@@ -32,7 +33,7 @@ export function getEnabledRecipes() {
let enabledRecipes = [];
- if (testContext.enableAllRecipes) {
+ if (testContext.enableAllRecipes || testContext.authRecipe === "all") {
enabledRecipes = [
"emailpassword",
"thirdparty",
diff --git a/examples/with-account-linking/backend/config.ts b/examples/with-account-linking/backend/config.ts
index 5f9017cad..65ad51394 100644
--- a/examples/with-account-linking/backend/config.ts
+++ b/examples/with-account-linking/backend/config.ts
@@ -1,4 +1,5 @@
-import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
+import ThirdParty from "supertokens-node/recipe/thirdparty";
+import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
import Passwordless from "supertokens-node/recipe/passwordless";
import AccountLinking from "supertokens-node/recipe/accountlinking";
@@ -29,7 +30,7 @@ export function getOtp() {
export const SuperTokensConfig: TypeInput = {
supertokens: {
// this is the location of the SuperTokens core.
- connectionURI: "https://try.supertokens.com",
+ connectionURI: "http://localhost:9000",
},
appInfo: {
appName: "SuperTokens Demo App",
@@ -56,33 +57,37 @@ export const SuperTokensConfig: TypeInput = {
};
},
}),
- ThirdPartyEmailPassword.init({
- providers: [
- // We have provided you with development keys which you can use for testing.
- // IMPORTANT: Please replace them with your own OAuth keys for production use.
- {
- config: {
- thirdPartyId: "google",
- clients: [
- {
- clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com",
- clientSecret: "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",
- },
- ],
+ EmailPassword.init(),
+ ThirdParty.init({
+ signInAndUpFeature: {
+ providers: [
+ // We have provided you with development keys which you can use for testing.
+ // IMPORTANT: Please replace them with your own OAuth keys for production use.
+ {
+ config: {
+ thirdPartyId: "google",
+ clients: [
+ {
+ clientId:
+ "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com",
+ clientSecret: "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",
+ },
+ ],
+ },
},
- },
- {
- config: {
- thirdPartyId: "github",
- clients: [
- {
- clientId: "467101b197249757c71f",
- clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd",
- },
- ],
+ {
+ config: {
+ thirdPartyId: "github",
+ clients: [
+ {
+ clientId: "467101b197249757c71f",
+ clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd",
+ },
+ ],
+ },
},
- },
- ],
+ ],
+ },
}),
Passwordless.init({
contactMethod: "EMAIL_OR_PHONE",
diff --git a/examples/with-account-linking/frontend/src/LinkingPage/index.tsx b/examples/with-account-linking/frontend/src/LinkingPage/index.tsx
index 3e02bde1c..1e116dd3f 100644
--- a/examples/with-account-linking/frontend/src/LinkingPage/index.tsx
+++ b/examples/with-account-linking/frontend/src/LinkingPage/index.tsx
@@ -1,8 +1,9 @@
import React, { useCallback, useEffect, useState } from "react";
import { NavLink, useLocation } from "react-router-dom";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
-import { redirectToThirdPartyLogin, emailPasswordSignUp } from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import Passwordless from "supertokens-auth-react/recipe/passwordless";
+import { redirectToThirdPartyLogin } from "supertokens-auth-react/recipe/thirdparty";
+import { signUp } from "supertokens-auth-react/recipe/emailpassword";
+import Passwordless, { clearLoginAttemptInfo } from "supertokens-auth-react/recipe/passwordless";
import { getApiDomain } from "../config";
import "./styles.css";
@@ -28,7 +29,7 @@ export const LinkingPage: React.FC = () => {
}, [setUserInfo]);
const addPassword = useCallback(async () => {
- const resp = await emailPasswordSignUp({
+ const resp = await signUp({
formFields: [
{ id: "email", value: userInfo.user.emails[0] },
{ id: "password", value: password },
@@ -41,6 +42,7 @@ export const LinkingPage: React.FC = () => {
} else {
setSuccess("Successfully added password");
setError(null);
+ loadUserInfo();
}
}, [setError, setSuccess, password]);
@@ -96,6 +98,7 @@ export const LinkingPage: React.FC = () => {
window.alert("OTP expired. Please try again");
setShowEnterOTPField(false);
} else {
+ clearLoginAttemptInfo();
setSuccess("Successfully added phone number");
setShowEnterOTPField(false);
loadUserInfo();
@@ -118,8 +121,8 @@ export const LinkingPage: React.FC = () => {
}
let passwordLoginMethods = userInfo?.user.loginMethods.filter((lm: any) => lm.recipeId === "emailpassword");
- let thirdPartyLoginMethod = userInfo?.user.loginMethods.filter((lm: any) => lm.recipeId === "thirdparty");
- let phoneLoginMethod = userInfo?.user.loginMethods.filter((lm: any) => lm.recipeId === "passwordless");
+ let thirdPartyLoginMethods = userInfo?.user.loginMethods.filter((lm: any) => lm.recipeId === "thirdparty");
+ let phoneLoginMethods = userInfo?.user.loginMethods.filter((lm: any) => lm.recipeId === "passwordless");
return (
@@ -138,7 +141,7 @@ export const LinkingPage: React.FC = () => {
Email: {lm.email}
))}
- {thirdPartyLoginMethod.map((lm: any) => (
+ {thirdPartyLoginMethods.map((lm: any) => (
{lm.recipeId}
{lm.recipeUserId}
@@ -147,7 +150,7 @@ export const LinkingPage: React.FC = () => {
))}
- {phoneLoginMethod.map((lm: any) => (
+ {phoneLoginMethods.map((lm: any) => (
{lm.recipeId}
{lm.recipeUserId}
@@ -157,18 +160,21 @@ export const LinkingPage: React.FC = () => {
))}
)}
- {passwordLoginMethods?.length === 0 && (
-
- )}
- {phoneLoginMethod?.length === 0 && (
+ {passwordLoginMethods?.length === 0 &&
+ (thirdPartyLoginMethods?.some((lm: any) => lm.email !== undefined && lm.verified) ? (
+
+ ) : (
+
Please add an email address by connecting a google account before adding a password
+ ))}
+ {phoneLoginMethods?.length === 0 && (
)}
- {thirdPartyLoginMethod?.length === 0 && (
+ {thirdPartyLoginMethods?.length === 0 && (
-
+
);
}
diff --git a/examples/with-no-session-on-sign-up-thirdpartyemailpassword/src/Home/index.js b/examples/with-no-session-on-sign-up-thirdpartyemailpassword/src/Home/index.js
index 3bf296ad4..77bdca1f2 100644
--- a/examples/with-no-session-on-sign-up-thirdpartyemailpassword/src/Home/index.js
+++ b/examples/with-no-session-on-sign-up-thirdpartyemailpassword/src/Home/index.js
@@ -3,7 +3,7 @@ import Logout from "./Logout";
import SuccessView from "./SuccessView";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
import { useNavigate } from "react-router-dom";
-import { signOut } from "supertokens-auth-react/recipe/thirdpartyemailpassword";
+import { signOut } from "supertokens-auth-react/recipe/session";
export default function Home() {
const sessionContext = useSessionContext();
diff --git a/examples/with-okta-multi-tenant-pkce-flow/src/routes/dashboard.tsx b/examples/with-okta-multi-tenant-pkce-flow/src/routes/dashboard.tsx
index 1f3188178..8135454f5 100644
--- a/examples/with-okta-multi-tenant-pkce-flow/src/routes/dashboard.tsx
+++ b/examples/with-okta-multi-tenant-pkce-flow/src/routes/dashboard.tsx
@@ -1,4 +1,4 @@
-import { signOut } from "supertokens-auth-react/recipe/thirdparty";
+import { signOut } from "supertokens-auth-react/recipe/session";
import Session from "supertokens-auth-react/recipe/session";
// This route is accessible only to logged in users
diff --git a/examples/with-one-login-many-subdomains/api-server.js b/examples/with-one-login-many-subdomains/api-server.js
index 0ec9907a7..c4519b5a7 100644
--- a/examples/with-one-login-many-subdomains/api-server.js
+++ b/examples/with-one-login-many-subdomains/api-server.js
@@ -7,8 +7,9 @@ let Session = require("supertokens-node/recipe/session");
let { verifySession } = require("supertokens-node/recipe/session/framework/express");
let { middleware, errorHandler } = require("supertokens-node/framework/express");
let Multitenancy = require("supertokens-node/recipe/multitenancy");
-let ThirdPartyEmailPassword = require("supertokens-node/recipe/thirdpartyemailpassword");
-let ThirdPartyPasswordless = require("supertokens-node/recipe/thirdpartypasswordless");
+let ThirdParty = require("supertokens-node/recipe/thirdparty");
+let EmailPassword = require("supertokens-node/recipe/emailpassword");
+let Passwordless = require("supertokens-node/recipe/passwordless");
let Dashboard = require("supertokens-node/recipe/dashboard");
let EmailVerification = require("supertokens-node/recipe/emailverification");
@@ -40,8 +41,9 @@ supertokens.init({
return [tenantId + ".example.com", "example.com"];
},
}),
- ThirdPartyEmailPassword.init(),
- ThirdPartyPasswordless.init({ contactMethod: "EMAIL", flowType: "USER_INPUT_CODE_AND_MAGIC_LINK" }),
+ ThirdParty.init(),
+ EmailPassword.init(),
+ Passwordless.init({ contactMethod: "EMAIL", flowType: "USER_INPUT_CODE_AND_MAGIC_LINK" }),
Session.init(),
Dashboard.init(),
],
diff --git a/examples/with-one-login-many-subdomains/frontend/src/App.js b/examples/with-one-login-many-subdomains/frontend/src/App.js
index 142ef59e9..cb081732a 100644
--- a/examples/with-one-login-many-subdomains/frontend/src/App.js
+++ b/examples/with-one-login-many-subdomains/frontend/src/App.js
@@ -1,8 +1,9 @@
import "./App.css";
import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
import EmailVerification from "supertokens-auth-react/recipe/emailverification";
-import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
+import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
+import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
+import Passwordless from "supertokens-auth-react/recipe/passwordless";
import Multitenancy, { AllowedDomainsClaim } from "supertokens-auth-react/recipe/multitenancy";
import Session, { SessionAuth } from "supertokens-auth-react/recipe/session";
import Home from "./Home";
@@ -38,8 +39,9 @@ SuperTokens.init({
}),
},
}),
- ThirdPartyEmailPassword.init(),
- ThirdPartyPasswordless.init({
+ ThirdParty.init(),
+ EmailPassword.init(),
+ Passwordless.init({
contactMethod: "EMAIL",
}),
Session.init({
diff --git a/examples/with-one-login-many-subdomains/frontend/src/AuthPage.jsx b/examples/with-one-login-many-subdomains/frontend/src/AuthPage.jsx
index 2a903225c..7199aa1c3 100644
--- a/examples/with-one-login-many-subdomains/frontend/src/AuthPage.jsx
+++ b/examples/with-one-login-many-subdomains/frontend/src/AuthPage.jsx
@@ -3,10 +3,10 @@ import * as reactRouterDom from "react-router-dom";
import { Routes } from "react-router-dom";
import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
-import { ThirdpartyEmailPasswordComponentsOverrideProvider } from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import { ThirdpartyPasswordlessComponentsOverrideProvider } from "supertokens-auth-react/recipe/thirdpartypasswordless";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
+import { AuthRecipeComponentsOverrideContextProvider } from "supertokens-auth-react/ui";
+import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
+import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import { getWebsiteBasePath } from "./utils";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
import { TenantSelector } from "./TenantSelector";
@@ -43,9 +43,9 @@ export const AuthPage = () => {
new URLSearchParams(location.search).has("tenantId") // or we are on a link (e.g.: email verification) that contains the tenantId
) {
return (
- {
+ AuthPageFooter_Override: ({ DefaultComponent, ...props }) => {
return (
@@ -59,35 +59,19 @@ export const AuthPage = () => {
);
},
}}>
-
{
- return (
-
-
- {
- localStorage.removeItem("tenantId");
- setHasSelectedTenantId(undefined);
- }}
- />
-
- );
- },
- }}>
-
- {getSuperTokensRoutesForReactRouterDom(
- reactRouterDom,
- [
- ThirdPartyEmailPasswordPreBuiltUI,
- ThirdPartyPasswordlessPreBuiltUI,
- EmailVerificationPreBuiltUI,
- ],
- getWebsiteBasePath()
- )}
-
-
-
+
+ {getSuperTokensRoutesForReactRouterDom(
+ reactRouterDom,
+ [
+ ThirdPartyPreBuiltUI,
+ EmailPasswordPreBuiltUI,
+ PasswordlessPreBuiltUI,
+ EmailVerificationPreBuiltUI,
+ ],
+ getWebsiteBasePath()
+ )}
+
+
);
} else {
return
;
diff --git a/examples/with-one-login-per-subdomain/api-server.js b/examples/with-one-login-per-subdomain/api-server.js
index 4707387fb..0967fb90e 100644
--- a/examples/with-one-login-per-subdomain/api-server.js
+++ b/examples/with-one-login-per-subdomain/api-server.js
@@ -4,8 +4,9 @@ let supertokens = require("supertokens-node");
let Session = require("supertokens-node/recipe/session");
let { verifySession } = require("supertokens-node/recipe/session/framework/express");
let { middleware, errorHandler } = require("supertokens-node/framework/express");
-let ThirdPartyEmailPassword = require("supertokens-node/recipe/thirdpartyemailpassword");
-let ThirdPartyPasswordless = require("supertokens-node/recipe/thirdpartypasswordless");
+let ThirdParty = require("supertokens-node/recipe/thirdparty");
+let EmailPassword = require("supertokens-node/recipe/emailpassword");
+let Passwordless = require("supertokens-node/recipe/passwordless");
let Dashboard = require("supertokens-node/recipe/dashboard");
let Multitenancy = require("supertokens-node/recipe/multitenancy");
let EmailVerification = require("supertokens-node/recipe/emailverification");
@@ -50,7 +51,7 @@ supertokens.init({
return [tenantId + ".example.com"];
},
}),
- ThirdPartyPasswordless.init({
+ Passwordless.init({
contactMethod: "EMAIL",
flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",
emailDelivery: {
@@ -66,7 +67,7 @@ supertokens.init({
}),
},
}),
- ThirdPartyEmailPassword.init({
+ EmailPassword.init({
emailDelivery: {
override: (oI) => ({
...oI,
@@ -80,6 +81,7 @@ supertokens.init({
}),
},
}),
+ ThirdParty.init(),
Session.init(),
Dashboard.init(),
],
diff --git a/examples/with-one-login-per-subdomain/src/App.js b/examples/with-one-login-per-subdomain/src/App.js
index 99fe54f15..5c60d20c4 100644
--- a/examples/with-one-login-per-subdomain/src/App.js
+++ b/examples/with-one-login-per-subdomain/src/App.js
@@ -4,10 +4,12 @@ import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui
import EmailVerification from "supertokens-auth-react/recipe/emailverification";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
import Multitenancy, { AllowedDomainsClaim } from "supertokens-auth-react/recipe/multitenancy";
-import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
-import ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
-import { ThirdPartyPasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartypasswordless/prebuiltui";
+import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
+import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
+import Passwordless from "supertokens-auth-react/recipe/passwordless";
+import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
+import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import Session, { SessionAuth, getClaimValue } from "supertokens-auth-react/recipe/session";
import { Routes, BrowserRouter as Router, Route } from "react-router-dom";
import Home from "./Home";
@@ -33,8 +35,9 @@ SuperTokens.init({
}),
},
}),
- ThirdPartyEmailPassword.init(),
- ThirdPartyPasswordless.init({
+ ThirdParty.init(),
+ EmailPassword.init(),
+ Passwordless.init({
contactMethod: "EMAIL",
}),
Session.init({
@@ -68,8 +71,9 @@ function App() {
{getSuperTokensRoutesForReactRouterDom(require("react-router-dom"), [
- ThirdPartyEmailPasswordPreBuiltUI,
- ThirdPartyPasswordlessPreBuiltUI,
+ ThirdPartyPreBuiltUI,
+ EmailPasswordPreBuiltUI,
+ PasswordlessPreBuiltUI,
EmailVerificationPreBuiltUI,
])}
({
...oI,
getGlobalClaimValidators: ({ claimValidatorsAddedByOtherRecipes }) => {
- return [...claimValidatorsAddedByOtherRecipes, PhoneVerifiedClaim.validators.isTrue()];
+ return [
+ ...claimValidatorsAddedByOtherRecipes.filter(
+ (v) => v.id !== MultiFactorAuth.MultiFactorAuthClaim.id
+ ),
+ PhoneVerifiedClaim.validators.isTrue(),
+ ];
},
}),
},
diff --git a/examples/with-phone-password/src/Home/index.tsx b/examples/with-phone-password/src/Home/index.tsx
index d7bb0ecc3..4aac8fd3b 100644
--- a/examples/with-phone-password/src/Home/index.tsx
+++ b/examples/with-phone-password/src/Home/index.tsx
@@ -3,7 +3,7 @@ import Logout from "./Logout";
import SuccessView from "./SuccessView";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
import { useNavigate } from "react-router-dom";
-import { signOut } from "supertokens-auth-react/recipe/emailpassword";
+import { signOut } from "supertokens-auth-react/recipe/session";
import { PhoneVerifiedClaim } from "../phoneVerifiedClaim";
export default function Home() {
diff --git a/examples/with-phone-password/src/PhoneVerification/index.tsx b/examples/with-phone-password/src/PhoneVerification/index.tsx
index fbdb220fa..00d045561 100644
--- a/examples/with-phone-password/src/PhoneVerification/index.tsx
+++ b/examples/with-phone-password/src/PhoneVerification/index.tsx
@@ -1,11 +1,14 @@
import { useState, useEffect } from "react";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
-import { SignInUp, SignInUpTheme } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import * as reactRouterDom from "react-router-dom";
+import { AuthPage, AuthPageTheme, AuthPageThemeProps } from "supertokens-auth-react/ui";
+import Passwordless from "supertokens-auth-react/recipe/passwordless";
+import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
-const CustomSignInUpTheme: typeof SignInUpTheme = (props) => {
+const CustomSignInUpTheme = (props: AuthPageThemeProps) => {
let [showDefaultUI, setShowDefaultUI] = useState(false);
const session = useSessionContext();
+
useEffect(() => {
let aborting = false;
async function effect() {
@@ -13,20 +16,37 @@ const CustomSignInUpTheme: typeof SignInUpTheme = (props) => {
return;
}
- let phoneNumber = session.accessTokenPayload.phoneNumber;
+ const phoneNumber = session.accessTokenPayload.phoneNumber;
+
// If don't have a phone number we show the default UI (which should be the phone form)
if (phoneNumber === undefined) {
setShowDefaultUI(true);
} else {
- // we start the OTP flow if it's not started already
- if (props.featureState.loginAttemptInfo === undefined) {
- await props.recipeImplementation.createCode({ phoneNumber, userContext: props.userContext });
- }
+ const attemptInfo = await Passwordless.getLoginAttemptInfo();
if (aborting) {
return;
}
- // if we have an OTP flow (or we just started one) we show the default UI which should be the OTP input
+ if (attemptInfo === undefined) {
+ const additionalAttemptInfo = {
+ lastResend: Date.now(),
+ contactMethod: "PHONE",
+ contactInfo: phoneNumber,
+ redirectToPath: "/dashboard",
+ };
+
+ const res = await Passwordless.createCode({
+ phoneNumber,
+ userContext: { additionalAttemptInfo },
+ });
+
+ if (res.status === "OK") {
+ props.rebuildAuthPage();
+ } else {
+ props.onError(res.reason ?? res.status);
+ }
+ }
+ // if we have an OTP flow (or we just tried to start one) we show the default UI which should be the OTP input
setShowDefaultUI(true);
}
}
@@ -34,10 +54,10 @@ const CustomSignInUpTheme: typeof SignInUpTheme = (props) => {
return () => {
aborting = true;
};
- }, []);
+ }, [session.loading]);
if (showDefaultUI) {
- return ;
+ return ;
}
return <>>;
};
@@ -46,11 +66,15 @@ export default function PhoneVerification() {
const navigate = reactRouterDom.useNavigate();
return (
-
+
{
// @ts-ignore We ignore the error about missing props, since they'll be set by the feature component
}
-
+
);
}
diff --git a/examples/with-sign-in-up-split-emailpassword/src/App.js b/examples/with-sign-in-up-split-emailpassword/src/App.js
index bd487ddd7..012391ebe 100644
--- a/examples/with-sign-in-up-split-emailpassword/src/App.js
+++ b/examples/with-sign-in-up-split-emailpassword/src/App.js
@@ -1,8 +1,12 @@
import { useState, useEffect } from "react";
import "./App.css";
import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
-import EmailPassword, { EmailPasswordComponentsOverrideProvider } from "supertokens-auth-react/recipe/emailpassword";
+import {
+ getSuperTokensRoutesForReactRouterDom,
+ AuthPage,
+ AuthRecipeComponentsOverrideContextProvider,
+} from "supertokens-auth-react/ui";
+import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import Session, { SessionAuth } from "supertokens-auth-react/recipe/session";
import Home from "./Home";
@@ -28,41 +32,23 @@ SuperTokens.init({
apiDomain: getApiDomain(), // TODO: Change to your app's API domain
websiteDomain: getWebsiteDomain(), // TODO: Change to your app's website domain
},
- recipeList: [
- EmailPassword.init({
- signInAndUpFeature: {
- disableDefaultImplementation: true, // this disables showing the default sign in + sign up component
-
- signInForm: {
- // hides the element that shows switch to the sign up form and the divider in the sign in UI
- style: `
- [data-supertokens~=headerSubtitle] {
- display: none;
- }
- [data-supertokens~=divider] {
- display: none;
- }
- `,
- },
- signUpForm: {
- // hides the element that shows switch to the sign in form
- style: `
- [data-supertokens~=headerSubtitle] {
- display: none;
- }
- `,
- },
- },
- getRedirectionURL: function (context) {
- if (context.action === "SIGN_IN_AND_UP") {
- // if the user is not logged in, we want to send
- // them to the sign in page.
- return "/signin";
- }
- },
- }),
- Session.init(),
- ],
+ disableAuthRoute: true,
+ style: `
+ [data-supertokens~=headerSubtitle] {
+ display: none;
+ }
+ [data-supertokens~=divider] {
+ display: none;
+ }
+ `,
+ getRedirectionURL: function (context) {
+ if (context.action === "TO_AUTH") {
+ // if the user is not logged in, we want to send
+ // them to the sign in page.
+ return "/signin";
+ }
+ },
+ recipeList: [EmailPassword.init(), Session.init()],
});
function App() {
@@ -70,59 +56,23 @@ function App() {
return (
- {
- /* if the user visits the /signin route, we want to show the
- default implementation. If thy visit the /signup
- route (which also renders the component),
- we want to show the sign up UI, so we set the query parm to ?show=signup
- which shows the sign up UI.
- */
- const [showUI, setShowUI] = useState(false);
- useEffect(() => {
- if (window.location.pathname === "/signin") {
- setShowUI(true);
- } else if (window.location.pathname === "/signup") {
- window.location.href = "/signup?show=signup";
- } else {
- setShowUI(true);
- }
- }, []);
- if (showUI) {
- return ;
- } else {
- return null;
- }
- },
- EmailPasswordSignUp_Override: ({ DefaultComponent, ...props }) => {
- /* if the user visits the /signup route, we want to show the
- default implementation. If thy visit the /signin?show=signup
- route, we want to show the sign in UI, so we redirect them to /signin
- which shows the sign in UI.
- */
- const [showUI, setShowUI] = useState(false);
- useEffect(() => {
- if (window.location.pathname === "/signup") {
- setShowUI(true);
- } else if (window.location.pathname === "/signin") {
- window.location.href = "/signin";
- } else {
- setShowUI(true);
- }
- }, []);
- if (showUI) {
- return ;
- } else {
- return null;
- }
- },
- EmailPasswordSignInHeader_Override: ({ DefaultComponent, ...props }) => {
- return (
+ AuthPageHeader_Override: ({ DefaultComponent, ...props }) => {
+ return props.isSignUp ? (
+
+
+ Click{" "}
+
+ here
+ {" "}
+ to sign in
+
+ ) : (
Click{" "}
-
+
here
{" "}
to sign up
@@ -143,8 +93,8 @@ function App() {
path="/"
element={
/* This protects the "/" route so that it shows
-
only if the user is logged in.
- Else it redirects the user to "/auth" */
+
only if the user is logged in.
+ Else it redirects the user to "/auth" */
{
updateShowSessionExpiredPopup(true);
@@ -155,20 +105,26 @@ function App() {
}
/>
{/* we want to render the sign in component in /signin.
- We will override the component to only show the sign in
- UI on this route. See the init function call above for how to do this*/}
- } />
+ We will override the component to only show the sign in
+ UI on this route. See the init function call above for how to do this*/}
+ }
+ />
{/* we want to render the sign up component in /signup.
- We will override the component to only show the sign up
- UI on this route. See the init function call above for how to do this*/}
- } />
+ We will override the component to only show the sign up
+ UI on this route. See the init function call above for how to do this*/}
+ }
+ />
-
+
);
}
diff --git a/examples/with-sign-in-up-split-emailpassword/src/Home/index.js b/examples/with-sign-in-up-split-emailpassword/src/Home/index.js
index 9fe0d1733..3b232a4fd 100644
--- a/examples/with-sign-in-up-split-emailpassword/src/Home/index.js
+++ b/examples/with-sign-in-up-split-emailpassword/src/Home/index.js
@@ -3,7 +3,7 @@ import Logout from "./Logout";
import SuccessView from "./SuccessView";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
import { useNavigate } from "react-router-dom";
-import { signOut } from "supertokens-auth-react/recipe/emailpassword";
+import { signOut } from "supertokens-auth-react/recipe/session";
export default function Home() {
const session = useSessionContext();
diff --git a/examples/with-supabase/config/backendConfig.ts b/examples/with-supabase/config/backendConfig.ts
index a8f4dd4f6..cf617714a 100644
--- a/examples/with-supabase/config/backendConfig.ts
+++ b/examples/with-supabase/config/backendConfig.ts
@@ -1,4 +1,5 @@
-import ThirdPartyEmailPasswordNode from "supertokens-node/recipe/thirdpartyemailpassword";
+import ThirdPartyNode from "supertokens-node/recipe/thirdparty";
+import EmailPasswordNode from "supertokens-node/recipe/emailpassword";
import SessionNode from "supertokens-node/recipe/session";
import EmailVerificationNode from "supertokens-node/recipe/emailverification";
import { appInfo } from "./appInfo";
@@ -18,60 +19,96 @@ export let backendConfig = (): TypeInput => {
EmailVerificationNode.init({
mode: "REQUIRED",
}),
- ThirdPartyEmailPasswordNode.init({
- providers: [
- // We have provided you with development keys which you can use for testing.
- // IMPORTANT: Please replace them with your own OAuth keys for production use.
- {
- config: {
- thirdPartyId: "google",
- clients: [
- {
- clientId: process.env.GOOGLE_CLIENT_ID,
- clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- },
- ],
+ EmailPasswordNode.init({
+ override: {
+ apis: (originalImplementation) => ({
+ ...originalImplementation,
+
+ signUpPOST: async function (input) {
+ if (originalImplementation.signUpPOST === undefined) {
+ throw Error("Should never come here");
+ }
+
+ let response = await originalImplementation.signUpPOST(input);
+
+ if (response.status === "OK") {
+ // retrieve the accessTokenPayload from the user's session
+ const accessTokenPayload = response.session.getAccessTokenPayload();
+
+ // create a supabase client with the supabase_token from the accessTokenPayload
+ const supabase = getSupabase(accessTokenPayload.supabase_token);
+
+ // store the user's email mapped to their userId in Supabase
+ const { error } = await supabase
+ .from("users")
+ .insert({ email: response.user.emails[0], user_id: response.user.id });
+
+ if (error !== null) {
+ throw error;
+ }
+ }
+
+ return response;
},
- },
- {
- config: {
- thirdPartyId: "github",
- clients: [
- {
- clientId: process.env.GITHUB_CLIENT_ID,
- clientSecret: process.env.GITHUB_CLIENT_SECRET,
- },
- ],
+ }),
+ },
+ }),
+ ThirdPartyNode.init({
+ signInAndUpFeature: {
+ providers: [
+ // We have provided you with development keys which you can use for testing.
+ // IMPORTANT: Please replace them with your own OAuth keys for production use.
+ {
+ config: {
+ thirdPartyId: "google",
+ clients: [
+ {
+ clientId: process.env.GOOGLE_CLIENT_ID,
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
+ },
+ ],
+ },
},
- },
- {
- config: {
- thirdPartyId: "apple",
- clients: [
- {
- clientId: process.env.APPLE_CLIENT_ID,
- additionalConfig: {
- keyId: process.env.APPLE_KEY_ID,
- privateKey: process.env.APPLE_PRIVATE_KEY.replace(/\\n/g, "\n"),
- teamId: process.env.APPLE_TEAM_ID,
+ {
+ config: {
+ thirdPartyId: "github",
+ clients: [
+ {
+ clientId: process.env.GITHUB_CLIENT_ID,
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
+ },
+ ],
+ },
+ },
+ {
+ config: {
+ thirdPartyId: "apple",
+ clients: [
+ {
+ clientId: process.env.APPLE_CLIENT_ID,
+ additionalConfig: {
+ keyId: process.env.APPLE_KEY_ID,
+ privateKey: process.env.APPLE_PRIVATE_KEY.replace(/\\n/g, "\n"),
+ teamId: process.env.APPLE_TEAM_ID,
+ },
},
- },
- ],
+ ],
+ },
},
- },
- ],
+ ],
+ },
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
- // the thirdPartySignInUpPost function handles sign up/in via Social login
- thirdPartySignInUpPOST: async function (input) {
- if (originalImplementation.thirdPartySignInUpPOST === undefined) {
+ // the signInUpPost function handles sign up/in via Social login
+ signInUpPOST: async function (input) {
+ if (originalImplementation.signInUpPOST === undefined) {
throw Error("Should never come here");
}
// call the sign up/in api for social login
- let response = await originalImplementation.thirdPartySignInUpPOST(input);
+ let response = await originalImplementation.signInUpPOST(input);
// check that there is no issue with sign up and that a new user is created
if (response.status === "OK" && response.createdNewRecipeUser) {
@@ -84,35 +121,7 @@ export let backendConfig = (): TypeInput => {
// store the user's email mapped to their userId in Supabase
const { error } = await supabase
.from("users")
- .insert({ email: response.user.email, user_id: response.user.id });
-
- if (error !== null) {
- throw error;
- }
- }
-
- return response;
- },
-
- // the emailPasswordSignUpPOST function handles sign up via Email-Password
- emailPasswordSignUpPOST: async function (input) {
- if (originalImplementation.emailPasswordSignUpPOST === undefined) {
- throw Error("Should never come here");
- }
-
- let response = await originalImplementation.emailPasswordSignUpPOST(input);
-
- if (response.status === "OK") {
- // retrieve the accessTokenPayload from the user's session
- const accessTokenPayload = response.session.getAccessTokenPayload();
-
- // create a supabase client with the supabase_token from the accessTokenPayload
- const supabase = getSupabase(accessTokenPayload.supabase_token);
-
- // store the user's email mapped to their userId in Supabase
- const { error } = await supabase
- .from("users")
- .insert({ email: response.user.email, user_id: response.user.id });
+ .insert({ email: response.user.emails[0], user_id: response.user.id });
if (error !== null) {
throw error;
diff --git a/examples/with-supabase/config/frontendConfig.ts b/examples/with-supabase/config/frontendConfig.ts
index 69e6f28e4..4c63549be 100644
--- a/examples/with-supabase/config/frontendConfig.ts
+++ b/examples/with-supabase/config/frontendConfig.ts
@@ -1,4 +1,5 @@
-import ThirdPartyEmailPasswordReact from "supertokens-auth-react/recipe/thirdpartyemailpassword";
+import ThirdPartyReact from "supertokens-auth-react/recipe/thirdparty";
+import EmailPasswordReact from "supertokens-auth-react/recipe/emailpassword";
import SessionReact from "supertokens-auth-react/recipe/session";
import EmailVerificationReact from "supertokens-auth-react/recipe/emailverification";
import { appInfo } from "./appInfo";
@@ -10,15 +11,16 @@ export let frontendConfig = () => {
EmailVerificationReact.init({
mode: "REQUIRED",
}),
- ThirdPartyEmailPasswordReact.init({
+ ThirdPartyReact.init({
signInAndUpFeature: {
providers: [
- ThirdPartyEmailPasswordReact.Google.init(),
- ThirdPartyEmailPasswordReact.Github.init(),
- ThirdPartyEmailPasswordReact.Apple.init(),
+ ThirdPartyReact.Google.init(),
+ ThirdPartyReact.Github.init(),
+ ThirdPartyReact.Apple.init(),
],
},
}),
+ EmailPasswordReact.init(),
SessionReact.init(),
],
};
diff --git a/examples/with-supabase/pages/auth/[[...path]].tsx b/examples/with-supabase/pages/auth/[[...path]].tsx
index 82392caec..adb50a706 100644
--- a/examples/with-supabase/pages/auth/[[...path]].tsx
+++ b/examples/with-supabase/pages/auth/[[...path]].tsx
@@ -5,18 +5,19 @@ import dynamic from "next/dynamic";
import SuperTokens from "supertokens-auth-react";
import { canHandleRoute, getRoutingComponent } from "supertokens-auth-react/ui";
import { EmailVerificationPreBuiltUI } from "supertokens-auth-react/recipe/emailverification/prebuiltui";
-import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
+import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
const SuperTokensComponentNoSSR = dynamic<{}>(
new Promise((res) =>
- res(() => getRoutingComponent([EmailVerificationPreBuiltUI, ThirdPartyEmailPasswordPreBuiltUI]))
+ res(() => getRoutingComponent([EmailVerificationPreBuiltUI, ThirdPartyPreBuiltUI, EmailPasswordPreBuiltUI]))
),
{ ssr: false }
);
export default function Auth() {
useEffect(() => {
- if (canHandleRoute([EmailVerificationPreBuiltUI, ThirdPartyEmailPasswordPreBuiltUI]) === false) {
+ if (canHandleRoute([EmailVerificationPreBuiltUI, ThirdPartyPreBuiltUI, EmailPasswordPreBuiltUI]) === false) {
SuperTokens.redirectToAuth();
}
}, []);
diff --git a/examples/with-supabase/pages/index.tsx b/examples/with-supabase/pages/index.tsx
index 43f86ceaa..55447005a 100644
--- a/examples/with-supabase/pages/index.tsx
+++ b/examples/with-supabase/pages/index.tsx
@@ -2,9 +2,8 @@ import React, { useState, useEffect } from "react";
import Head from "next/head";
import styles from "../styles/Home.module.css";
import { redirectToAuth } from "supertokens-auth-react";
-import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
import dynamic from "next/dynamic";
-import { useSessionContext, SessionAuth } from "supertokens-auth-react/recipe/session";
+import { useSessionContext, SessionAuth, signOut } from "supertokens-auth-react/recipe/session";
import { getSupabase } from "../utils/supabase";
export default function Home() {
@@ -46,7 +45,7 @@ function ProtectedPage() {
}, [sessionContext]);
async function logoutClicked() {
- await ThirdPartyEmailPassword.signOut();
+ await signOut();
redirectToAuth();
}
diff --git a/examples/with-svelte-react-thirdpartyemailpassword/server.js b/examples/with-svelte-react-thirdpartyemailpassword/server.js
index 0b6e2964b..457ed0bf5 100644
--- a/examples/with-svelte-react-thirdpartyemailpassword/server.js
+++ b/examples/with-svelte-react-thirdpartyemailpassword/server.js
@@ -2,7 +2,8 @@ const express = require("express");
const supertokens = require("supertokens-node");
const Session = require("supertokens-node/recipe/session");
const EmailVerification = require("supertokens-node/recipe/emailverification");
-const ThirdPartyEmailPassword = require("supertokens-node/recipe/thirdpartyemailpassword");
+const ThirdParty = require("supertokens-node/recipe/thirdparty");
+const EmailPassword = require("supertokens-node/recipe/emailpassword");
const { middleware, errorHandler } = require("supertokens-node/framework/express");
const cors = require("cors");
const Dashboard = require("supertokens-node/recipe/dashboard");
@@ -26,33 +27,37 @@ supertokens.init({
websiteDomain, // TODO: Change to your app's website domain
},
recipeList: [
- ThirdPartyEmailPassword.init({
- providers: [
- // We have provided you with development keys which you can use for testsing.
- // IMPORTANT: Please replace them with your own OAuth keys for production use.
- {
- config: {
- thirdPartyId: "google",
- clients: [
- {
- clientId: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com",
- clientSecret: "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",
- },
- ],
+ EmailPassword.init(),
+ ThirdParty.init({
+ signInAndUpFeature: {
+ providers: [
+ // We have provided you with development keys which you can use for testsing.
+ // IMPORTANT: Please replace them with your own OAuth keys for production use.
+ {
+ config: {
+ thirdPartyId: "google",
+ clients: [
+ {
+ clientId:
+ "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com",
+ clientSecret: "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",
+ },
+ ],
+ },
},
- },
- {
- config: {
- thirdPartyId: "github",
- clients: [
- {
- clientId: "467101b197249757c71f",
- clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd",
- },
- ],
+ {
+ config: {
+ thirdPartyId: "github",
+ clients: [
+ {
+ clientId: "467101b197249757c71f",
+ clientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd",
+ },
+ ],
+ },
},
- },
- ],
+ ],
+ },
}),
Session.init(), // initializes session features
Dashboard.init(),
diff --git a/examples/with-svelte-react-thirdpartyemailpassword/src/App.svelte b/examples/with-svelte-react-thirdpartyemailpassword/src/App.svelte
index 97f0d1e53..e568cb68f 100644
--- a/examples/with-svelte-react-thirdpartyemailpassword/src/App.svelte
+++ b/examples/with-svelte-react-thirdpartyemailpassword/src/App.svelte
@@ -4,12 +4,14 @@
import ReactDOM from "react-dom";
import SuperTokens from "supertokens-auth-react";
import { getRoutingComponent, canHandleRoute } from "supertokens-auth-react/ui";
- import ThirdPartyEmailPassword, {
+ import ThirdParty, {
Github,
Google,
signOut,
- } from "supertokens-auth-react/recipe/thirdpartyemailpassword";
- import { ThirdPartyEmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/thirdpartyemailpassword/prebuiltui";
+ } from "supertokens-auth-react/recipe/thirdparty";
+ import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
+ import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
+ import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import Session from "supertokens-auth-react/recipe/session";
import { Router, Route } from "svelte-navigator";
import { onMount } from "svelte";
@@ -22,7 +24,8 @@
websiteDomain: "http://localhost:8080", // TODO: Change to your app's website domain
},
recipeList: [
- ThirdPartyEmailPassword.init({
+ EmailPassword.init(),
+ ThirdParty.init({
signInAndUpFeature: {
providers: [Github.init(), Google.init()],
},
@@ -33,8 +36,8 @@
class SuperTokensComponent extends React.Component {
render() {
- if (canHandleRoute([ThirdPartyEmailPasswordPreBuiltUI])) {
- return getRoutingComponent([ThirdPartyEmailPasswordPreBuiltUI]);
+ if (canHandleRoute([ThirdPartyPreBuiltUI, EmailPasswordPreBuiltUI])) {
+ return getRoutingComponent([ThirdPartyPreBuiltUI, EmailPasswordPreBuiltUI]);
}
return "Route not found";
}
diff --git a/examples/with-svelte-react-thirdpartyemailpassword/src/Navbar.svelte b/examples/with-svelte-react-thirdpartyemailpassword/src/Navbar.svelte
index 3679733ca..25ca5cba9 100644
--- a/examples/with-svelte-react-thirdpartyemailpassword/src/Navbar.svelte
+++ b/examples/with-svelte-react-thirdpartyemailpassword/src/Navbar.svelte
@@ -1,7 +1,7 @@