Skip to content

Commit

Permalink
cookie v2 containing role and userId (#1922)
Browse files Browse the repository at this point in the history
* add authorities file

* add logic to send cookie-v2

* write test

* fix auth test

* test check cookie v2

* fix the issue with rdsUiUrl

* remove done()

* address review comment
  • Loading branch information
bhtibrewal authored Feb 24, 2024
1 parent 9a7602b commit 5451808
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 8 deletions.
1 change: 1 addition & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ module.exports = {

userToken: {
cookieName: `rds-session-${NODE_ENV}`,
cookieV2Name: `rds-session-v2-${NODE_ENV}`,
ttl: 30 * 24 * 60 * 60, // in seconds
refreshTtl: 180 * 24 * 60 * 60, // in seconds
publicKey: "<publicKey>",
Expand Down
1 change: 1 addition & 0 deletions config/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
discordMissedUpdatesRoleId: "1183553844811153458",
userToken: {
cookieName: "rds-session",
cookieV2Name: "rds-session-v2",
},

services: {
Expand Down
7 changes: 7 additions & 0 deletions constants/authorities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const AUTHORITIES = {
SUPERUSER: "super_user",
MEMBER: "member",
USER: "user",
};

module.exports = { AUTHORITIES };
27 changes: 21 additions & 6 deletions controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,18 @@ const githubAuthCallback = (req, res, next) => {
const rdsUiUrl = new URL(config.get("services.rdsUi.baseUrl"));
let authRedirectionUrl = rdsUiUrl;
let devMode = false;
let isV2FlagPresent = false;

if ("state" in req.query) {
try {
const redirectUrl = new URL(req.query.state);
if (redirectUrl.searchParams.get("isMobileApp") === "true") {
isMobileApp = true;
redirectUrl.searchParams.delete("isMobileApp");
}

if (redirectUrl.searchParams.get("v2") === "true") isV2FlagPresent = true;

if (`.${redirectUrl.hostname}`.endsWith(`.${rdsUiUrl.hostname}`)) {
// Matching *.realdevsquad.com
authRedirectionUrl = redirectUrl;
Expand All @@ -78,18 +83,25 @@ const githubAuthCallback = (req, res, next) => {
updated_at: Date.now(),
};

const { userId, incompleteUserDetails } = await users.addOrUpdate(userData);
const { userId, incompleteUserDetails, role } = await users.addOrUpdate(userData);

const token = authService.generateAuthToken({ userId });

// respond with a cookie
res.cookie(config.get("userToken.cookieName"), token, {
const cookieOptions = {
domain: rdsUiUrl.hostname,
expires: new Date(Date.now() + config.get("userToken.ttl") * 1000),
httpOnly: true,
secure: true,
sameSite: "lax",
});
};
// respond with a cookie
res.cookie(config.get("userToken.cookieName"), token, cookieOptions);

/* redirectUrl woud be like https://realdevsquad.com?v2=true */
if (isV2FlagPresent) {
const tokenV2 = authService.generateAuthToken({ userId, role });
res.cookie(config.get("userToken.cookieV2Name"), tokenV2, cookieOptions);
}

if (!devMode) {
// TODO: Revisit incompleteUserDetails redirect condition
Expand All @@ -112,12 +124,15 @@ const githubAuthCallback = (req, res, next) => {
const signout = (req, res) => {
const cookieName = config.get("userToken.cookieName");
const rdsUiUrl = new URL(config.get("services.rdsUi.baseUrl"));
res.clearCookie(cookieName, {
const cookieOptions = {
domain: rdsUiUrl.hostname,
httpOnly: true,
secure: true,
sameSite: "lax",
});
};
res.clearCookie(cookieName, cookieOptions);
const cookieV2Name = config.get("userToken.cookieV2Name");
res.clearCookie(cookieV2Name, cookieOptions);
return res.json({
message: "Signout successful",
});
Expand Down
13 changes: 11 additions & 2 deletions models/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const photoVerificationModel = firestore.collection("photo-verification");
const { ITEM_TAG, USER_STATE } = ALLOWED_FILTER_PARAMS;
const admin = require("firebase-admin");
const { INTERNAL_SERVER_ERROR } = require("../constants/errorMessages");
const { AUTHORITIES } = require("../constants/authorities");

/**
* Adds or updates the user data
Expand Down Expand Up @@ -59,13 +60,15 @@ const addOrUpdate = async (userData, userId = null) => {
if (!user || (user && user.empty)) {
user = await userModel.where("github_id", "==", userData.github_id).limit(1).get();
}
if (user && !user.empty) {
if (user && !user.empty && user.docs !== null) {
await userModel.doc(user.docs[0].id).set(userData, { merge: true });
const data = user.docs[0].data();
return {
isNewUser: false,
userId: user.docs[0].id,
incompleteUserDetails: user.docs[0].data().incompleteUserDetails,
updated_at: Date.now(),
role: Object.values(AUTHORITIES).find((role) => data.roles[role]) || AUTHORITIES.USER,
};
}

Expand All @@ -78,7 +81,13 @@ const addOrUpdate = async (userData, userId = null) => {
userData.roles = { archived: false, in_discord: false };
userData.incompleteUserDetails = true;
const userInfo = await userModel.add(userData);
return { isNewUser: true, userId: userInfo.id, incompleteUserDetails: true, updated_at: Date.now() };
return {
isNewUser: true,
role: AUTHORITIES.USER,
userId: userInfo.id,
incompleteUserDetails: true,
updated_at: Date.now(),
};
} catch (err) {
logger.error("Error in adding or updating user", err);
throw err;
Expand Down
26 changes: 26 additions & 0 deletions test/integration/auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,30 @@ describe("auth", function () {
return done();
});
});

it("should send rds-session-v2 in res cookie", async function () {
const rdsUiUrl = new URL(config.get("services.rdsUi.baseUrl"));

sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => {
callback(null, "accessToken", githubUserInfo[0]);
return (req, res, next) => {};
});

const res = await chai
.request(app)
.get("/auth/github/callback")
.query({ code: "codeReturnedByGithub", state: rdsUiUrl.href + "?v2=true" })
.redirects(0);

expect(res).to.have.status(302);
// rds-session-v2=token; Domain=realdevsquad.com; Path=/; Expires=Tue, 06 Oct 2020 11:23:07 GMT; HttpOnly; Secure
expect(res.headers["set-cookie"]).to.have.length(2); /* res has 2 cookies rds-session & rds-session-v2 */
expect(res.headers["set-cookie"][1])
.to.be.a("string")
.and.satisfy((msg) => msg.startsWith(config.get("userToken.cookieV2Name")));
expect(res.headers["set-cookie"][1]).to.include("HttpOnly");
expect(res.headers["set-cookie"][1]).to.include("Secure");
expect(res.headers["set-cookie"][1]).to.include(`Domain=${rdsUiUrl.hostname}`);
expect(res.headers["set-cookie"][1]).to.include("SameSite=Lax");
});
});

0 comments on commit 5451808

Please sign in to comment.