Skip to content

Commit a8024d3

Browse files
porcellusMihaly Lengyelrishabhpoddar
authored
feat(sessiongrants): add support for session grants (#278)
* feat(sessiongrants): define types and add some implementation for session grants * refactor(sessiongrants): implement interface related feedback * refactor(sesssiongrants): renamed to claims * refactor(sessionclaims): implementing review feedback + cleanup * feat(sessiongrants): updated claims interface & fixes * refactor(sessiongrants): updating the interface WIP * refactor: review feedback + merge updates * feat: implementing review feedback * feat(sessionclaims): implementing interface feedback + initial tests * feat(sessionclaims): add claim management funcs to session * feat(sessionclaims): remove separate session claims field from AT * fix(sessionclaims): add missing await to fix applyClaimBuilder * feat(sessionclaims): implementing review feedback * feat(sessionclaims): implementing review feedback * feat(sessionclaims): implementing review feedback * refactor(sessionclaims): review feedback * feat(sessionclaims): review changes + exporting missing functions * feat: review feedback * feat: clarifications/minor improvements + further testing * refactor: change getLastRefetchTime to return raw number instead of Date * feat(sessionclaims): review feedback * test(sessionclaims): add removeClaim and fetchAndSetClaim tests * refactor(sessionclaims): added debug log after session claims assertion * feat: move claim assertion out of getSession * feat: add isTrue and isFalse validators * feat: review feedback * feat: initial (untested) implementation for email verification claims * fix(sessionclaims): fix circular dep error * fix(sessionclaims): add missing initializer for bootstrap callback list * test(sessionclaims): remove test of deleted module * refactor(sessionclaims): renamed parameter to fit existing terminology * feat: review feedback (#350) * refactor(sessionclaims): further review feedback * test(sessionclaims): add tests for session handle methods + extend tests * refactor: rename removeFromPayload + fix value type of PrimitiveClaim * feat(sessionclaims): implement review feedback * refactor(sessionclaims): finished renaming EmailVerifiedClaim * feat(sessionclaims): implement review feedback * feat(sessionclaims): mark passwordless users as validated * fix(sessionclaims): add missing await * test(sessionclaims): remove unused test code * fix(sessionclaims): self-review fix * feat(sessionclaims): review feedback * feat(sessionclaims): review feedback (#352) * feat(sessionclaims): make validators return only promises * refactor(sessionclaims): check expiration first in primitive claims * refactor(sessionclaims): throw on duplicate claims added by recipes * test(sessionclaims): update tests for async validators * feat(sessionclaims): make getClaimValue non-throwing * feat(sessionclaims): adding claim validation functions to session recipe * feat(sessionclaims): implement review feedback * feat(sessionclaims): review feedback * test(sessionclaims): update tests (#356) * fix(sessionclaims): fix updating claims * feat(sessionclaims): make the email param optional in user facing emailverification methods * test(sessionclaims): update/fix tests * refactor(sessionclaims): removed unnecessary if + console log * feat(sessionclaims): remove console log * feat(sessionclaims): add roles claim and primitive array claim (#357) * feat(sessionclaims): add roles claim and primitive array claim to support * feat(sessionclaims): removed strictEquals * chore: update changelog (#358) * chore(sessionclaims): update changelog * chore: add update instruction to changelog * Update CHANGELOG.md * Update CHANGELOG.md Co-authored-by: Rishabh Poddar <[email protected]> * feat(sessionclaims): add request to default usercontext of verifySession (#361) * refactor to session recipe to remove extra assertClaims (#366) * refactor to session recipe to remove extra assertClaims * feat: review feedback + test fixing * test: updated test after the merge * feat: fix updateAccessTokenPayload param type Co-authored-by: Mihaly Lengyel <[email protected]> * Fixes to session grants base branch (#369) * fixes to emaildelivery import from emailverification reicpe * fixes issue with emailverification function TS * fixes typo in SMTP service * feat(sessionclaims): review feedback (#370) * feat(sessionclaims): review feedback * refactor: added missing id override to boolean claim validators * adds session object as input / output to some of the api functions in session recipe (#371) * fix: fix the returned status of revokeEmailVerificationTokens for pwless users (#372) * fix: fix the returned status of revokeEmailVerificationTokens for pwless users * test: test revokeEmailVerificationTokens when getEmailForUserId returns an error * Signinup function cleanup (#373) * removes unnecessary param in signInUp function * fixes tests * fixes more tests * fix: passing changelog in emailverification api + added migration for passwordless-emailverification into changelog * feat: refetch email verified claim based on maxAgeInSeconds (5 min default) (#378) * fix: check and throw if sessionExpiredStatusCode == invalidClaimStatusCode * chore: update changelog to mention changed integration and role guides * fix: fix type issues from review comments * fix: make userContext non-optional in recipe interface method inputs * chore: updated supported fdi version * test: fix tests Co-authored-by: Mihaly Lengyel <[email protected]> Co-authored-by: Rishabh Poddar <[email protected]>
1 parent 9dc46ce commit a8024d3

File tree

265 files changed

+8648
-5096
lines changed

Some content is hidden

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

265 files changed

+8648
-5096
lines changed

CHANGELOG.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,182 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [unreleased]
99

10+
### Changed
11+
12+
- Made the `email` parameter option in `unverifyEmail`, `revokeEmailVerificationTokens`, `isEmailVerified`, `verifyEmailUsingToken`, `createEmailVerificationToken` of the `EmailVerification` recipe.
13+
14+
### Added
15+
16+
- Added support for session claims with related interfaces and classes.
17+
- Added `onInvalidClaim` optional error handler to send InvalidClaim error responses.
18+
- Added `INVALID_CLAIMS` to `SessionErrors`.
19+
- Added `invalidClaimStatusCode` optional config to set the status code of InvalidClaim errors.
20+
- Added `overrideGlobalClaimValidators` to options of `getSession` and `verifySession`.
21+
- Added `mergeIntoAccessTokenPayload` to the Session recipe and session objects which should be preferred to the now deprecated `updateAccessTokenPayload`.
22+
- Added `EmailVerificationClaim`, `UserRoleClaim` and `PermissionClaim`. These claims are now added to the access token payload by default by their respective recipes.
23+
- Added `assertClaims`, `validateClaimsForSessionHandle`, `validateClaimsInJWTPayload` to the Session recipe to support validation of the newly added claims.
24+
- Added `fetchAndSetClaim`, `getClaimValue`, `setClaimValue` and `removeClaim` to the Session recipe to manage claims.
25+
- Added `assertClaims`, `fetchAndSetClaim`, `getClaimValue`, `setClaimValue` and `removeClaim` to session objects to manage claims.
26+
- Added session to the input of `generateEmailVerifyTokenPOST`, `verifyEmailPOST`, `isEmailVerifiedGET`.
27+
- Adds default userContext for verifySession calls that contains the request object.
28+
29+
### Breaking changes
30+
31+
- Changed `signInUp` third party recipe function to accept an email string instead of an object that takes `{id: string, isVerified: boolean}`.
32+
- Renames `STMP` to `SMTP` everywhere (typo).
33+
- The frontend SDK should be updated to a version supporting session claims!
34+
- supertokens-auth-react: >= 0.25.0
35+
- supertokens-web-js: >= 0.2.0
36+
- `EmailVerification` recipe is now not initialized as part of auth recipes, it should be added to the `recipeList` directly instead.
37+
- Email verification related overrides (`emailVerificationFeature` prop of `override`) moved from auth recipes into the `EmailVerification` recipe config.
38+
- Email verificitaion related configs (`emailVerificationFeature` props) moved from auth recipes into the `EmailVerification` config object root.
39+
- ThirdParty recipe no longer takes emailDelivery config -> use emailverification recipe's emailDelivery instead.
40+
- Moved email verification related configs from the `emailDelivery` config of auth recipes into a separate `EmailVerification` email delivery config.
41+
- Updated return type of `getEmailForUserId` in the `EmailVerification` recipe config. It should now return an object with status.
42+
- Removed `getResetPasswordURL`, `getEmailVerificationURL`, `getLinkDomainAndPath`. Changing these urls can be done in the email delivery configs instead.
43+
- Removed `unverifyEmail`, `revokeEmailVerificationTokens`, `isEmailVerified`, `verifyEmailUsingToken` and `createEmailVerificationToken` from auth recipes. These should be called on the `EmailVerification` recipe instead.
44+
- Changed function signature for email verification APIs to accept a session as an input.
45+
- Changed Session API interface functions:
46+
- `refreshPOST` now returns a Session container object.
47+
- `signOutPOST` now takes in an optional session object as a parameter.
48+
49+
### Migration
50+
51+
Before:
52+
53+
```
54+
SuperTokens.init({
55+
appInfo: {
56+
apiDomain: "...",
57+
appName: "...",
58+
websiteDomain: "...",
59+
},
60+
recipeList: [
61+
EmailPassword.init({
62+
emailVerificationFeature: {
63+
// these options should be moved into the config of the EmailVerification recipe
64+
},
65+
override: {
66+
emailVerificationFeature: {
67+
// these overrides should be moved into the overrides of the EmailVerification recipe
68+
}
69+
}
70+
})
71+
]
72+
})
73+
```
74+
75+
After the update:
76+
77+
```
78+
SuperTokens.init({
79+
appInfo: {
80+
apiDomain: "...",
81+
appName: "...",
82+
websiteDomain: "...",
83+
},
84+
recipeList: [
85+
EmailVerification.init({
86+
// all config should be moved here from the emailVerificationFeature prop of the EmailPassword recipe config
87+
override: {
88+
// move the overrides from the emailVerificationFeature prop of the override config in the EmailPassword init here
89+
}
90+
}),
91+
EmailPassword.init()
92+
]
93+
})
94+
```
95+
96+
#### Passwordless users and email verification
97+
98+
If you turn on email verification your email-based passwordless users may be redirected to an email verification screen in their existing session.
99+
Logging out and logging in again will solve this problem or they could click the link in the email to verify themselves.
100+
101+
You can avoid this by running a script that will:
102+
103+
1. list all users of passwordless
104+
2. create an emailverification token for each of them if they have email addresses
105+
3. user the token to verify their address
106+
107+
Something similar to this script:
108+
109+
```ts
110+
const SuperTokens = require("supertokens-node");
111+
const Session = require("supertokens-node/recipe/session");
112+
const Passwordless = require("supertokens-node/recipe/passwordless");
113+
const EmailVerification = require("supertokens-node/recipe/emailverification");
114+
115+
SuperTokens.init({
116+
supertokens: {
117+
// TODO: This is a core hosted for demo purposes. You can use this, but make sure to change it to your core instance URI eventually.
118+
connectionURI: "https://try.supertokens.com",
119+
apiKey: "<REQUIRED FOR MANAGED SERVICE, ELSE YOU CAN REMOVE THIS FIELD>",
120+
},
121+
appInfo: {
122+
apiDomain: "...",
123+
appName: "...",
124+
websiteDomain: "...",
125+
},
126+
recipeList: [
127+
EmailVerification.init({
128+
mode: "REQUIRED",
129+
}),
130+
Passwordless.init({
131+
contactMethod: "EMAIL_OR_PHONE",
132+
flowType: "USER_INPUT_CODE_AND_MAGIC_LINK",
133+
}),
134+
Session.init(),
135+
],
136+
});
137+
138+
async function main() {
139+
let paginationToken = undefined;
140+
let done = false;
141+
while (!done) {
142+
const userList = await SuperTokens.getUsersNewestFirst({
143+
includeRecipeIds: ["passwordless"],
144+
limit: 100,
145+
paginationToken,
146+
});
147+
148+
for (const { recipeId, user } of userList.users) {
149+
if (recipeId === "passwordless" && user.email) {
150+
const tokenResp = await EmailVerification.createEmailVerificationToken(user.id, user.email);
151+
if (tokenResp.status === "OK") {
152+
await EmailVerification.verifyEmailUsingToken(tokenResp.token);
153+
}
154+
}
155+
}
156+
157+
done = userList.nextPaginationToken !== undefined;
158+
if (!done) {
159+
paginationToken = userList.nextPaginationToken;
160+
}
161+
}
162+
}
163+
164+
main().then(console.log, console.error);
165+
```
166+
167+
#### User roles
168+
169+
The UserRoles recipe now adds role and permission information into the access token payload by default. If you are already doing this manually, this will result in duplicate data in the access token.
170+
171+
- You can disable this behaviour by setting `skipAddingRolesToAccessToken` and `skipAddingPermissionsToAccessToken` to true in the recipe init.
172+
- Check how to use the new claims in the updated guide: https://supertokens.com/docs/userroles/protecting-routes
173+
174+
#### Next.js integration
175+
176+
- Since a new exception type has been added, there is a required change in SRR (`getServerSideProps`). You should handle the new (`INVALID_CLAIMS`) exception in the same way as you handle `UNAUTHORISED`
177+
- You can check our updated guide here: https://supertokens.com/docs/thirdpartyemailpassword/nextjs/session-verification/in-ssr
178+
179+
#### AWS integration
180+
181+
- The new exception type and error code requires changes if you are using SuperTokens as as an Authorizer in API Gateways.
182+
- You need to handle the new exception type in the authorizer code.
183+
- You need to configure the "Access Denied" response.
184+
- You can check our updated guide here: https://supertokens.com/docs/thirdpartyemailpassword/serverless/with-aws-lambda/authorizer
185+
10186
## [11.3.0] - 2022-08-30
11187

12188
### Added:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"_comment": "contains a list of frontend-driver interfaces branch names that this core supports",
3-
"versions": ["1.14"]
3+
"versions": ["1.14", "1.15"]
44
}

lib/build/postSuperTokensInitCallbacks.d.ts

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/postSuperTokensInitCallbacks.js

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/recipe/dashboard/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,6 @@ function getApiIdIfMatched(path, method) {
6565
}
6666
exports.getApiIdIfMatched = getApiIdIfMatched;
6767
function sendUnauthorisedAccess(res) {
68-
utils_1.sendNon200Response(res, "Unauthorised access", 401);
68+
utils_1.sendNon200ResponseWithMessage(res, "Unauthorised access", 401);
6969
}
7070
exports.sendUnauthorisedAccess = sendUnauthorisedAccess;

lib/build/recipe/emailpassword/api/implementation.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ function getAPIImplementation() {
6464
};
6565
}
6666
let passwordResetLink =
67-
(yield options.config.resetPasswordUsingTokenFeature.getResetPasswordURL(user, userContext)) +
68-
"?token=" +
67+
options.appInfo.websiteDomain.getAsStringDangerous() +
68+
options.appInfo.websiteBasePath.getAsStringDangerous() +
69+
"/reset-password?token=" +
6970
response.token +
7071
"&rid=" +
7172
options.recipeId;

lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.d.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export default class BackwardCompatibilityService
88
private isInServerlessEnv;
99
private appInfo;
1010
private resetPasswordUsingTokenFeature;
11-
private emailVerificationBackwardCompatibilityService;
1211
constructor(
1312
recipeInterfaceImpl: RecipeInterface,
1413
appInfo: NormalisedAppinfo,
@@ -19,22 +18,11 @@ export default class BackwardCompatibilityService
1918
passwordResetURLWithToken: string,
2019
userContext: any
2120
) => Promise<void>;
22-
},
23-
emailVerificationFeature?: {
24-
createAndSendCustomEmail?: (
25-
user: User,
26-
emailVerificationURLWithToken: string,
27-
userContext: any
28-
) => Promise<void>;
2921
}
3022
);
3123
sendEmail: (
32-
input:
33-
| (import("../../../../emailverification/types").TypeEmailVerificationEmailDeliveryInput & {
34-
userContext: any;
35-
})
36-
| (import("../../../types").TypeEmailPasswordPasswordResetEmailDeliveryInput & {
37-
userContext: any;
38-
})
24+
input: import("../../../types").TypeEmailPasswordPasswordResetEmailDeliveryInput & {
25+
userContext: any;
26+
}
3927
) => Promise<void>;
4028
}

lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.js

Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -32,42 +32,31 @@ var __awaiter =
3232
};
3333
Object.defineProperty(exports, "__esModule", { value: true });
3434
const passwordResetFunctions_1 = require("../../../passwordResetFunctions");
35-
const backwardCompatibility_1 = require("../../../../emailverification/emaildelivery/services/backwardCompatibility");
3635
class BackwardCompatibilityService {
37-
constructor(
38-
recipeInterfaceImpl,
39-
appInfo,
40-
isInServerlessEnv,
41-
resetPasswordUsingTokenFeature,
42-
emailVerificationFeature
43-
) {
36+
constructor(recipeInterfaceImpl, appInfo, isInServerlessEnv, resetPasswordUsingTokenFeature) {
4437
this.sendEmail = (input) =>
4538
__awaiter(this, void 0, void 0, function* () {
46-
if (input.type === "EMAIL_VERIFICATION") {
47-
yield this.emailVerificationBackwardCompatibilityService.sendEmail(input);
48-
} else {
49-
let user = yield this.recipeInterfaceImpl.getUserById({
50-
userId: input.user.id,
51-
userContext: input.userContext,
52-
});
53-
if (user === undefined) {
54-
throw Error("this should never come here");
55-
}
56-
try {
57-
if (!this.isInServerlessEnv) {
58-
this.resetPasswordUsingTokenFeature
59-
.createAndSendCustomEmail(user, input.passwordResetLink, input.userContext)
60-
.catch((_) => {});
61-
} else {
62-
// see https://github.com/supertokens/supertokens-node/pull/135
63-
yield this.resetPasswordUsingTokenFeature.createAndSendCustomEmail(
64-
user,
65-
input.passwordResetLink,
66-
input.userContext
67-
);
68-
}
69-
} catch (_) {}
39+
let user = yield this.recipeInterfaceImpl.getUserById({
40+
userId: input.user.id,
41+
userContext: input.userContext,
42+
});
43+
if (user === undefined) {
44+
throw Error("this should never come here");
7045
}
46+
try {
47+
if (!this.isInServerlessEnv) {
48+
this.resetPasswordUsingTokenFeature
49+
.createAndSendCustomEmail(user, input.passwordResetLink, input.userContext)
50+
.catch((_) => {});
51+
} else {
52+
// see https://github.com/supertokens/supertokens-node/pull/135
53+
yield this.resetPasswordUsingTokenFeature.createAndSendCustomEmail(
54+
user,
55+
input.passwordResetLink,
56+
input.userContext
57+
);
58+
}
59+
} catch (_) {}
7160
});
7261
this.recipeInterfaceImpl = recipeInterfaceImpl;
7362
this.isInServerlessEnv = isInServerlessEnv;
@@ -86,33 +75,6 @@ class BackwardCompatibilityService {
8675
createAndSendCustomEmail: passwordResetFunctions_1.createAndSendCustomEmail(this.appInfo),
8776
};
8877
}
89-
{
90-
const inputCreateAndSendCustomEmail =
91-
emailVerificationFeature === null || emailVerificationFeature === void 0
92-
? void 0
93-
: emailVerificationFeature.createAndSendCustomEmail;
94-
let emailVerificationFeatureNormalisedConfig =
95-
inputCreateAndSendCustomEmail !== undefined
96-
? {
97-
createAndSendCustomEmail: (user, link, userContext) =>
98-
__awaiter(this, void 0, void 0, function* () {
99-
let userInfo = yield this.recipeInterfaceImpl.getUserById({
100-
userId: user.id,
101-
userContext,
102-
});
103-
if (userInfo === undefined) {
104-
throw new Error("Unknown User ID provided");
105-
}
106-
return yield inputCreateAndSendCustomEmail(userInfo, link, userContext);
107-
}),
108-
}
109-
: {};
110-
this.emailVerificationBackwardCompatibilityService = new backwardCompatibility_1.default(
111-
this.appInfo,
112-
this.isInServerlessEnv,
113-
emailVerificationFeatureNormalisedConfig.createAndSendCustomEmail
114-
);
115-
}
11678
}
11779
}
11880
exports.default = BackwardCompatibilityService;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// @ts-nocheck
22
import SMTP from "./smtp";
3-
export declare let STMPService: typeof SMTP;
3+
export declare let SMTPService: typeof SMTP;

lib/build/recipe/emailpassword/emaildelivery/services/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
*/
1616
Object.defineProperty(exports, "__esModule", { value: true });
1717
const smtp_1 = require("./smtp");
18-
exports.STMPService = smtp_1.default;
18+
exports.SMTPService = smtp_1.default;

0 commit comments

Comments
 (0)