Skip to content

Commit 4299e90

Browse files
porcellussattvikcanku255
authored
feat(mfa)!: add mfa and totp recipes (#780)
* chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: update pwless to support otp based mfa * feat: initial impl of totp mfa * feat: export totp bundle * feat: finish TOTP + test setup WIP * feat: finish TOTP + test setup WIP * feat: add back button to factor chooser and filter the options * feat: update how back buttons are styled * test: update how back button is selected in tests * feat: finishing totp initial impl * test: initial test for MFA * feat: self-review fixes & updates * feat: self-review fixes&cleanup * feat: self-review fixes&cleanup * test: add firstFactors tests * tests: complete initial test-set of MFA * fix: firstFactors + test helpers * fix: small test based fixes * feat: finishing touches * test: update first factor tests to match new behaviour w/ extra checks * feat: clean up first factor handling * feat: add retry info to verifyCode/Device * refactor: rename passwordlessFirstFactors since it's not only first factors * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * test: clean up * chore: increase size limits * test: add reset method to mfa recipe * feat: make sure firstFactor conflicts hit user error boundaries * feat: update design and fix font-weight issues * chore: update web-js dep * feat: update design * feat: update design * refactor: self-review fixes * refactor: self-review fixes * chore: update changelog * fix: revert unnecessary changes * feat: use redirect info if available on mfa success * refactor: use redirectToFactor instead of re-implementing * fix: add missing param into redirectToFactorChooser call * chore: update changelog * test: update tests for MFA * test: skip mock mfa tests until removal * fix: override and routing fixes * test: update e2e test to work with an actual BE * fix: making sure async errors hit error boundaries + smaller test fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * fix: auth server test * feat: add the mfa recipe and basic support (#758) * chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: add back button to factor chooser and filter the options * test: update how back button is selected in tests * feat: self-review fixes & updates * fix: firstFactors + test helpers * feat: clean up first factor handling * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * chore: increase size limits * test: add reset method to mfa recipe * feat: update design and fix font-weight issues * chore: update web-js dep * refactor: use redirectToFactor instead of re-implementing * fix: override and routing fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * chore: add missing notes to changelog * test: ensure tests pass on older versions * test: add missing case * fix: exposing mfa in tppwless + cleanup/refactor * test: split up mfa tests into multiple files * feat: update passwordless to support OTP based MFA (#759) * chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: update pwless to support otp based mfa * feat: add back button to factor chooser and filter the options * feat: update how back buttons are styled * test: update how back button is selected in tests * feat: self-review fixes & updates * feat: self-review fixes&cleanup * fix: firstFactors + test helpers * fix: small test based fixes * feat: clean up first factor handling * refactor: rename passwordlessFirstFactors since it's not only first factors * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * chore: increase size limits * test: add reset method to mfa recipe * feat: make sure firstFactor conflicts hit user error boundaries * feat: update design and fix font-weight issues * chore: update web-js dep * feat: update design * refactor: self-review fixes * refactor: self-review fixes * chore: update changelog * feat: use redirect info if available on mfa success * refactor: use redirectToFactor instead of re-implementing * fix: add missing param into redirectToFactorChooser call * fix: override and routing fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * fix: exposing mfa in tppwless + cleanup/refactor * feat: totp recipe for MFA (#763) * chore: update to mfa branch of web-js * feat: mfa recipe setup * feat: add support for firstFactor * fix: fix chooseComponentBasedOnFirstFactors to properly get the max count * feat: navigation based on claim validation failures * feat: implement factor chooser screen * feat: factor chooser fixes and updates * feat: update pwless to support otp based mfa * feat: initial impl of totp mfa * feat: export totp bundle * feat: finish TOTP + test setup WIP * feat: finish TOTP + test setup WIP * feat: add back button to factor chooser and filter the options * feat: update how back buttons are styled * test: update how back button is selected in tests * feat: finishing totp initial impl * test: initial test for MFA * feat: self-review fixes & updates * feat: self-review fixes&cleanup * feat: self-review fixes&cleanup * test: add firstFactors tests * tests: complete initial test-set of MFA * fix: firstFactors + test helpers * fix: small test based fixes * feat: finishing touches * test: update first factor tests to match new behaviour w/ extra checks * feat: clean up first factor handling * feat: add retry info to verifyCode/Device * refactor: rename passwordlessFirstFactors since it's not only first factors * feat: self-review fixes * chore: add mfa ui to size limits * refactor: remove updates that will be added in other PRs + simplifications * test: clean up * chore: increase size limits * test: add reset method to mfa recipe * feat: make sure firstFactor conflicts hit user error boundaries * feat: update design and fix font-weight issues * chore: update web-js dep * feat: update design * feat: update design * refactor: self-review fixes * refactor: self-review fixes * chore: update changelog * fix: revert unnecessary changes * feat: use redirect info if available on mfa success * refactor: use redirectToFactor instead of re-implementing * fix: add missing param into redirectToFactorChooser call * chore: update changelog * test: update tests for MFA * test: skip mock mfa tests until removal * fix: override and routing fixes * feat: allow showing matching sub-recipe components if not on websitebasepath * fix: exposing mfa in tppwless + cleanup/refactor * refactor: cleanup&renames * refactor: consistency fixes * docs: add storybook (#774) * ci: add storybook * ci: update stories after merge * ci: update&add stories * refactor: small code-changes to help storybooks build/work right * docs: fix usesDynamicLoginMethods control in storybooks * docs: reset uis properly when re-rendering auth page stories * docs: provide better error reporting in auth page stories * docs: add separate stories for different button configs in totp * test: add stories for auth recipe screens * fix: type fixes and design updates + extended storybook * test: make tests backward compatible * fix: fix recipe name in error message * test: fix enableMFA * test: update tests to work w/ new BE behaviour * fix: small self-review fixes * fix: self-review fixes * fix: add missing type to prebuiltuis * fix: fix console errors * fix: small design and usability upgrades * docs: update with-phone-password to use MFA * docs: remove 2fa examples and update the README to point to new mfa examples * fix: add missing arg to redirectToFactorChooser * fix: add missing param * fix: add missing param * docs: add mfa example with recovery codes * docs: save netlify-cli version in netlify example * fix: mfa otp loading screen override * docs: add mfa-with-phone-chooser example * fix: remove duplicate type + rebuild * refactor: removed unused state and related action/types * refactor: simplify impl * refactor: make usage of FeatureBaseProps consistent * refactor: consistency updates * chore: remove unused test code * feat(mfa): finish todo list (#782) * feat: updated when we ask for contact info based slack discussion * fix: make sure change email address shows up at the right time * docs: update emailverification-with-otp example to use MFA * test: add test cases that check if redirectToPath is respected in mfa * fix: small fixes and updates for the updated node impl * test: update tests to match new behaviour/utils * docs: reset dependencies to latest * feat(mfa!): w1 discussions (#787) * feat: update to match new BE interface * feat: simplifications and consistency fixes * test: remove test changes & rebuild * fix: manual-test fixes * chore: update to match new st-web types * feat: add totp events + update types * chore: add clarification comment * refactor: clean up todos * feat(mfa): implement w2 discussion (#788) * feat: updates based on w2 discussions * chore: update changelog * test: test app consistency fixes * chore: remove duplicate deps * chore: add storybook to npmignore * feat: implementing review comments * fix: update how we decide when to show the back button * fix: remove !important from css styles (#791) * feat: fix types and add newSessionCreated to redirect context * feat: implementing review feedback + discussion * feat: update getLoginMethod types and related logic * fix: test fixes * feat: expose FactorIds through the mfa recipe * feat: add rid to success events * docs: update examples to newest API * feat: redirect to the email verification page in case MFA requires it * docs: update account-linking example * docs: update recovery code example to separate the create recovery code page * docs: update example readmes and minor cleanup * feat\!: rename isNewPrimaryUser to createdNewUser * chore: update changelog and PR template checklist with review comments * docs: add error codes to translation files * chore: move and update version requirements in changelog * chore: add factor id list update to pr checklist * docs: complete error code list in translation files * feat: add consistent fallbacks to every onFetchError * docs: removed example we will be splitting up * docs: implement review comments in examples and extend the changelog * docs: replace custom API with session based linking * docs: update examples to new interface * feat: update totp logo * feat: update after web-js types changed * fix: minor test fixes and updates * chore: update size limits * docs: update examples * docs: rename updated phone-pw example to phone-pw-mfa and reset the phone-pw to master --------- Co-authored-by: Sattvik Chakravarthy <[email protected]> Co-authored-by: Ankit Tiwari <[email protected]>
1 parent 4b2a650 commit 4299e90

File tree

501 files changed

+46887
-29914
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

501 files changed

+46887
-29914
lines changed

.babelrc

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
{
2-
"presets": [["@babel/preset-env", {}, "@babel/preset-react"]],
3-
"plugins": [
2+
"presets": [
3+
"@babel/preset-env",
44
[
5-
"@babel/plugin-transform-react-jsx",
5+
"@babel/preset-typescript",
66
{
7-
"pragmaFrag": "React.Fragment"
7+
"allExtensions": true,
8+
"isTSX": true
89
}
9-
]
10+
],
11+
["@babel/preset-react", { "runtime": "automatic" }]
1012
]
1113
}

.github/PULL_REQUEST_TEMPLATE.md

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
- [ ] If added a new recipe interface, then make sure that the implementation of it uses NON arrow functions only (like `someFunc: function () {..}`).
3232
- [ ] If I added a new recipe, I also added the recipe entry point into the `size-limit` section of `package.json` with the size limit set to the current size rounded up.
3333
- [ ] If I added a new recipe, I also added the recipe entry point into the `rollup.config.mjs`
34+
- [ ] If I added a new login method, I modified the list in `lib/ts/types.ts`
35+
- [ ] If I added a factor id, I modified the list in `lib/ts/recipe/multifactorauth/types.ts`
3436

3537
## Remaining TODOs for this PR
3638

.npmignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ jest.config.js
2828
docs/
2929
init.sh
3030
supertokens-auth-react-*.tgz
31-
runExample.sh
31+
runExample.sh
32+
.storybook
33+
stories

.storybook/main.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { StorybookConfig } from "@storybook/react-webpack5";
2+
// import '@storybook/addon-console';
3+
4+
const config: StorybookConfig = {
5+
stories: ["../stories/**/*.mdx", "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
6+
addons: [
7+
"@storybook/addon-essentials",
8+
"@storybook/addon-actions",
9+
"@storybook/addon-links",
10+
"@storybook/addon-interactions",
11+
"@storybook/addon-designs",
12+
// "@storybook/addon-actions/register",
13+
],
14+
async webpackFinal(config, { configType }) {
15+
if (config.module?.rules) {
16+
// By default, Storybook utilizes the style-loader, injecting CSS directly into the DOM.
17+
// In our build process, we import the CSS string and embed it within a style tag.
18+
// The follwoing changes ensure that we replicate this behavior in Storybook.
19+
config.module.rules = config.module.rules.filter(
20+
(rule) => !(typeof rule === "object" && rule?.test instanceof RegExp && rule.test.test(".css"))
21+
);
22+
23+
config.module.rules.push({
24+
test: /\.css$/,
25+
use: ["to-string-loader", "css-loader"],
26+
});
27+
}
28+
return config;
29+
},
30+
framework: {
31+
name: "@storybook/react-webpack5",
32+
options: {},
33+
},
34+
docs: {
35+
autodocs: false,
36+
},
37+
env: {
38+
REACT_APP_TEST_MODE: "testing",
39+
TEST_MODE: "testing",
40+
},
41+
};
42+
export default config;

.storybook/preview.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Preview } from "@storybook/react";
2+
3+
const preview: Preview = {
4+
parameters: {
5+
actions: { argTypesRegex: "^(w+.)*on[A-Z].*" },
6+
controls: {
7+
matchers: {
8+
color: /(background|color)$/i,
9+
date: /Date$/i,
10+
boolean: /(is|show|loaded)/i,
11+
},
12+
},
13+
},
14+
};
15+
16+
export default preview;

CHANGELOG.md

+244
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,250 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
77

8+
## [0.39.0] - 2024-03-07
9+
10+
### Overview
11+
12+
#### Introducing MFA
13+
14+
With this release, we are introducing MultiFactorAuth and TOTP, this will let you:
15+
16+
- require (2FA or MFA) during sign in
17+
- make use of TOTP (e.g.: Google authenticator) as an MFA challenge
18+
19+
Check our [guide](https://supertokens.com/docs/mfa/introduction) for more information.
20+
21+
### Breaking changes
22+
23+
- `SUCCESS` redirections are now handled by the `getRedirectionURL` callback passed to the `SuperTokens.init` config, instead of the recipe level callbacks
24+
- `isNewPrimaryUser` is renamed to `createdNewUser`
25+
- Refactored/renamed some styling options (`resetPasswordHeaderTitle` -> `headerTitle withBackButton`)
26+
- Some default styling has changed related to how fonts/font-weights are applied
27+
- Changed how `headerSubtitle` is styled in components: `EmailPasswordResetPasswordEmail`, `EmailPasswordSubmitNewPassword`, `EmailPasswordSignInHeader`, `EmailPasswordSignUpHeader`
28+
- Removed an `ErrorBoundary` wrapping all our feature components to make sure all errors are properly catchable by the app
29+
- In `supertokens-web-js` (which you may also be using), we added `firstFactors` into the return type of `getLoginMethods` and removed the enabled flags of different login methods.
30+
- For older FDI versions, the firstFactors array will be calculated based on those enabled flags.
31+
32+
#### Migration guide
33+
34+
##### Success redirections & isNewPrimaryUser rename
35+
36+
Before:
37+
38+
```tsx
39+
import SuperTokens, { SuperTokensWrapper, getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react";
40+
import Passwordless from "supertokens-auth-react/recipe/passwordless";
41+
42+
SuperTokens.init({
43+
appInfo: {
44+
// appInfo
45+
},
46+
recipeList: [
47+
Passwordless.init({
48+
contactMethod: "EMAIL_OR_PHONE",
49+
50+
async getRedirectionURL(context) {
51+
if (context.action === "SUCCESS") {
52+
if (context.isNewRecipeUser) {
53+
// new primary user
54+
} else {
55+
// only a recipe user was created
56+
}
57+
}
58+
return undefined;
59+
},
60+
}),
61+
Session.init(),
62+
],
63+
});
64+
```
65+
66+
After:
67+
68+
```tsx
69+
import SuperTokens, { SuperTokensWrapper, getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react";
70+
import Passwordless from "supertokens-auth-react/recipe/passwordless";
71+
72+
SuperTokens.init({
73+
appInfo: {
74+
// appInfo
75+
},
76+
async getRedirectionURL(context, userContext) {
77+
if (context.action === "SUCCESS" && context.newSessionCreated) {
78+
if (context.createdNewUser && context.recipeId === "passwordless") {
79+
// custom logic
80+
}
81+
}
82+
// Returning undefined means we use the default redirection
83+
return undefined;
84+
},
85+
recipeList: [
86+
Passwordless.init({
87+
contactMethod: "EMAIL_OR_PHONE",
88+
}),
89+
Session.init(),
90+
],
91+
});
92+
```
93+
94+
#### Styling changes
95+
96+
There are 2 types of style changes in this release:
97+
98+
1. Refactored/renamed some styling options. If you didn't add custom styles for the following classes there is no action needed
99+
100+
- `resetPasswordHeaderTitle`: should now be styled using `withBackButton`
101+
- `headerSubtitle`: now directly includes the text instead of a `div`, your styles may require an update to match this change
102+
103+
2. Some default styling has changed related to how fonts/font-weights are applied. This may interact with your own font/sizing settings,
104+
if you didn't add font, font-size/weight and size changes to your custom styles, no action should be needed.
105+
106+
Both of the above changes could have subtle interactions with custom styles, so we recommend a quick manual (visual) test to make sure everything
107+
still looks right.
108+
109+
#### getLoginMethods interface change in supertokens-web-js
110+
111+
If you used to use the enabled flags in getLoginMethods:
112+
113+
Before:
114+
115+
```ts
116+
async function checkLoginMethods() {
117+
const loginMethods = await Multitenancy.getLoginMethods();
118+
if (loginMethods.thirdParty.enabled) {
119+
// custom logic
120+
}
121+
if (loginMethods.emailPassword.enabled) {
122+
// custom logic
123+
}
124+
if (loginMethods.passwordless.enabled) {
125+
// custom logic
126+
}
127+
}
128+
```
129+
130+
After:
131+
132+
```ts
133+
async function checkLoginMethods() {
134+
const loginMethods = await Multitenancy.getLoginMethods();
135+
if (loginMethods.firstFactors.includes("thirdparty")) {
136+
// custom logic
137+
}
138+
if (loginMethods.firstFactors.includes("emailpassword")) {
139+
// custom logic
140+
}
141+
142+
if (
143+
loginMethods.firstFactors.includes("otp-email") ||
144+
loginMethods.firstFactors.includes("otp-phone") ||
145+
loginMethods.firstFactors.includes("link-email") ||
146+
loginMethods.firstFactors.includes("link-phone")
147+
) {
148+
// custom logic
149+
}
150+
}
151+
```
152+
153+
#### Event handler changes
154+
155+
Before:
156+
157+
```tsx
158+
import SuperTokens, { SuperTokensWrapper, getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react";
159+
import Passwordless from "supertokens-auth-react/recipe/passwordless";
160+
161+
SuperTokens.init({
162+
appInfo: {
163+
// appInfo
164+
},
165+
recipeList: [
166+
Passwordless.init({
167+
contactMethod: "EMAIL_OR_PHONE",
168+
169+
onHandleEvent(context) {
170+
if (context.action === "SUCCESS") {
171+
let user = context.user;
172+
if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
173+
// sign up success
174+
} else {
175+
// sign in success
176+
}
177+
}
178+
},
179+
}),
180+
Session.init(),
181+
],
182+
});
183+
```
184+
185+
After:
186+
187+
```tsx
188+
import SuperTokens, { SuperTokensWrapper, getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react";
189+
import Passwordless from "supertokens-auth-react/recipe/passwordless";
190+
191+
SuperTokens.init({
192+
appInfo: {
193+
// appInfo
194+
},
195+
recipeList: [
196+
Passwordless.init({
197+
contactMethod: "EMAIL_OR_PHONE",
198+
199+
onHandleEvent(context) {
200+
if (context.action === "SUCCESS" && context.createdNewSession) {
201+
let user = context.user;
202+
let rid = context.rid;
203+
if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
204+
// sign up success
205+
} else {
206+
// sign in success
207+
}
208+
}
209+
},
210+
}),
211+
Session.init(),
212+
],
213+
});
214+
```
215+
216+
### Changes
217+
218+
- Added support for FDI 1.19 (Node SDK>= 17.0.0), but keeping support FDI version 1.17 and 1.18 (node >= 15.0.0, golang>=0.13, python>=0.15.0)
219+
- Added the `MultiFactorAuth` and `TOTP` recipes. To start using them you'll need compatible versions:
220+
- Core>=8.0.0
221+
- supertokens-node>=17.0.0
222+
- supertokens-website>=18.0.0
223+
- supertokens-web-js>=0.10.0
224+
- supertokens-auth-react>=0.39.0
225+
- Added new MFA related components to Passwordless
226+
- Added new prop `mfaFeature` to recipe config
227+
- `disableDefaultUI`: can be used to disable paths: `${websiteBasePath}/mfa/otp-phone`, `${websiteBasePath}/mfa/otp-email`
228+
- `style`: is applied on top of normal sign in/up styles on the MFA paths
229+
- New embeddable components:
230+
- `MfaOtpPhone` (by default handling path `${websiteBasePath}/mfa/otp-phone`)
231+
- `MfaOtpEmail` (by default handling path `${websiteBasePath}/mfa/otp-email`)
232+
- New overrideable components:
233+
- `PasswordlessMFAHeader_Override`
234+
- `PasswordlessMFAFooter_Override`
235+
- `PasswordlessMFAOTPHeader_Override`
236+
- `PasswordlessMFAOTPFooter_Override`
237+
- Please note, that during MFA we re-use the existing overrideable comps for the form section:
238+
- `PasswordlessEmailForm_Override`
239+
- `PasswordlessPhoneForm_Override`
240+
- `PasswordlessEmailOrPhoneForm_Override`
241+
- Added a `useShadowDom` prop to the `AccessDeniedScreen`
242+
- Added an `error` prop to the `AccessDeniedScreen` that can be used to describe the reason access is denied.
243+
- Added a `footer` prop to `EmailOrPhoneForm`, `EmailForm` and `PhoneForm` which is used to override the default sign in/up footers in case the component is for MFA
244+
- Sign in/up functions can now return new (MFA related) error codes.
245+
- New (MFA related) error codes have been added to the default translation files.
246+
- Updated how we select which login UI to show to take the `firstFactors` config value into account (defined in the `MultiFactorAuth` recipe or in the tenant information)
247+
- The passwordless and thirdpartypasswordless sign in/up screens now respect the firstFactors configuration (defined in the `MultiFactorAuth` recipe or in the tenant information) when selecting the available contact methods.
248+
- Added TOTP recipe. For more details please check our guide MFA guide.
249+
- Fixed a font loading issue, that caused apps using the default (Rubik) font to appear with the incorrect font weights
250+
- Added `rid` and `createdNewSession` to events with `action: "SUCCESS"`
251+
8252
## [0.38.0] - 2024-02-29
9253

10254
## Breaking Changes

0 commit comments

Comments
 (0)