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: Refactor app info type to allow adding multiple website domains #706

Merged
merged 35 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
705205a
Update type for website domain in app info
nkshah2 Sep 26, 2023
60f3a7d
Convert topLevelWebsiteDomain to a function
nkshah2 Sep 26, 2023
d0503e9
Convert cookie same site into a function
nkshah2 Sep 26, 2023
5c92815
Rename original request to request
nkshah2 Sep 29, 2023
e80ec8e
Merge branch '16.2' into appinfo-refactor
nkshah2 Sep 29, 2023
3d5372f
Merge branch '16.2' into appinfo-refactor
nkshah2 Sep 29, 2023
2228388
Update existing tests
nkshah2 Sep 29, 2023
6ae4467
Add request and user context in topLevelWebsiteDomain and CookieSameSite
nkshah2 Sep 29, 2023
f749956
Add request and user context in topLevelWebsiteDomain and CookieSameSite
nkshah2 Sep 29, 2023
3a37007
Rename app info properties
nkshah2 Oct 4, 2023
73b8737
Rename app info properties
nkshah2 Oct 4, 2023
fc5300f
Rename session recipe normalise config properties
nkshah2 Oct 4, 2023
fd7defd
Add origin to app info input type
nkshah2 Oct 4, 2023
b521e07
Merge branch '16.2' into appinfo-refactor
nkshah2 Oct 6, 2023
4ba93ac
Convert anticsrf to function
nkshah2 Oct 9, 2023
21b1826
Refactor based on PR comments
nkshah2 Oct 9, 2023
340fb5c
Add request and user context when clearing tokens
nkshah2 Oct 9, 2023
653fedf
Refactor debug logs
nkshah2 Oct 9, 2023
fbd9645
Rename anti csrf
nkshah2 Oct 9, 2023
e70667a
Refactor based on PR comments
nkshah2 Oct 9, 2023
d896dc5
Refactor analytics API
nkshah2 Oct 9, 2023
db21d5e
Refactor getEmailVerifyLink
nkshah2 Oct 9, 2023
814d865
Refactor getPasswordResetLink
nkshah2 Oct 9, 2023
75afe74
Refactor createMagicLink
nkshah2 Oct 9, 2023
d40e848
Refactor utils
nkshah2 Oct 9, 2023
5eed059
Refactor based on PR review
nkshah2 Oct 9, 2023
5bc7f67
Update based on a PR review
nkshah2 Oct 10, 2023
800b6a0
Add ocnfig tests
nkshah2 Oct 10, 2023
02e288c
Add test for reset password
nkshah2 Oct 10, 2023
42cf7b2
Add test for email verify
nkshah2 Oct 10, 2023
695fc8b
Add test for passwordless email
nkshah2 Oct 10, 2023
5a46cc5
Add test for token transfer method
nkshah2 Oct 10, 2023
d599072
Fix and update existing tests
nkshah2 Oct 10, 2023
d226203
Merge branch '16.3' into appinfo-refactor
rishabhpoddar Oct 10, 2023
8e477ec
Update version and CHANGELOG
nkshah2 Oct 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/build/framework/awsLambda/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ const middleware = (handler) => {
});
return response.sendResponse();
} catch (err) {
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
if (response.responseSet) {
return response.sendResponse();
}
Expand Down
5 changes: 3 additions & 2 deletions lib/build/framework/express/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ const middleware = () => {
} catch (err) {
if (supertokens) {
try {
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
} catch (_a) {
next(err);
}
Expand All @@ -156,8 +156,9 @@ const errorHandler = () => {
let supertokens = supertokens_1.default.getInstanceOrThrowError();
let request = new ExpressRequest(req);
let response = new ExpressResponse(res);
const userContext = utils_1.makeDefaultUserContextFromAPI(request);
try {
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
} catch (err) {
return next(err);
}
Expand Down
5 changes: 3 additions & 2 deletions lib/build/framework/fastify/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ function plugin(fastify, _, done) {
try {
await supertokens.middleware(request, response, userContext);
} catch (err) {
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
}
});
done();
Expand All @@ -183,7 +183,8 @@ const errorHandler = () => {
let supertokens = supertokens_1.default.getInstanceOrThrowError();
let request = new FastifyRequest(req);
let response = new FastifyResponse(res);
await supertokens.errorHandler(err, request, response);
let userContext = utils_1.makeDefaultUserContextFromAPI(request);
await supertokens.errorHandler(err, request, response, userContext);
};
};
exports.errorHandler = errorHandler;
Expand Down
3 changes: 2 additions & 1 deletion lib/build/framework/hapi/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,10 @@ const plugin = {
let err = request.response.data || request.response;
let req = new HapiRequest(request);
let res = new HapiResponse(h);
const userContext = utils_1.makeDefaultUserContextFromAPI(req);
if (err !== undefined && err !== null) {
try {
await supertokens.errorHandler(err, req, res);
await supertokens.errorHandler(err, req, res, userContext);
if (res.responseSet) {
let resObj = res.sendResponse(true);
(request.app.lazyHeaders || []).forEach(({ key, value, allowDuplicateKey }) => {
Expand Down
2 changes: 1 addition & 1 deletion lib/build/framework/koa/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const middleware = () => {
return await next();
}
} catch (err) {
return await supertokens.errorHandler(err, request, response);
return await supertokens.errorHandler(err, request, response, userContext);
}
};
};
Expand Down
2 changes: 1 addition & 1 deletion lib/build/framework/loopback/framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const middleware = async (ctx, next) => {
}
return;
} catch (err) {
return await supertokens.errorHandler(err, request, response);
return await supertokens.errorHandler(err, request, response, userContext);
}
};
exports.middleware = middleware;
Expand Down
7 changes: 5 additions & 2 deletions lib/build/recipe/dashboard/api/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ async function analyticsPost(_, ___, options, __) {
status: "OK",
};
}
const { apiDomain, websiteDomain, appName } = options.appInfo;
const { apiDomain, getOrigin: websiteDomain, appName } = options.appInfo;
const data = {
websiteDomain: websiteDomain.getAsStringDangerous(),
websiteDomain: websiteDomain({
request: undefined,
userContext: {},
}).getAsStringDangerous(),
apiDomain: apiDomain.getAsStringDangerous(),
appName,
sdk: "node",
Expand Down
2 changes: 2 additions & 0 deletions lib/build/recipe/emailpassword/api/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ function getAPIImplementation() {
token: response.token,
recipeId: options.recipeId,
tenantId,
request: options.req,
userContext,
});
logger_1.logDebugMessage(`Sending password reset email to ${email}`);
await options.emailDelivery.ingredientInterfaceImpl.sendEmail({
Expand Down
2 changes: 2 additions & 0 deletions lib/build/recipe/emailpassword/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class Wrapper {
recipeId: recipeInstance.getRecipeId(),
token: token.token,
tenantId: tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId,
request: __1.getRequestFromUserContext(userContext),
userContext,
}),
};
}
Expand Down
3 changes: 3 additions & 0 deletions lib/build/recipe/emailpassword/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Recipe from "./recipe";
import { TypeInput, TypeNormalisedInput, NormalisedFormField, TypeInputFormField } from "./types";
import { NormalisedAppinfo } from "../../types";
import { BaseRequest } from "../../framework";
export declare function validateAndNormaliseUserInput(
recipeInstance: Recipe,
appInfo: NormalisedAppinfo,
Expand All @@ -26,4 +27,6 @@ export declare function getPasswordResetLink(input: {
token: string;
recipeId: string;
tenantId: string;
request: BaseRequest | undefined;
userContext: any;
}): string;
7 changes: 6 additions & 1 deletion lib/build/recipe/emailpassword/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,12 @@ async function defaultEmailValidator(value) {
exports.defaultEmailValidator = defaultEmailValidator;
function getPasswordResetLink(input) {
return (
input.appInfo.websiteDomain.getAsStringDangerous() +
input.appInfo
.getOrigin({
request: input.request,
userContext: input.userContext,
})
.getAsStringDangerous() +
input.appInfo.websiteBasePath.getAsStringDangerous() +
"/reset-password?token=" +
input.token +
Expand Down
2 changes: 2 additions & 0 deletions lib/build/recipe/emailverification/api/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ function getAPIInterface() {
token: response.token,
recipeId: options.recipeId,
tenantId,
request: options.req,
userContext,
});
logger_1.logDebugMessage(`Sending email verification email to ${emailInfo}`);
await options.emailDelivery.ingredientInterfaceImpl.sendEmail({
Expand Down
3 changes: 3 additions & 0 deletions lib/build/recipe/emailverification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const recipe_1 = __importDefault(require("./recipe"));
const error_1 = __importDefault(require("./error"));
const emailVerificationClaim_1 = require("./emailVerificationClaim");
const utils_1 = require("./utils");
const __1 = require("../..");
class Wrapper {
static async createEmailVerificationToken(tenantId, recipeUserId, email, userContext = {}) {
const recipeInstance = recipe_1.default.getInstanceOrThrowError();
Expand Down Expand Up @@ -67,6 +68,8 @@ class Wrapper {
token: emailVerificationToken.token,
recipeId: recipeInstance.getRecipeId(),
tenantId,
request: __1.getRequestFromUserContext(userContext),
userContext,
}),
};
}
Expand Down
3 changes: 3 additions & 0 deletions lib/build/recipe/emailverification/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Recipe from "./recipe";
import { TypeInput, TypeNormalisedInput } from "./types";
import { NormalisedAppinfo } from "../../types";
import { BaseRequest } from "../../framework";
export declare function validateAndNormaliseUserInput(
_: Recipe,
appInfo: NormalisedAppinfo,
Expand All @@ -12,4 +13,6 @@ export declare function getEmailVerifyLink(input: {
token: string;
recipeId: string;
tenantId: string;
request: BaseRequest | undefined;
userContext: any;
}): string;
7 changes: 6 additions & 1 deletion lib/build/recipe/emailverification/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ function validateAndNormaliseUserInput(_, appInfo, config) {
exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput;
function getEmailVerifyLink(input) {
return (
input.appInfo.websiteDomain.getAsStringDangerous() +
input.appInfo
.getOrigin({
request: input.request,
userContext: input.userContext,
})
.getAsStringDangerous() +
input.appInfo.websiteBasePath.getAsStringDangerous() +
"/verify-email" +
"?token=" +
Expand Down
14 changes: 12 additions & 2 deletions lib/build/recipe/passwordless/api/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,12 @@ function getAPIImplementation() {
const flowType = input.options.config.flowType;
if (flowType === "MAGIC_LINK" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") {
magicLink =
input.options.appInfo.websiteDomain.getAsStringDangerous() +
input.options.appInfo
.getOrigin({
request: input.options.req,
userContext: input.userContext,
})
.getAsStringDangerous() +
input.options.appInfo.websiteBasePath.getAsStringDangerous() +
"/verify" +
"?rid=" +
Expand Down Expand Up @@ -354,7 +359,12 @@ function getAPIImplementation() {
const flowType = input.options.config.flowType;
if (flowType === "MAGIC_LINK" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") {
magicLink =
input.options.appInfo.websiteDomain.getAsStringDangerous() +
input.options.appInfo
.getOrigin({
request: input.options.req,
userContext: input.userContext,
})
.getAsStringDangerous() +
input.options.appInfo.websiteBasePath.getAsStringDangerous() +
"/verify" +
"?rid=" +
Expand Down
2 changes: 2 additions & 0 deletions lib/build/recipe/passwordless/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.sendSms = exports.sendEmail = exports.signInUp = exports.createMagicLink = exports.revokeCode = exports.revokeAllCodes = exports.updateUser = exports.createNewCodeForDevice = exports.listCodesByPreAuthSessionId = exports.listCodesByPhoneNumber = exports.listCodesByEmail = exports.listCodesByDeviceId = exports.consumeCode = exports.createCode = exports.Error = exports.init = void 0;
const recipe_1 = __importDefault(require("./recipe"));
const error_1 = __importDefault(require("./error"));
const __1 = require("../..");
class Wrapper {
static createCode(input) {
var _a;
Expand Down Expand Up @@ -104,6 +105,7 @@ class Wrapper {
var _a;
return recipe_1.default.getInstanceOrThrowError().createMagicLink(
Object.assign(Object.assign({}, input), {
request: __1.getRequestFromUserContext(input.userContext),
userContext: (_a = input.userContext) !== null && _a !== void 0 ? _a : {},
})
);
Expand Down
2 changes: 2 additions & 0 deletions lib/build/recipe/passwordless/recipe.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ export default class Recipe extends RecipeModule {
| {
email: string;
tenantId: string;
request: BaseRequest | undefined;
userContext?: any;
}
| {
phoneNumber: string;
tenantId: string;
request: BaseRequest | undefined;
userContext?: any;
}
) => Promise<string>;
Expand Down
7 changes: 6 additions & 1 deletion lib/build/recipe/passwordless/recipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,12 @@ class Recipe extends recipeModule_1.default {
);
const appInfo = this.getAppInfo();
let magicLink =
appInfo.websiteDomain.getAsStringDangerous() +
appInfo
.getOrigin({
request: input.request,
userContext: input.userContext,
})
.getAsStringDangerous() +
appInfo.websiteBasePath.getAsStringDangerous() +
"/verify" +
"?rid=" +
Expand Down
19 changes: 15 additions & 4 deletions lib/build/recipe/session/cookieAndHeaders.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
// @ts-nocheck
import type { BaseRequest, BaseResponse } from "../../framework";
import { TokenTransferMethod, TokenType, TypeNormalisedInput } from "./types";
export declare function clearSessionFromAllTokenTransferMethods(config: TypeNormalisedInput, res: BaseResponse): void;
export declare function clearSessionFromAllTokenTransferMethods(
config: TypeNormalisedInput,
res: BaseResponse,
request: BaseRequest | undefined,
userContext: any
): void;
export declare function clearSession(
config: TypeNormalisedInput,
res: BaseResponse,
transferMethod: TokenTransferMethod
transferMethod: TokenTransferMethod,
request: BaseRequest | undefined,
userContext: any
): void;
export declare function getAntiCsrfTokenFromHeaders(req: BaseRequest): string | undefined;
export declare function setAntiCsrfTokenInHeaders(res: BaseResponse, antiCsrfToken: string): void;
Expand All @@ -23,7 +30,9 @@ export declare function setToken(
tokenType: TokenType,
value: string,
expires: number,
transferMethod: TokenTransferMethod
transferMethod: TokenTransferMethod,
req: BaseRequest | undefined,
userContext: any
): void;
export declare function setHeader(res: BaseResponse, name: string, value: string): void;
/**
Expand All @@ -43,6 +52,8 @@ export declare function setCookie(
name: string,
value: string,
expires: number,
pathType: "refreshTokenPath" | "accessTokenPath"
pathType: "refreshTokenPath" | "accessTokenPath",
req: BaseRequest | undefined,
userContext: any
): void;
export declare function getAuthModeFromHeader(req: BaseRequest): string | undefined;
21 changes: 13 additions & 8 deletions lib/build/recipe/session/cookieAndHeaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ const refreshTokenHeaderKey = "st-refresh-token";
const antiCsrfHeaderKey = "anti-csrf";
const frontTokenHeaderKey = "front-token";
const authModeHeaderKey = "st-auth-mode";
function clearSessionFromAllTokenTransferMethods(config, res) {
function clearSessionFromAllTokenTransferMethods(config, res, request, userContext) {
// We are clearing the session in all transfermethods to be sure to override cookies in case they have been already added to the response.
// This is done to handle the following use-case:
// If the app overrides signInPOST to check the ban status of the user after the original implementation and throwing an UNAUTHORISED error
// In this case: the SDK has attached cookies to the response, but none was sent with the request
// We can't know which to clear since we can't reliably query or remove the set-cookie header added to the response (causes issues in some frameworks, i.e.: hapi)
// The safe solution in this case is to overwrite all the response cookies/headers with an empty value, which is what we are doing here
for (const transferMethod of constants_2.availableTokenTransferMethods) {
clearSession(config, res, transferMethod);
clearSession(config, res, transferMethod, request, userContext);
}
}
exports.clearSessionFromAllTokenTransferMethods = clearSessionFromAllTokenTransferMethods;
function clearSession(config, res, transferMethod) {
function clearSession(config, res, transferMethod, request, userContext) {
// If we can be specific about which transferMethod we want to clear, there is no reason to clear the other ones
const tokenTypes = ["access", "refresh"];
for (const token of tokenTypes) {
setToken(config, res, token, "", 0, transferMethod);
setToken(config, res, token, "", 0, transferMethod, request, userContext);
}
res.removeHeader(antiCsrfHeaderKey);
// This can be added multiple times in some cases, but that should be OK
Expand Down Expand Up @@ -111,7 +111,7 @@ function getToken(req, tokenType, transferMethod) {
}
}
exports.getToken = getToken;
function setToken(config, res, tokenType, value, expires, transferMethod) {
function setToken(config, res, tokenType, value, expires, transferMethod, req, userContext) {
logger_1.logDebugMessage(`setToken: Setting ${tokenType} token as ${transferMethod}`);
if (transferMethod === "cookie") {
setCookie(
Expand All @@ -120,7 +120,9 @@ function setToken(config, res, tokenType, value, expires, transferMethod) {
getCookieNameFromTokenType(tokenType),
value,
expires,
tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath"
tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath",
req,
userContext
);
} else if (transferMethod === "header") {
setHeader(res, getResponseHeaderNameForTokenType(tokenType), value);
Expand All @@ -143,10 +145,13 @@ exports.setHeader = setHeader;
* @param expires
* @param path
*/
function setCookie(config, res, name, value, expires, pathType) {
function setCookie(config, res, name, value, expires, pathType, req, userContext) {
let domain = config.cookieDomain;
let secure = config.cookieSecure;
let sameSite = config.cookieSameSite;
let sameSite = config.getCookieSameSite({
request: req,
userContext,
});
let path = "";
if (pathType === "refreshTokenPath") {
path = config.refreshTokenPath.getAsStringDangerous();
Expand Down
2 changes: 1 addition & 1 deletion lib/build/recipe/session/framework/awsLambda.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function verifySession(handler, verifySessionOptions) {
let handlerResult = await handler(event, context, callback);
return response.sendResponse(handlerResult);
} catch (err) {
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
if (response.responseSet) {
return response.sendResponse({});
}
Expand Down
2 changes: 1 addition & 1 deletion lib/build/recipe/session/framework/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function verifySession(options) {
} catch (err) {
try {
const supertokens = supertokens_1.default.getInstanceOrThrowError();
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
} catch (_a) {
next(err);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/build/recipe/session/framework/fastify.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function verifySession(options) {
req.session = await sessionRecipe.verifySession(options, request, response, userContext);
} catch (err) {
const supertokens = supertokens_1.default.getInstanceOrThrowError();
await supertokens.errorHandler(err, request, response);
await supertokens.errorHandler(err, request, response, userContext);
throw err;
}
};
Expand Down
Loading
Loading