Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: move account linking related MFA things into account linking recipe #788

Merged
merged 25 commits into from
Feb 19, 2024

Conversation

porcellus
Copy link
Collaborator

Summary of change

(A few sentences about this PR)

Related issues

  • Link to issue1 here
  • Link to issue1 here

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Bonus points for screenshots and videos!)

Documentation changes

(If relevant, please create a PR in our docs repo, or create a checklist here highlighting the necessary changes)

Checklist for important updates

  • Changelog has been updated
  • coreDriverInterfaceSupported.json file has been updated (if needed)
    • Along with the associated array in lib/ts/version.ts
  • frontendDriverInterfaceSupported.json file has been updated (if needed)
  • Changes to the version if needed
    • In package.json
    • In package-lock.json
    • In lib/ts/version.ts
  • Had run npm run build-pretty
  • Had installed and ran the pre-commit hook
  • If new thirdparty provider is added,
    • update switch statement in recipe/thirdparty/providers/configUtils.ts file, createProvider function.
    • add an icon on the user management dashboard.
  • Issue this PR against the latest non released version branch.
    • To know which one it is, run find the latest released tag (git tag) in the format vX.Y.Z, and then find the latest branch (git branch --all) whose X.Y is greater than the latest released tag.
    • If no such branch exists, then create one from the latest released branch.
  • If have added a new web framework, update the add-ts-no-check.js file to include that
  • If added a new recipe / api interface, then make sure that the implementation of it uses NON arrow functions only (like someFunc: function () {..}).
  • If added a new recipe, then make sure to expose it inside the recipe folder present in the root of this repo. We also need to expose its types.

Remaining TODOs for this PR

  • Item1
  • Item2

// This is different from linking based on account info, but the presence of a session shows that the user has access to both accounts,
// and intends to link these two accounts.
const sessionUserHasVerifiedAccountInfo = sessionUser.loginMethods.some(
(lm) => lm.email === accountInfo.email && lm.phoneNumber === accountInfo.phoneNumber && lm.verified
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not use ===, we should use hasSameEmailAs, and hasSamePhoneNumberAs

});
}

// TODO: verify this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

Comment on lines 82 to 86
// TODO: this'll make us consider EP signups as first factor if `shouldRequireVerification` is true and the user doesn't have the same email address
// TODO: an alternative would be to throw if the verification status is wrong but shouldAutomaticallyLink is true.
wantToLinkSessionUser =
shouldLink.shouldAutomaticallyLink &&
(!shouldLink.shouldRequireVerification || isVerified || sessionUserHasVerifiedAccountInfo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

lib/ts/recipe/accountlinking/index.ts Show resolved Hide resolved
let validRes = await isValidFirstFactor(tenantId, id, userContext);

if (validRes.status === "TENANT_NOT_FOUND_ERROR") {
throw new Error("Tenant not found");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a session exists, we should throw unauthorised, else a normal JS error is fine

tenantId,
user,
// If nether should become a primary user, we can't link them together, so we can return the response user.
return user;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have to try and link the input user to some user here. It's probably already there somewhere above, but need to double check

return user;
}
} else {
if (await this.shouldBecomePrimaryUser(user, tenantId, session, userContext)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this else branch should never come here.

session,
});
if (preAuthChecks.status === "SIGN_IN_UP_NOT_ALLOWED") {
throw new Error("This should never happen: post-auth sign in/up checks should not fail for sign up");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new Error("This should never happen: post-auth sign in/up checks should not fail for sign up");
throw new Error("This should never happen: pre-auth sign in/up checks should not fail for sign in");

session?: SessionContainerInterface;
userContext: UserContext;
}): Promise<
{ status: "OK"; validFactorIds: string[]; isFirstFactor: boolean } | { status: "SIGN_IN_UP_NOT_ALLOWED" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ status: "OK"; validFactorIds: string[]; isFirstFactor: boolean } | { status: "SIGN_IN_UP_NOT_ALLOWED" }
{ status: "OK"; validFactorIds: string[]; isFirstFactor: boolean } | { status: "SIGN_UP_NOT_ALLOWED" }

