Skip to content

Commit

Permalink
test: add tests for custom framework
Browse files Browse the repository at this point in the history
  • Loading branch information
porcellus committed Oct 10, 2023
1 parent efea64d commit 5874da6
Show file tree
Hide file tree
Showing 2 changed files with 255 additions and 41 deletions.
193 changes: 193 additions & 0 deletions test/framework/custom.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
const { printPath, setupST, startST, killAllST, cleanST, extractInfoFromResponse } = require("../utils");
let assert = require("assert");
let { ProcessState, PROCESS_STATE } = require("../../lib/build/processState");
let SuperTokens = require("../..");
let CustomFramework = require("../../framework/custom");
let Session = require("../../recipe/session");
let { verifySession } = require("../../recipe/session/framework/custom");

describe(`Custom framework: ${printPath("[test/framework/custom.test.js]")}`, function () {
beforeEach(async function () {
await killAllST();
await setupST();
ProcessState.getInstance().reset();
});

afterEach(async function () {
try {
await this.server.close();
} catch (err) {}
});
after(async function () {
await killAllST();
await cleanST();
});

// - check if session verify middleware responds with a nice error even without the global error handler
it("test session verify middleware without error handler added", async function () {
const connectionURI = await startST();
SuperTokens.init({
framework: "custom",
supertokens: {
connectionURI,
},
appInfo: {
apiDomain: "api.supertokens.io",
appName: "SuperTokens",
websiteDomain: "supertokens.io",
},
recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })],
});

const req = new CustomFramework.PreParsedRequest({
method: "get",
url: "/verify",
query: {},
headers: new Headers(),
cookies: {},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp = new CustomFramework.CollectingResponse();

const verifyResult = await verifySession()(req, resp);

assert.strictEqual(verifyResult, undefined);
assert.strictEqual(resp.statusCode, 401);
assert.deepStrictEqual(JSON.parse(resp.body), { message: "unauthorised" });
});

// check basic usage of session
it("test basic usage of sessions", async function () {
const connectionURI = await startST();
SuperTokens.init({
framework: "custom",
supertokens: {
connectionURI,
},
appInfo: {
apiDomain: "api.supertokens.io",
appName: "SuperTokens",
websiteDomain: "supertokens.io",
},
recipeList: [Session.init({ getTokenTransferMethod: () => "cookie", antiCsrf: "VIA_TOKEN" })],
});

const middleware = CustomFramework.middleware();

const req = new CustomFramework.PreParsedRequest({
method: "get",
url: "/session/create",
query: {},
headers: new Headers(),
cookies: {},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp = new CustomFramework.CollectingResponse();

await Session.createNewSession(req, resp, "public", SuperTokens.convertToRecipeUserId("testUserId"));

let res = extractInfoFromResponse(resp);

assert(res.accessToken !== undefined);
assert(res.antiCsrf !== undefined);
assert(res.refreshToken !== undefined);

const req2 = new CustomFramework.PreParsedRequest({
method: "get",
url: "/session/refresh",
query: {},
headers: new Headers([["anti-csrf", res.antiCsrf]]),
cookies: {
sAccessToken: res.accessToken,
sRefreshToken: res.refreshToken,
},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp2 = new CustomFramework.CollectingResponse();

let verifyState3 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1500);
assert(verifyState3 === undefined);

await Session.refreshSession(req2, resp2);
let res2 = extractInfoFromResponse(resp2);

assert(res2.accessToken !== undefined);
assert(res2.antiCsrf !== undefined);
assert(res2.refreshToken !== undefined);

const req3 = new CustomFramework.PreParsedRequest({
method: "get",
url: "/session/verify",
query: {},
headers: new Headers(),
cookies: {
sAccessToken: res2.accessToken,
},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp3 = new CustomFramework.CollectingResponse();
await verifySession()(req3, resp3);

let res3 = extractInfoFromResponse(resp3);
let verifyState = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY);

assert(verifyState !== undefined);
assert(res3.accessToken !== undefined);

ProcessState.getInstance().reset();

const req4 = new CustomFramework.PreParsedRequest({
method: "get",
url: "/session/verify",
query: {},
headers: new Headers(),
cookies: {
sAccessToken: res3.accessToken,
},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp4 = new CustomFramework.CollectingResponse();
await verifySession()(req4, resp4);
let verifyState2 = await ProcessState.getInstance().waitForEvent(PROCESS_STATE.CALLING_SERVICE_IN_VERIFY, 1000);
assert(verifyState2 === undefined);

const req5 = new CustomFramework.PreParsedRequest({
method: "get",
url: "/session/verify",
query: {},
headers: new Headers(),
cookies: {
sAccessToken: res3.accessToken,
},
getFormBody: () => {},
getJSONBody: () => {},
});
const resp5 = new CustomFramework.CollectingResponse();
await verifySession()(req5, resp5);
await req5.session.revokeSession();
let sessionRevokedResponseExtracted = extractInfoFromResponse(resp5);
assert.strictEqual(sessionRevokedResponseExtracted.accessTokenExpiry, "Thu, 01 Jan 1970 00:00:00 GMT");
assert.strictEqual(sessionRevokedResponseExtracted.refreshTokenExpiry, "Thu, 01 Jan 1970 00:00:00 GMT");
assert.strictEqual(sessionRevokedResponseExtracted.accessToken, "");
assert.strictEqual(sessionRevokedResponseExtracted.refreshToken, "");
});
});
103 changes: 62 additions & 41 deletions test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const { join } = require("path");

const users = require("./users.json");
let assert = require("assert");
const { CollectingResponse } = require("../framework/custom");

module.exports.printPath = function (path) {
return `${createFormat([consoleOptions.yellow, consoleOptions.italic, consoleOptions.dim])}${path}${createFormat([
Expand Down Expand Up @@ -83,7 +84,7 @@ module.exports.setKeyValueInConfig = async function (key, value) {
};

module.exports.extractInfoFromResponse = function (res) {
let antiCsrf = res.headers["anti-csrf"];
let headers;
let accessToken = undefined;
let refreshToken = undefined;
let accessTokenExpiry = undefined;
Expand All @@ -95,49 +96,69 @@ module.exports.extractInfoFromResponse = function (res) {
let accessTokenHttpOnly = false;
let idRefreshTokenHttpOnly = false;
let refreshTokenHttpOnly = false;
let frontToken = res.headers["front-token"];
let cookies = res.headers["set-cookie"] || res.headers["Set-Cookie"];
cookies = cookies === undefined ? [] : cookies;
if (!Array.isArray(cookies)) {
cookies = [cookies];
}

cookies.forEach((i) => {
if (i.split(";")[0].split("=")[0] === "sAccessToken") {
/**
* if token is sAccessToken=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0=.eyJzZXNzaW9uSGFuZGxlIjoiMWI4NDBhOTAtMjVmYy00ZjQ4LWE2YWMtMDc0MDIzZjNjZjQwIiwidXNlcklkIjoiIiwicmVmcmVzaFRva2VuSGFzaDEiOiJjYWNhZDNlMGNhMDVkNzRlNWYzNTc4NmFlMGQ2MzJjNDhmMTg1YmZmNmUxNThjN2I2OThkZDYwMzA1NzAyYzI0IiwidXNlckRhdGEiOnt9LCJhbnRpQ3NyZlRva2VuIjoiYTA2MjRjYWItZmIwNy00NTFlLWJmOTYtNWQ3YzU2MjMwZTE4IiwiZXhwaXJ5VGltZSI6MTYyNjUxMjM3NDU4NiwidGltZUNyZWF0ZWQiOjE2MjY1MDg3NzQ1ODYsImxtcnQiOjE2MjY1MDg3NzQ1ODZ9.f1sCkjt0OduS6I6FBQDBLV5zhHXpCU2GXnbe+8OCU6HKG00TX5CM8AyFlOlqzSHABZ7jES/+5k0Ff/rdD34cczlNqICcC4a23AjJg2a097rFrh8/8V7J5fr4UrHLIM4ojZNFz1NyVyDK/ooE6I7soHshEtEVr2XsnJ4q3d+fYs2wwx97PIT82hfHqgbRAzvlv952GYt+OH4bWQE4vTzDqGN7N2OKpn9l2fiCB1Ytzr3ocHRqKuQ8f6xW1n575Q1sSs9F9TtD7lrKfFQH+//6lyKFe2Q1SDc7YU4pE5Cy9Kc/LiqiTU+gsGIJL5qtMzUTG4lX38ugF4QDyNjDBMqCKw==; Max-Age=3599; Expires=Sat, 17 Jul 2021 08:59:34 GMT; Secure; HttpOnly; SameSite=Lax; Path=/'
* i.split(";")[0].split("=")[1] will result in eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0
*/
accessToken = decodeURIComponent(i.split(";")[0].split("=").slice(1).join("="));
if (i.split(";")[2].includes("Expires=")) {
accessTokenExpiry = i.split(";")[2].split("=")[1];
} else if (i.split(";")[2].includes("expires=")) {
accessTokenExpiry = i.split(";")[2].split("=")[1];
} else {
accessTokenExpiry = i.split(";")[3].split("=")[1];
}
if (i.split(";")[1].includes("Domain=")) {
accessTokenDomain = i.split(";")[1].split("=")[1];
}
accessTokenHttpOnly = i.split(";").findIndex((j) => j.includes("HttpOnly")) !== -1;
} else if (i.split(";")[0].split("=")[0] === "sRefreshToken") {
refreshToken = i.split(";")[0].split("=").slice(1).join("=");
if (i.split(";")[2].includes("Expires=")) {
refreshTokenExpiry = i.split(";")[2].split("=")[1];
} else if (i.split(";")[2].includes("expires=")) {
refreshTokenExpiry = i.split(";")[2].split("=")[1];
} else {
refreshTokenExpiry = i.split(";")[3].split("=")[1];
}
if (i.split(";")[1].includes("Domain=")) {
refreshTokenDomain = i.split(";")[1].split("=").slice(1).join("=");
}
refreshTokenHttpOnly = i.split(";").findIndex((j) => j.includes("HttpOnly")) !== -1;
if (res instanceof CollectingResponse) {
const accessTokenCookie = res.cookies.find((info) => info.key === "sAccessToken");
if (accessTokenCookie) {
accessToken = accessTokenCookie.value;
accessTokenExpiry = new Date(accessTokenCookie.expires).toUTCString();
accessTokenDomain = accessTokenCookie.domain;
accessTokenHttpOnly = accessTokenCookie.httpOnly;
}
});
const refreshTokenCookie = res.cookies.find((info) => info.key === "sRefreshToken");
if (refreshTokenCookie) {
refreshToken = refreshTokenCookie.value;
refreshTokenExpiry = new Date(refreshTokenCookie.expires).toUTCString();
refreshTokenDomain = refreshTokenCookie.domain;
refreshTokenHttpOnly = refreshTokenCookie.httpOnly;
}
headers = Object.fromEntries(res.headers.entries());
} else {
let cookies = res.headers["set-cookie"] || res.headers["Set-Cookie"];
cookies = cookies === undefined ? [] : cookies;
if (!Array.isArray(cookies)) {
cookies = [cookies];
}

cookies.forEach((i) => {
if (i.split(";")[0].split("=")[0] === "sAccessToken") {
/**
* if token is sAccessToken=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0=.eyJzZXNzaW9uSGFuZGxlIjoiMWI4NDBhOTAtMjVmYy00ZjQ4LWE2YWMtMDc0MDIzZjNjZjQwIiwidXNlcklkIjoiIiwicmVmcmVzaFRva2VuSGFzaDEiOiJjYWNhZDNlMGNhMDVkNzRlNWYzNTc4NmFlMGQ2MzJjNDhmMTg1YmZmNmUxNThjN2I2OThkZDYwMzA1NzAyYzI0IiwidXNlckRhdGEiOnt9LCJhbnRpQ3NyZlRva2VuIjoiYTA2MjRjYWItZmIwNy00NTFlLWJmOTYtNWQ3YzU2MjMwZTE4IiwiZXhwaXJ5VGltZSI6MTYyNjUxMjM3NDU4NiwidGltZUNyZWF0ZWQiOjE2MjY1MDg3NzQ1ODYsImxtcnQiOjE2MjY1MDg3NzQ1ODZ9.f1sCkjt0OduS6I6FBQDBLV5zhHXpCU2GXnbe+8OCU6HKG00TX5CM8AyFlOlqzSHABZ7jES/+5k0Ff/rdD34cczlNqICcC4a23AjJg2a097rFrh8/8V7J5fr4UrHLIM4ojZNFz1NyVyDK/ooE6I7soHshEtEVr2XsnJ4q3d+fYs2wwx97PIT82hfHqgbRAzvlv952GYt+OH4bWQE4vTzDqGN7N2OKpn9l2fiCB1Ytzr3ocHRqKuQ8f6xW1n575Q1sSs9F9TtD7lrKfFQH+//6lyKFe2Q1SDc7YU4pE5Cy9Kc/LiqiTU+gsGIJL5qtMzUTG4lX38ugF4QDyNjDBMqCKw==; Max-Age=3599; Expires=Sat, 17 Jul 2021 08:59:34 GMT; Secure; HttpOnly; SameSite=Lax; Path=/'
* i.split(";")[0].split("=")[1] will result in eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0
*/
accessToken = decodeURIComponent(i.split(";")[0].split("=").slice(1).join("="));
if (i.split(";")[2].includes("Expires=")) {
accessTokenExpiry = i.split(";")[2].split("=")[1];
} else if (i.split(";")[2].includes("expires=")) {
accessTokenExpiry = i.split(";")[2].split("=")[1];
} else {
accessTokenExpiry = i.split(";")[3].split("=")[1];
}
if (i.split(";")[1].includes("Domain=")) {
accessTokenDomain = i.split(";")[1].split("=")[1];
}
accessTokenHttpOnly = i.split(";").findIndex((j) => j.includes("HttpOnly")) !== -1;
} else if (i.split(";")[0].split("=")[0] === "sRefreshToken") {
refreshToken = i.split(";")[0].split("=").slice(1).join("=");
if (i.split(";")[2].includes("Expires=")) {
refreshTokenExpiry = i.split(";")[2].split("=")[1];
} else if (i.split(";")[2].includes("expires=")) {
refreshTokenExpiry = i.split(";")[2].split("=")[1];
} else {
refreshTokenExpiry = i.split(";")[3].split("=")[1];
}
if (i.split(";")[1].includes("Domain=")) {
refreshTokenDomain = i.split(";")[1].split("=").slice(1).join("=");
}
refreshTokenHttpOnly = i.split(";").findIndex((j) => j.includes("HttpOnly")) !== -1;
}
});
}
let antiCsrf = headers["anti-csrf"];
let frontToken = headers["front-token"];

const refreshTokenFromHeader = res.headers["st-refresh-token"];
const accessTokenFromHeader = res.headers["st-access-token"];
const refreshTokenFromHeader = headers["st-refresh-token"];
const accessTokenFromHeader = headers["st-access-token"];

const accessTokenFromAny = accessToken === undefined ? accessTokenFromHeader : accessToken;
const refreshTokenFromAny = refreshToken === undefined ? refreshTokenFromHeader : refreshToken;
Expand Down

0 comments on commit 5874da6

Please sign in to comment.