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!: Account linking #670

Merged
merged 85 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
170c677
account linking changes (#425)
bhumilsarvaiya Nov 23, 2022
08c2b89
Recipe interface changes regarding account-linking (#439)
bhumilsarvaiya Nov 25, 2022
1c8b4f5
thirdparty interface changes regarding account-linking (#443)
bhumilsarvaiya Nov 28, 2022
7973b8c
passwordless interface changes for account linking (#444)
bhumilsarvaiya Nov 28, 2022
1d98e90
feat: Account linking interface update (#463)
bhumilsarvaiya Dec 30, 2022
3148dc1
merge with 13.0
bhumilsarvaiya Feb 13, 2023
d233bbc
feat: Account linking recipe implementation (#466)
bhumilsarvaiya Mar 3, 2023
3046204
chore: Account linking general refactor (#541)
nkshah2 May 2, 2023
765d915
more review comment changes
rishabhpoddar May 2, 2023
35c1e93
type changes
rishabhpoddar May 2, 2023
8b493a7
feat: Emailpassword accountlinking (#501)
bhumilsarvaiya May 7, 2023
b678e7d
merges with latest (#559)
rishabhpoddar May 8, 2023
211c898
Emailverification accountlinking (#528)
bhumilsarvaiya May 11, 2023
651d2e7
merges (#560)
rishabhpoddar May 11, 2023
b14e25d
merges
rishabhpoddar May 11, 2023
81d0055
builds pretty
rishabhpoddar May 11, 2023
559539b
merges with latest
rishabhpoddar May 11, 2023
808f75c
merges
rishabhpoddar May 11, 2023
89baf8e
merges with latest
rishabhpoddar May 11, 2023
9a093cb
Account linking test fixes (#566)
rishabhpoddar May 17, 2023
de00244
Account linking recipe primary user id types (#568)
rishabhpoddar May 19, 2023
73f3b7c
merges with latest
rishabhpoddar May 30, 2023
39c9636
Account linking tests (#572)
rishabhpoddar Jun 1, 2023
f77d909
Merge branch '14.1' into account-linking
rishabhpoddar Jun 3, 2023
2130c6e
removes use of account linking claim (#577)
rishabhpoddar Jun 4, 2023
a26c48b
adds mock reset to make tests pass
rishabhpoddar Jun 4, 2023
683ed8b
merges with latest
rishabhpoddar Jun 7, 2023
777f363
account linking third party (#579)
rishabhpoddar Jun 11, 2023
8296c17
Merge branch '14.1' into account-linking
rishabhpoddar Jun 14, 2023
b2ba9b2
changes to sign in flow for third party and email password to check f…
rishabhpoddar Jun 15, 2023
8c5c992
fixes a test
rishabhpoddar Jun 15, 2023
8d00959
removes unnecessary console log
rishabhpoddar Jun 15, 2023
802bb26
fixes a bug
rishabhpoddar Jun 16, 2023
17e2002
a few fixes and edge cases
rishabhpoddar Jun 16, 2023
e791146
Merge branch '14.1' into account-linking
rishabhpoddar Jun 20, 2023
b7a58e3
small bug fix
rishabhpoddar Jun 21, 2023
147be98
removes unused function
rishabhpoddar Jun 29, 2023
aa12c03
small changes
rishabhpoddar Jun 29, 2023
37ec32e
Merge remote-tracking branch 'origin/15.0' into account-linking
porcellus Aug 2, 2023
05719a3
feat: smaller test&test based fixes for merge issues
porcellus Aug 2, 2023
96e9fb4
feat: implement passwordless in account-linking (#664)
porcellus Aug 4, 2023
0522927
feat: integrate with CDI 4.0 (#665)
porcellus Aug 6, 2023
24ef7a3
fix: minor fix for getsession api in dashboard recipe (#666)
iresharma Aug 7, 2023
9ceaae6
fix: add missing serialization in userDetailsGET
porcellus Aug 7, 2023
dd87174
feat: fixing checklist items (#669)
porcellus Aug 8, 2023
7b4d4d1
feat: checklist progress + updated/extended tests
porcellus Aug 18, 2023
82ddf38
test: extended account linking tests based on the checklist
porcellus Aug 21, 2023
a4e186c
feat: add some error codes to messages including contact support
porcellus Aug 21, 2023
c9c9082
feat: Account unlink endpoint for dashboard (#674)
iresharma Aug 21, 2023
a21bf65
Merge remote-tracking branch 'origin/15.1' into account-linking
porcellus Aug 22, 2023
a284b04
feat(account_linkig): optimize to have less core calls/update interfa…
rishabhpoddar Sep 1, 2023
966e9d9
test: test util improvements
porcellus Sep 1, 2023
9ab4f61
docs: moved account-linking example app to auth-react
porcellus Sep 4, 2023
5093a2a
feat: update error codes
porcellus Sep 4, 2023
59e933a
fix: emailExistsGET should check if the login method has the right email
porcellus Sep 4, 2023
7a7315b
feat: allow sign-in in more cases
porcellus Sep 6, 2023
f0c8bc1
feat: remove EMAIL_ALREADY_USED_IN_ANOTHER_ACCOUNT
porcellus Sep 7, 2023
244a225
feat: update types based on CDI changes
porcellus Sep 7, 2023
f3fcaf8
feat: ignore protected props in createNewSession* (#690)
porcellus Sep 11, 2023
dcf849f
feat: update return type of update user in pwless
porcellus Sep 12, 2023
37c66d3
feat: add separate error codes for sign in/up not allowed in EP
porcellus Sep 12, 2023
9463064
fix: make connection refused detection in querier a bit more general
porcellus Sep 12, 2023
2a82e65
feat: remove tenantId from isEmailChangeAllowed inputs
porcellus Sep 12, 2023
8cf2eef
feat: make user (dis)association fns take recipeUserId instead of userId
porcellus Sep 12, 2023
8db8133
test: update tests for new behaviour + some cleanup
porcellus Sep 12, 2023
2a6cb57
Merge branch 'account-linking' of github.com:supertokens/supertokens-…
porcellus Sep 12, 2023
0bf3742
Merge remote-tracking branch 'origin/15.2' into account-linking
porcellus Sep 12, 2023
d737abd
fix: fix returning SIGN_UP_NOT_ALLOWED to the client
porcellus Sep 12, 2023
c57a784
fix: update the error message for ERR_CODE_007
porcellus Sep 12, 2023
e110712
feat: remove DISASSOCIATION_NOT_ALLOWED_ERROR
porcellus Sep 12, 2023
f723447
chore: update changelog
porcellus Sep 12, 2023
67efb36
feat: update param name to match CDI
porcellus Sep 13, 2023
5da23d8
chore: bump dashboard version
porcellus Sep 13, 2023
dc681e3
fix: update types based on the CDI
porcellus Sep 13, 2023
74ba078
test: update tests
porcellus Sep 13, 2023
bb74f9b
test: update auth-react-server for tests
porcellus Sep 13, 2023
ff5f182
test: update test server to better handle in-memory tests
porcellus Sep 14, 2023
825888f
chore: extended changelog
porcellus Sep 14, 2023
4f1a681
test: update integration test server
porcellus Sep 14, 2023
1140130
test: add an extended test checking if protected props are ignored in…
porcellus Sep 16, 2023
68c4803
fix: return FIELD_ERROR even if AL is on if there is a conflicting EP…
porcellus Sep 16, 2023
340d80f
Apply suggestions from code review
porcellus Sep 16, 2023
56255ee
docs: extended changelog & implemented review comments
porcellus Sep 16, 2023
d2b8684
docs: make migration guide more consistent
porcellus Sep 16, 2023
617d882
Update .github/PULL_REQUEST_TEMPLATE.md
rishabhpoddar Sep 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
233 changes: 233 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,239 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

## [16.0.0] - 2023-08-XX

rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
### Overview

#### Introducing account-linking

With this release, we are introducing a new AccountLinking recipe, this will let you:

- link accounts automatically,
- implement manual account linking flows.

Check our [guide](https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/account-linking/overview) for more information.

To use this you'll need compatible versions:

- Core>=7.0.0
- supertokens-node>=16.0.0 (support is pending in other backend SDKs)
- supertokens-website>=17.0.3
- supertokens-web-js>=0.8.0
- supertokens-auth-react>=0.35.0

#### The new User object and primary vs non-primary users

In this release, we've removed the recipes specific user types and instead introduced a new `User` class to support the "Primary user" concept introduced by account linking

- The new `User` class now provides the same interface for all recipes.
- It contains an `isPrimary` field that you can use to differentiate between primary and recipe users
- The `loginMethods` array contains objects that covers all props of the old (recipe specific) user types, with the exception of the id. Please check the migration section below to get the exact mapping between old and new props.
- Non-primary users:
- The `loginMethods` array should contain exactly 1 element.
- `user.id` will be the same as `user.loginMethods[0].recipeUserId.getAsString()`.
- `user.id` will change if it is linked to another user.
- They can become a primary user if, and only if there are no other primary users with the same email, third party info or phone number as this user across all the tenants that this user is a part of.
- Primary users
- The `loginMethods` array can have 1 or more elements, each corresponding to a single recipe user.
- `user.id` will not change even if other users are linked to it.
- Other non-primary users can be linked to it. The user ID of the linked accounts will now be the primary users ID.
- Check [here](https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/account-linking/overview#primary-user-vs-non-primary-user) for more information about differences between primary and recipe users.

#### Primary vs RecipeUserId

Because of account linking we've introduced a new Primary user concept (see above). In most cases, you should only use the primary user id (`user.id` or `session.getUserId()`) if you are associating data to users. Still, in some cases you need to specifically refer to a login method, which is covered by the new `RecipeUserId` class:

- You can get it:
- From a session by: `session.getRecipeUserId()`.
- By finding the appropriate entry in the `loginMethods` array of a `User` object (see above): `user.loginMethods[0].recipeUserId`.
- It wraps a simple string value that you can get by calling `recipeUserId.getAsString()`.
- We've introduced it to differentiate between primary and recipe user ids in our APIs on a type level.
- Check [here](https://supertokens.com/docs/thirdpartyemailpassword/user-object#primary-vs-recipe-user-id) for more information.

### Breaking changes

rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
- Now only supporting CDI 4.0. Compatible with core version >= 7.0
- Now supporting FDI 1.18
- Removed the recipe specific `User` type, now all functions are using the new generic `User` type.
- Check [here](https://supertokens.com/docs/thirdpartyemailpassword/user-object) for more information.
- The `build` function and the `fetchValue` callback of session claims now take a new `recipeUserId` param.
- This affects built-in claims: `EmailVerificationClaim`, `UserRoleClaim`, `PermissionClaim`, `AllowedDomainsClaim`.
- This will affect all custom claims as well built on our base classes.
- Now ignoring protected props in the payload in `createNewSession` and `createNewSessionWithoutRequestResponse`
- `createdNewUser` has been renamed to `createdNewRecipeUser` in sign up related APIs and functions

- EmailPassword:
- removed `getUserById`, `getUserByEmail`. You should use `supertokens.getUser`, and `supertokens. listUsersByAccountInfo` instead
- added `consumePasswordResetToken`. This function allows the consumption of the reset password token without changing the password. It will return OK if the token was valid.
- added an overrideable `createNewRecipeUser` function that is called during sign up and password reset flow (in case a new email password user is being created on the fly). This is mostly for internal use.
- `recipeUserId` is added to the input of `getContent` of the email delivery config
- `email` was added to the input of `createResetPasswordToken` , `sendResetPasswordEmail`, `createResetPasswordLink`
- `updateEmailOrPassword` :
- now takes `recipeUserId` instead of `userId`
- can return the new `EMAIL_CHANGE_NOT_ALLOWED_ERROR` status
- `signIn`:
- returns new `recipeUserId` prop in the `status: OK` case
- `signUp`:
- returns new `recipeUserId` prop in the `status: OK` case
- `signInPOST`:
- can return status `SIGN_IN_NOT_ALLOWED`
- `signUpPOST`:
- can return status `SIGN_UP_NOT_ALLOWED`
- `generatePasswordResetTokenPOST`:
- can now return `PASSWORD_RESET_NOT_ALLOWED`
- `passwordResetPOST`:
- now returns the `user` and the `email` whose password was reset
- can now return `PASSWORD_POLICY_VIOLATED_ERROR`
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
- EmailVerification:
- `createEmailVerificationToken`, `createEmailVerificationLink`, `isEmailVerified`, `revokeEmailVerificationTokens` , `unverifyEmail`:
- now takes `recipeUserId` instead of `userId`
- `sendEmailVerificationEmail` :
- now takes an additional `recipeUserId` parameter
- `verifyEmailUsingToken`:
- now takes a new `attemptAccountLinking` parameter
- returns the `recipeUserId` instead of `id`
- `sendEmail` now requires a new `recipeUserId` as part of the user info
- `getEmailForUserId` config option was renamed to `getEmailForRecipeUserId`
- `verifyEmailPOST`, `generateEmailVerifyTokenPOST`: returns an optional `newSession` in case the current user session needs to be updated
- Passwordless:
- removed `getUserById`, `getUserByEmail`, `getUserByPhoneNumber`
- `updateUser` :
- now takes `recipeUserId` instead of `userId`
- can return `"EMAIL_CHANGE_NOT_ALLOWED_ERROR` and `PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR` statuses
- `createCodePOST` and `consumeCodePOST` can now return `SIGN_IN_UP_NOT_ALLOWED`
- Session:
- access tokens and session objects now contain the recipe user id
- Support for new access token version
- `recipeUserId` is now added to the payload of the `TOKEN_THEFT_DETECTED` error
- `createNewSession`: now takes `recipeUserId` instead of `userId`
- Removed `validateClaimsInJWTPayload`
- `revokeAllSessionsForUser` now takes an optional `revokeSessionsForLinkedAccounts` param
- `getAllSessionHandlesForUser` now takes an optional `fetchSessionsForAllLinkedAccounts` param
- `regenerateAccessToken` return value now includes `recipeUserId`
- `getGlobalClaimValidators` and `validateClaims` now get a new `recipeUserId` param
- Added `getRecipeUserId` to the session class
- ThirdParty:
- The `signInUp` override:
- gets a new `isVerified` param
- can return new status: `SIGN_IN_UP_NOT_ALLOWED`
- `manuallyCreateOrUpdateUser`:
- gets a new `isVerified` param
- can return new statuses: `EMAIL_CHANGE_NOT_ALLOWED_ERROR`, `SIGN_IN_UP_NOT_ALLOWED`
- Removed `getUserByThirdPartyInfo`, `getUsersByEmail`, `getUserById`
- `signInUpPOST` can now return `SIGN_IN_UP_NOT_ALLOWED`
- ThirdPartyEmailPassword:
- Removed `getUserByThirdPartyInfo`, `getUsersByEmail`, `getUserById`
- `thirdPartyManuallyCreateOrUpdateUser`:
- now get a new `isVerified` param
- can return new statuses: `EMAIL_CHANGE_NOT_ALLOWED_ERROR`, `SIGN_IN_UP_NOT_ALLOWED`
- The `thirdPartySignInUp` override:
- now get a new `isVerified` param
- can return new status: `SIGN_IN_UP_NOT_ALLOWED`
- `email` was added to the input of `createResetPasswordToken` , `sendResetPasswordEmail`, `createResetPasswordLink`
- added an overrideable `createNewEmailPasswordRecipeUser` function that is called during email password sign up and in the “invitation link” flow
- added `consumePasswordResetToken`
- `updateEmailOrPassword` :
- now takes `recipeUserId` instead of `userId`
- can return the new `EMAIL_CHANGE_NOT_ALLOWED_ERROR` status
- added an overrideable `createNewEmailPasswordRecipeUser` function that is called during sign up and in the “invitation link” flow
- `emailPasswordSignIn`:
- returns new `recipeUserId` prop in the `status: OK` case
- `emailPasswordSignUp`:
- returns new `recipeUserId` prop in the `status: OK` case
- `emailPasswordSignInPOST`:
- can return status `SIGN_IN_NOT_ALLOWED`
- `emailPasswordSignUpPOST`:
- can return status `SIGN_UP_NOT_ALLOWED`
- `generatePasswordResetTokenPOST`:
- can now return `PASSWORD_RESET_NOT_ALLOWED`
- `passwordResetPOST`:
- now returns the `user` and the `email` whose password was reset
- can now return `PASSWORD_POLICY_VIOLATED_ERROR`
- `thirdPartySignInUpPOST` can now return `SIGN_IN_UP_NOT_ALLOWED`
- ThirdPartyPasswordless:
- Removed `getUserByThirdPartyInfo`, `getUsersByEmail`, `getUserByPhoneNumber`, `getUserById`
- `thirdPartyManuallyCreateOrUpdateUser`:
- gets a new `isVerified` param
- can return new statuses: `EMAIL_CHANGE_NOT_ALLOWED_ERROR`, `SIGN_IN_UP_NOT_ALLOWED`
- The `thirdPartySignInUp` override:
- gets a new `isVerified` param
- can return new status: `SIGN_IN_UP_NOT_ALLOWED`
- `updatePasswordlessUser`:
- now takes `recipeUserId` instead of `userId`
- can return `"EMAIL_CHANGE_NOT_ALLOWED_ERROR` and `PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR` statuses
- `thirdPartySignInUpPOST` can now return `SIGN_IN_UP_NOT_ALLOWED`
- `createCodePOST` and `consumeCodePOST` can now return `SIGN_IN_UP_NOT_ALLOWED`
- Multitenancy:
- `associateUserToTenant` can now return `ASSOCIATION_NOT_ALLOWED_ERROR`
- `associateUserToTenant` and `disassociateUserFromTenant` now take `RecipeUserId` instead of a string user id

### Changes

- Added `RecipeUserId` and a generic `User` class
- Added `getUser`, `listUsersByAccountInfo`, `convertToRecipeUserId` to the main exports
- Updated compilation target of typescript to ES2017 to make debugging easier.
- Added account-linking recipe

### Migration guide

#### New User structure

We've added a generic `User` class instead of the old recipe specific ones. The mapping of old props to new in case you are not using account-linking:

- `user.id` stays `user.id` (or `user.loginMethods[0].recipeUserId` in case you need `RecipeUserId`)
- `user.email` becomes `user.emails[0]`
- `user.phoneNumber` becomes `user.phoneNumbers[0]`
- `user.thirdParty` becomes `user.thirdParty[0]`
- `user.timeJoined` is still `user.timeJoined`
- `user.tenantIds` is still `user.tenantIds`

#### RecipeUserId

Some functions now require you to pass a `RecipeUserId` instead of a string user id. If you are using our auth recipes, you can find the recipeUserId as: `user.loginMethods[0].recipeUserId` (you'll need to worry about selecting the right login method after enabling account linking). Alternatively, if you already have a string user id you can convert it to a `RecipeUserId` using `supertokens.convertToRecipeUserId(userIdString)`

#### Checking if a user signed up or signed in

- In the passwordless consumeCode / social login signinup APIs, you can check if a user signed up by:

```
// Here res refers to the result the function/api functions mentioned above.
const isNewUser = res.createdNewRecipeUser && res.user.loginMethods.length === 1;
```

- In the emailpassword sign up API, you can check if a user signed up by:

```
const isNewUser = res.user.loginMethods.length === 1;
```

#### Changing user emails

- We recommend that you check if the email change of a user is allowed, before calling the update function
- Check [here](https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/change-email-post-login) for more information

```
import {isEmailChangeAllowed} from "supertokens-node/recipe/accountlinking";
/// ...
app.post("/change-email", verifySession(), async (req: SessionRequest, res: express.Response) => {
let session = req.session!;
let email = req.body.email;

// ...
if (!(await isEmailChangeAllowed(session.getRecipeUserId(), email, false))) {
// this can come here if you have enabled the account linking feature, and
// if there is a security risk in changing this user's email.
}

// Update the email
let resp = await ThirdPartyEmailPassword.updateEmailOrPassword({
recipeUserId: session.getRecipeUserId(),
email: email,
});
// ...
});
```

Copy link
Contributor

Choose a reason for hiding this comment

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

Need to have a section on frontend / core migration needed - that these are the versions of the frontend and core.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The supported FE version didn't change if you are not using account linking, and the core is mentioned above. I can add a section/link here pointing to the account linking recipe docs.

## [15.2.0] - 2023-09-11

### Added
Expand Down
2 changes: 1 addition & 1 deletion coreDriverInterfaceSupported.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"_comment": "contains a list of core-driver interfaces branch names that this core supports",
"versions": ["3.0"]
"versions": ["4.0"]
}
1 change: 0 additions & 1 deletion docs/.nojekyll

This file was deleted.

Loading
Loading