lib/ts/recipe/emailpassword/api/implementation.ts Outdated Show resolved Hide resolved
);

// create a new session keeping the payloads from the input session
respSession = await Session.createNewSession(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really comfortable with doing this.. it feels weird. What do you think about these instead:

  • If we reach a case where we have to link the session user to the secondary factor user, we instead return a support code; OR
  • We just logout the user from their current session and so they have to sign in again.

lib/ts/authUtils.ts Show resolved Hide resolved
@porcellus porcellus force-pushed the feat/mfa/account-linking-refactor branch 2 times, most recently from b7f14ed to b0e3f86 Compare February 2, 2024 15:29
@porcellus porcellus force-pushed the feat/mfa/account-linking-refactor branch from b0e3f86 to a6cb81d Compare February 2, 2024 22:45
Comment on lines 89 to 97
// This means that the session user got primary since we loaded the session user info above
sessionUser = await getUser(makeSessionUserPrimaryRes.primaryUserId, userContext);

if (sessionUser === undefined) {
throw new SessionError({
type: SessionError.UNAUTHORISED,
message: "Session user not found",
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, this means that the session got linked to another primary user, which means the primary user id has changed, so we should just logout the user?

} else {
// All other statuses signify that we can't make the session user primary
// Which means we can't continue
return { status: "NON_PRIMARY_SESSION_USER" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should translate to a different support code compared to the case below. So we might want to make this a different status here, or add some other prop to this output indicating the actual reason

// It should not happen in general, but it is possible that we end up with an unlinked user after this even though originally we considered this
// an MFA sign in.
// There are a couple of race-conditions associated with this functions, but it handles retries internally.
const linkingResult = await accountLinkingInstance.createPrimaryUserIdOrLinkByAccountInfo({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const linkingResult = await accountLinkingInstance.createPrimaryUserIdOrLinkByAccountInfo({
const linkingResult = await accountLinkingInstance.createPrimaryUserIdOrLinkByAccountInfoOrLinkToSessionIfProvided({

@@ -34,6 +35,7 @@ export default class Wrapper {
static async createPrimaryUserIdOrLinkAccounts(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function shouldn't link to the session user even if a session is passed to it (so same behaviour as in the master branch)

(lm) => lm.recipeUserId === session.getRecipeUserId()
);
if (postLinkUserLinkedToSessionUser && mfaInstance !== undefined) {
// if the authenticating user is linked to the current user (it means that the factor got set up or completed),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if the authenticating user is linked to the current user (it means that the factor got set up or completed),
// if the authenticating user is linked to the current session user (it means that the factor got set up or completed),

const postLinkUserLinkedToSessionUser = linkingResult.user.loginMethods.some(
(lm) => lm.recipeUserId === session.getRecipeUserId()
);
if (postLinkUserLinkedToSessionUser && mfaInstance !== undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (postLinkUserLinkedToSessionUser && mfaInstance !== undefined) {
if (postLinkUserLinkedToSessionUser) { if (mfaInstance !== undefined) {...

// then we do not want to include a link in the email.
for (const id of factorIds) {
try {
if (!factorsAlreadySetUp.includes(id)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!factorsAlreadySetUp.includes(id)) {
if (isSignUp) {...} else { /* assert that id is in factorsAlreadySetUp */}

try {
if (!factorsAlreadySetUp.includes(id)) {
await MultiFactorAuth.assertAllowedToSetupFactorElseThrowInvalidClaimError(
session!,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should take the authenticating user into account here and when we decide value of wantToLinkSessionUser

lib/ts/authUtils.ts Show resolved Hide resolved
}

logDebugMessage("preAuthChecks checking auth types");
// First we check if the app intends to link the user from the signin/up response or not,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"from the signin/up response" -> what does this mean?

return { status: "OK", sessionUser };
}

async function checkAuthType( // TODO: better name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: better name. Consider calling it preAuthChecksHelper

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't really help tell what it does. For now I've renamed it to checkAuthTypeAndLinkingStatus but we can discuss this over a call

lib/ts/authUtils.ts Outdated Show resolved Hide resolved
Comment on lines 526 to 534
// This means that the session user got primary since we loaded the session user info above
sessionUser = await getUser(makeSessionUserPrimaryRes.primaryUserId, userContext);

if (sessionUser === undefined) {
throw new SessionError({
type: SessionError.UNAUTHORISED,
message: "Session user not found",
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just throw unauthorised here cause the user Id of the session has changed here anyway, so the session is invalid?

logDebugMessage(`checkAuthType loading session user`);
// We have to load the session user in order to get the account linking info
const sessionUserResult = await getPrimarySessionUser(session, tenantId, userContext);
if (sessionUserResult.status !== "OK") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a status of NON_PRIMARY_SESSION_USER_OTHER_PRIMARY_USER should not mean isFirstFactor, but it should instead result in a support code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess we can do that since that also implies that the app tried to make it a primary user.
This'll slightly change how we used to work even in the case where the app doesn't want to link to the session user. I think we are OK with that as well, but that's basically why I went with first factor sign in in this case.

Comment on lines 915 to 920
if (
primaryUserThatCanBeLinkedToTheInputUser !== undefined &&
sessionUser.id !== primaryUserThatCanBeLinkedToTheInputUser.id
) {
return { status: "LINKING_TO_SESSION_USER_FAILED" };
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to do this check? When we call linkAccounts, it will fail anyway.

Comment on lines 899 to 904
const usersToLink = await this.getUsersThatCanBeLinkedToRecipeUser({
tenantId,
user: inputUser,
userContext,
});
const primaryUserThatCanBeLinkedToTheInputUser = usersToLink.primaryUser;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed (see comment in place where primaryUserThatCanBeLinkedToTheInputUser is used)

Comment on lines 906 to 911
// If we get here, we know that the session user is primary.
// if both of them are primary, they cannot be linked together.
// we also check this outside of this function.
if (inputUser.isPrimaryUser) {
return { status: "LINKING_TO_SESSION_USER_FAILED" };
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to do this check? Calling linkAccounts will anyway make this fail..

Comment on lines 894 to 896
| { status: "OK"; user: User }
| { status: "LINKING_TO_SESSION_USER_FAILED" }
| { status: "NON_PRIMARY_SESSION_USER" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please reuse existing account linking status codes

!sessionUserLinkingRequiresVerification || authLoginMethod.verified || sessionUserHasVerifiedAccountInfo;

if (!canLinkBasedOnVerification) {
return { status: "LINKING_TO_SESSION_USER_FAILED" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will go as a support code to the frontend right? We should capture the exact reason here.

Comment on lines 45 to 49
accountInfo,
tenantId,
isSignUp,
isVerified,
inputUser,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename inputUser and accountInfo

}
logDebugMessage(`checkAuthTypeAndLinkingStatus loading session user`);
// We have to load the session user in order to get the account linking info
const sessionUserResult = await AccountLinking.getInstance().getPrimarySessionUser(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move getPrimarySessionUser into this file. It can continue to be its own function.


getPrimarySessionUser = async function (
session: SessionContainerInterface,
tenantId: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need tenantId cause session already contains all tenant id

return { primaryUser, oldestUser };
};

getPrimarySessionUser = async function (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment here explaining what this function is doing exactly. It's not obvious from the name

return { primaryUser, oldestUser };
};

getPrimarySessionUser = async function (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
getPrimarySessionUser = async function (
tryAndMakeSessionUserIntoAPrimaryUser = async function (

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go into authUtils.ts

getAuthenticatingUserAndAddToCurrentTenantIfRequired: async ({
recipeId,
accountInfo,
tenantId: currentTenantId,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for tenantid since session already has it

userContext,
}: {
recipeId: string;
accountInfo: AccountInfo;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update the type of this to make sure that only one of the info (email, phone number or third party) is passed and not multiple

logDebugMessage(
`getAuthenticatingUserAndAddToCurrentTenantIfRequired session user is non-primary so returning early without checking other tenants`
);
return undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth mentioning why returning undefined here is ok

return undefined;
}

const matchingLoginMethods = sessionUser.loginMethods.filter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const matchingLoginMethods = sessionUser.loginMethods.filter(
const matchingLoginMethodsFromSessionUser = sessionUser.loginMethods.filter(

authenticatingUser = {
user: sessionUser,
loginMethod: matchingLoginMethods.find((lm) => lm.tenantIds.includes(currentTenantId))!,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should return early?

Comment on lines 540 to 535
let linkedToUser = await AccountLinking.getInstance().createPrimaryUserIdOrLinkAccounts({
tenantId,
user: createUserResponse.user,
userContext,
});
if (linkedToUser.id !== existingUser.id) {
const linkRes = await AuthUtils.linkToSessionIfProvidedElseCreatePrimaryUserIdOrLinkByAccountInfo(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not take into account the input session

Comment on lines 807 to 822
// We call signUp whenever possible, since people overriding functions will expect this to be called for normal sign up flows
// and use this to execute post sign up hooks
signUpResponse = await options.recipeImplementation.signUp({
tenantId,
email,
password,
session,
userContext,
});
} else {
signUpResponse = await options.recipeImplementation.createNewRecipeUser({
tenantId,
email,
password,
userContext,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can just use signUp here instead of using createNewRecipeUser

@@ -151,28 +157,49 @@ export type RecipeInterface = {
userInputCode: string;
deviceId: string;
preAuthSessionId: string;
createRecipeUserIfNotExists: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not required

Comment on lines 193 to 202
status: "LINKING_TO_SESSION_USER_FAILED";
reason:
| "EMAIL_VERIFICATION_REQUIRED"
| "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"
| "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR";
}
| {
status: "NON_PRIMARY_SESSION_USER";
reason: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR";
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this into one block

}
const checkCredentialsOnTenant = async (tenantId: string) => {
return (
(await options.recipeImplementation.signIn({ email, password, session, tenantId, userContext }))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a new recipe function called checkCredentials

userInputCode: string;
deviceId: string;
preAuthSessionId: string;
createRecipeUserIfNotExists: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this boolean should not be here. It should always be false.

| {
linkCode: string;
preAuthSessionId: string;
createRecipeUserIfNotExists: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this boolean should not be here. It should always be false.

phoneNumber?: string;
};
createdNewRecipeUser?: boolean;
user?: User;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
user?: User;

email?: string;
phoneNumber?: string;
};
createdNewRecipeUser?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
createdNewRecipeUser?: boolean;

};
createdNewRecipeUser?: boolean;
user?: User;
recipeUserId?: RecipeUserId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
recipeUserId?: RecipeUserId;

@@ -209,6 +243,44 @@ export type RecipeInterface = {
}
>;

verifyAndDeleteCode: (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
verifyAndDeleteCode: (
verifyCode: (

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass a non optional flag called deleteCode (so this will require a core change).

We expose a verifyAndDeleteCode function in the index file, which calls verifyCode with deleteCode: true all the time.

@porcellus porcellus merged commit 9153bff into feat/mfa/base Feb 19, 2024
3 of 14 checks passed
@porcellus porcellus deleted the feat/mfa/account-linking-refactor branch February 19, 2024 08:49
rishabhpoddar added a commit that referenced this pull request Mar 12, 2024
* feat(mfa): initial types (#708)

* feat: add (partial) initial types for MFA

* feat: expand the MFA recipe interface

* feat: add export point for mfa

* feat: update based on review discussions

* feat: add extra params to MFARequirements callbacks to help customizations

* feat: implement review feedback

* feat: implement review comments

* feat: implement review comments

* feat: stricter type for first factor/mfa requirement

* feat: remove distinction between built-in and custom factors (#729)

* fix: MFA type updates (#737)

* fix: type fix and account linking functions

* fix: cdi version update

* fix: more type updates

* fix: tests

* fix: TOTP recipe (#739)

* fix: type fix and account linking functions

* fix: cdi version update

* fix: more type updates

* fix: tests

* fix: totp recipe

* fix: totp types

* fix: update types

* fix: totp apis

* fix: user identifier info

* fix: recipe tests

* fix: test

* fix: pr comments

* fix: tests

* fix: PR comment

* fix: MFA implementation (#743)

* fix: type fix and account linking functions

* fix: cdi version update

* fix: more type updates

* fix: tests

* fix: totp recipe

* fix: totp types

* fix: update types

* fix: totp apis

* fix: user identifier info

* fix: recipe tests

* fix: test

* fix: basic mfa impl

* fix: pr comments

* fix: tests

* fix: factors setup from other recipe

* fix: getFactorsSetupForUser impl

* fix: getMFARequirementsForAuth impl

* fix: isAllowedToSetupFactor impl

* fix: addToDefaultRequiredFactorsForUser and getDefaultRequiredFactorsForUser impl

* fix: typo

* fix: build next array

* fix: remove error file

* fix: factorSetupForUser refactor

* fix: next array

* fix: api impl

* fix: typo

* fix: isValidFirstFactorForTenant

* fix: impl

* fix: updated impl

* feat: fix and update mfa imlp to make all e2e tests pass

* fix: adds overwriteSessionDuringSignIn config in session

* fix: error messages in claims

* fix: cleanup

* fix: new errors for sign in up APIs

* fix: add error in totp

* fix: marked MFA TODOs

* fix: new param in createNewSession

* fix: impl cleanup

* fix: remove MFA_ERROR

* fix: cdi version

* fix: test fix

* fix: update/fix mfa impl to match e2e tests

* fix: pr comments

* fix: session user deleted error

* fix: adding cache to getUserById

* fix: get user cache

* caching in querier

* fix: mfa impl

* fix: email selection

* fix: mfa claims

* fix: remove unnecessary file

* fix: pr comment

* fix: PR comments

* fix: session handling

* fix: review comments

* fix: defaultRequiredFactorsForUser is now appwide

* fix: using accountlinking instead of mfa for primary user and link accounts

* fix: overwrite session flag refactor

* fix: race conditions in createOrUpdateSessionForMultifactorAuthAfterFactorCompletion

* fix: race conditions in createOrUpdateSessionForMultifactorAuthAfterFactorCompletion

* fix: recipe functions refactor

* fix: contact support case

* fix: unnecessary file

* fix: test

* refactor: added shouldRefetch + fetchValue building the next array into MFAclaim (#758)

* fix: usercontext type

* fix: test

* fix: test

* feat: add access token payload param to claim.build

* feat: expose addToDefaultRequiredFactorsForUser and remove tenantId param

* fix: remaining TODOs

* fix: auto init tests related to mfa

* fix: recipe function tests

* fix: create new session refactor

* fix: recipe interface refactor

* fix: userContext type fix

* fix: test

* fix: test

* fix: session

* fix: user context and support codes

* fix: type fixes after merge

* fix: test

* fix: pr comments

* fix: pr comment

* fix: test

* fix: available factors

* fix: updated user object

* fix: shouldAttemptAccountLinkingIfAllowed

* fix: missed types and test fixes

* fix: mfa fixes and tests

* fix: more tests

---------

Co-authored-by: Mihaly Lengyel <mihaly@lengyel.tech>

* fix: contact support case when existing user signs in

* fix: shouldAttemptAccountLinkingIfAllowed

* fix: tackling some corner cases with account linking and user sign up

* fix: isSignUpAllowed condition

* fix: branded type explanation

* fix: revert verifyEmailForRecipeUserIfLinkedAccountsAreVerified

* fix: fixing shouldAttemptAccountLinkingIfAllowed typing

* fix: recipe id check in emailpassword

* fix: comment on not checking for tenantId

* fix: remove implicit tenantInfo

* fix: remove implicit tenantInfo

* fix: duplicate factorIds

* fix: not required params in validateForMultifactorAuthBeforeFactorCompletion

* fix: input type of validateForMultifactorAuthBeforeFactorCompletion

* changes impl of getMFARequirementsForAuth to remove oldest factor id

* fix: rename defaultRequiredFactors to requiredSecondaryFactors for user

* fix: update multitenancy core api

* fix: add remove required secondary factors for user

* fix: exposing known factor idsstnbp

* fix: move to recipe impl

* fix: not automatically assuming otp as setup

* fix: update mfa info response

* fix: changed mfa/info to PUT

* fix: user refetch in emailpassword

* fix: updated comments

* fix: constant name

* fix: factor flow impl in emailpassword and passwordless

* fix: factor flow for thirdparty

* fix: totp verification

* fix: remove createNewOrKeepExistingSession

* fix: improve createOrUpdateSessionForMultifactorAuthAfterFactorCompletion

* fix: phoneNumber check

* fix: sign in/up status refactor

* fix: sign in/up status

* fix: tests

* fix: tests

* feat: return email addresses for pwless factors based on the discussed priority order

* fix: firstFactor validation and loginmethods

* fix: userContext types and test

* fix: misc changes

* fix: emails for factor

* fix: param rename

* fix: msg update

* fix: shouldAttemptAccountLinkingIfAllowed in thirdparty

* fix: updated race conditions recursions

* fix: removed tenantId checks for mfa

* fix: recursion for support cases

* fix: revert recursion fix to return 011

* fix: support code flows

* fix: recursion point

* fix: rename allOf to allOfInAnyOrder

* fix: support codes

* fix: copyright update

* fix: copyright update

* fix: implicit check

* fix: support codes

* fix: mfa flow refactor (#771)

mfa flow refactor and support codes

* fix: typo

* fix: comments

* fix: next array (#770)

mfa info endpoint changes

* fix: support code messages

* fix: rename isAllowedToSetup and return claim error

* fix: call checkAllowedToSetupFactorElseThrowInvalidClaimError in createCode and createDevice

* fix: fixed status

* fix: createNewSession param type

* fix: mfa validation only on sign up in createCode

* fix: factor check in create code

* fix: factor check in create code

* fix: remove mfa check in createCode

* fix: removed unused status

* fix: thirdparty api refactor

* fix: passwordless api refactor and thirdparty api refactor fixes

* fix: emailpassword api refactor and fixes in pless and tparty apis

* fix: fixes after refactor

* fix: clean up is valid first factor

* fix: pr comments

* fix: pr comments

* fix: refactor

* fix: refactor

* fix: internal function for get user metadata for MFA

* fix: pr comment

* fix: race conditions

* fix: refactor all factors

* fix: comments

* fix: assertAllowedToSetupFactorElseThrowInvalidClaimError in verify device

* fix: tests

* fix: add comment

* fix: refactor resync api stuff

* fix: refactor missing claims

* fix: dedup code in mfa claim

* fix: pr comments for emailpassword

* fix: pr comments for emailpassword

* fix: pr comments

* fix: pr comments for email password

* fix: pr comments for passwordless

* fix: pr comments for thirdparty

* fix: pr comments

* fix: move recurse outside

* fix: move assert sign in is allowed

* fixes and changes

* thirdparty recipe change

* fix: cyclic dependency

* fix: test

* fix: claim value type

* fix: pr comments from ep to pless

* fix: remove internal functions from usermetadata

* fix: context in session class

* fix: session required in signout

* fix: remove implicit check

* fix: doUnionOfAccountInfo false for consistency

* fix: pr comments from ep in pless

* fix: remove shouldAttemptAccountLinkingIfAllowed in passwordless

* fix: make isValidFirstFactor more readble with comments

* fix: remove tenantId from getFactorsSetupForuser

* fix: PR comments

* fix: refactor totp

* fix: post init callbacks to constructor

* fix: totp PR comments

* fix: error messages, test and fetch failure check

* fix: tests

* fix: tests

* fix: PR comments

* fix: Pr comments

* fix: missed await + test fix

* fix: missed await

* fix: pr comments

* fix: not use splice

* fix: user metadata refactor

* fix: mfa refactor

* fix: self review

* fix: clean up and comments

* fix: comment

* fix: refactor factorIds

* fix: refactor factorIds

* fix: handle unknown user id error in totp

* fix: updated signout

* fix: removed extra code

* fix: session and tenantId in createCode

* fix: first factor computation

* fix: comment

* fix: createRecipeUser in pless

* fix: factor completion in thirdparty signInUp

* fix: updated fake email

* fix: should attempt account linking in third party

* fix: throw unauthorised for tenant not found

* fix: signout api

* fix: cyclic dependency

* fix: shouldAttemptAccountLinkingIfAllowed

* fix: check claims error and throw others

* fix: remove unnecessary session undefined check

* fix: session in create code and resend code POST

* fix: tenant not found

* fix: mfa claim updation in util function

* fix: revert to original :(

* fix: revert to original :(

* fix: cleanup

* fix: pless createRecipeUser type

* fix: pless revert

* fix: querier caching to include headers

* feat: use dynamic signing key switching (#782)

* feat: enable a smooth switch between useDynamicAccessTokenSigningKey true and false

* Merging feat/mfa/base into feat/useDynamicSigningKey_switching

* fix: update prop name

* feat: move account linking related MFA things into account linking recipe (#788)

* feat: move account linking related MFA things into account linking recipe

* test: update test to match new linking logic

* feat(mfa)!: simplifying account linking flows

* feat(mfa): updating impl of other recipe sign in/up endpoints + add createRecipeUserIfNotExists to consume code

* feat: implement updated linking flow + fix tests

* chore: remove unnecessary code

* fix: fix typo/missing update

* refactor: implementing review comments

* refactor: implementing review comments

* fix: add retry logic to createPrimaryUserIdOrLinkAccounts index func

* fix: use hasSameEmailAs instead of ===

* refactor: improve getAuthenticatingUserAndAddToCurrentTenantIfRequired input types & comments

* fix: remove wrong emailverification check from tryLinkAccounts

* refactor: removed unnecessary status + added explanation comments

* refactor: implement review comments

* refactor: implement review comments + move functions

* fix: fix accidentally flipped condition

* fix: tidy up typos

* fix: update func impl after moving

* fix: cleaning up and updating tests

* feat: refactoring for latest review comments

* test: add mock for verifyCode

* fix: cleanup and test fixes

* chore: update error code reason strings

* feat: remove factorIds from createCode input

* fix: properly compare recipeUserIds as strings

* feat: add signInVerifiesLoginMethod and minor cleanup/fixes

* test: add new tests + update cases for new account linking logic/interface

* fix: login methods (#794)

* fix: login methods fix

* fix: cleanup

* fix: cleanup

* fix: pr comments

* fix: pr comment

* fix: better test names

* fix: comparision

* feat: self-review fixes

* chore: update changelog

* feat: self-review fixes

* feat: remove shouldAttemptAccountLinkingIfAllowed

* feat: add verifyCredentials to ep and tpep recipes

* feat: self-review fixes and latest discussions

* fix: return userType instead of the user class consistently in the index files

* feat: properly expose verifyCredentials and verifyCode

* fix: add some missing tests and a related fix

* feat: add call count tests and improve call counts

* refactor: not trying linking if shouldDoAutomaticAccountLinking wasn't defined by the app

* feat: implement review feedback

* chore: add version number and compatibility section into changelog

* feat: update mfa interface to optimize for less core calls

* feat: make the core call cache reset globally if a call was made without usercontext

* feat: ensure the email verification api can update the session if necessary

* feat: verify the user in consume code if possible before trying to make it primary

* feat: update verifyCredentials types to re-use it in signIn

* feat: add disableCoreCallCache

* refactor: remove resolved comment

* chore: update changelog

* feat: move the skipSessionUserUpdateInCore check before we check EV status

* feat: fix tests & update for latest core

* docs: fix jsdocs for pwless

* docs: add explanation comment

* feat: cache the result of checkCode in pwless consume code api

* feat: add new param to revokeCode

* feat: update changelog + consistency

---------

Co-authored-by: Mihály Lengyel <mihaly@lengyel.tech>
Co-authored-by: Rishabh Poddar <rishabh.poddar@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants