diff --git a/backend/controllers/file.ts b/backend/controllers/file.ts index 88c940f..94e7c99 100644 --- a/backend/controllers/file.ts +++ b/backend/controllers/file.ts @@ -318,9 +318,9 @@ class FileController { const user = req.user; - const ipAddress = req.clientIp; + const currentUUID = req.headers.uuid as string; - const streamVideoAccessToken = await user.generateAuthTokenStreamVideo(ipAddress); + const streamVideoAccessToken = await user.generateAuthTokenStreamVideo(currentUUID); createStreamVideoCookie(res, streamVideoAccessToken); diff --git a/backend/controllers/user.ts b/backend/controllers/user.ts index 99f102c..b3bfb1b 100644 --- a/backend/controllers/user.ts +++ b/backend/controllers/user.ts @@ -55,9 +55,10 @@ class UserController { try { const body = req.body; - const ipAddress = req.clientIp; + + const currentUUID = req.headers.uuid as string; - const {user, accessToken, refreshToken} = await UserProvider.login(body, ipAddress); + const {user, accessToken, refreshToken} = await UserProvider.login(body, currentUUID); createLoginCookie(res, accessToken, refreshToken); @@ -79,7 +80,9 @@ class UserController { if (!user) throw new NotFoundError("User Not Found"); - const {accessToken, refreshToken} = await user.generateAuthToken(req.clientIp); + const currentUUID = req.headers.uuid as string; + + const {accessToken, refreshToken} = await user.generateAuthToken(currentUUID); if (!accessToken || !refreshToken) throw new InternalServerError("User/Access/Refresh Token Missing"); @@ -153,9 +156,9 @@ class UserController { try { - const ipAddress = req.clientIp; + const currentUUID = req.headers.uuid as string; - const {user, accessToken, refreshToken} = await UserProvider.create(req.body, ipAddress); + const {user, accessToken, refreshToken} = await UserProvider.create(req.body, currentUUID); createLoginCookie(res, accessToken, refreshToken); @@ -182,9 +185,10 @@ class UserController { const oldPassword = req.body.oldPassword; const newPassword = req.body.newPassword; const oldRefreshToken = req.cookies["refresh-token"]; - const ipAddress = req.clientIp; + + const currentUUID = req.headers.uuid as string; - const {accessToken, refreshToken} = await UserProvider.changePassword(userID, oldPassword, newPassword, oldRefreshToken, ipAddress); + const {accessToken, refreshToken} = await UserProvider.changePassword(userID, oldPassword, newPassword, oldRefreshToken, currentUUID); createLoginCookie(res, accessToken, refreshToken); @@ -247,11 +251,12 @@ class UserController { try { const verifyToken = req.body.emailToken; - const ipAddress = req.clientIp; + + const currentUUID = req.headers.uuid as string; const user = await UserProvider.verifyEmail(verifyToken); - const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await user.generateAuthToken(currentUUID); createLoginCookie(res, accessToken, refreshToken); diff --git a/backend/controllers/userGoogle.ts b/backend/controllers/userGoogle.ts index 8f1d397..8635955 100644 --- a/backend/controllers/userGoogle.ts +++ b/backend/controllers/userGoogle.ts @@ -49,9 +49,10 @@ class UserGoogleController { const user = req.user; const code = req.body.code; - const ipAddress = req.clientIp; + + const currentUUID = req.headers.uuid as string; - const {accessToken, refreshToken} = await UserProviderGoogle.addGoogleStorage(user, code, ipAddress); + const {accessToken, refreshToken} = await UserProviderGoogle.addGoogleStorage(user, code, currentUUID); createLoginCookie(res, accessToken, refreshToken); @@ -74,9 +75,10 @@ class UserGoogleController { try { const user = req.user - const ipAddress = req.clientIp; - const {accessToken, refreshToken} = await UserProviderGoogle.removeGoogleStorage(user, ipAddress); + const currentUUID = req.headers.uuid as string; + + const {accessToken, refreshToken} = await UserProviderGoogle.removeGoogleStorage(user, currentUUID); createLoginCookie(res, accessToken, refreshToken); diff --git a/backend/controllers/userPersonal.ts b/backend/controllers/userPersonal.ts index 328744d..3dc4f67 100644 --- a/backend/controllers/userPersonal.ts +++ b/backend/controllers/userPersonal.ts @@ -38,9 +38,10 @@ class UserPersonalController { const user = req.user; const s3Data = req.body; - const ipAddress = req.clientIp; + + const currentUUID = req.headers.uuid as string; - const {accessToken, refreshToken} = await UserProviderPersonal.addS3Storage(user, s3Data, ipAddress); + const {accessToken, refreshToken} = await UserProviderPersonal.addS3Storage(user, s3Data, currentUUID); createLoginCookie(res, accessToken, refreshToken); @@ -63,9 +64,9 @@ class UserPersonalController { try { const user = req.user; - const ipAddress = req.clientIp; + const currentUUID = req.headers.uuid as string; - const {accessToken, refreshToken} = await UserProviderPersonal.removeS3Storage(user, ipAddress); + const {accessToken, refreshToken} = await UserProviderPersonal.removeS3Storage(user, currentUUID); createLoginCookie(res, accessToken, refreshToken); diff --git a/backend/cookies/createCookies.ts b/backend/cookies/createCookies.ts index 81c17f6..42652d8 100644 --- a/backend/cookies/createCookies.ts +++ b/backend/cookies/createCookies.ts @@ -2,7 +2,9 @@ import {Response } from "express"; import env from "../enviroment/env"; const maxAgeAccess = 60 * 1000 * 20; +//const maxAgeAccess = 1000; const maxAgeRefresh = 60 * 1000 * 60 * 24 * 30; +//const maxAgeRefresh = 1000; const maxAgeStreamVideo = 60 * 1000 * 60 * 24; const secureCookies = env.secureCookies ? env.secureCookies === "true" ? true : false : false; diff --git a/backend/middleware/auth.ts b/backend/middleware/auth.ts index b79ed8b..bda1a19 100644 --- a/backend/middleware/auth.ts +++ b/backend/middleware/auth.ts @@ -26,7 +26,7 @@ const auth = async(req: RequestType, res: Response, next: NextFunction) => { try { - console.log("auth up address", req.clientIp, req.ip); + console.log("auth uuid", req.headers.uuid); // console.log(req.headers); diff --git a/backend/middleware/authNoEmailVerificication.ts b/backend/middleware/authNoEmailVerificication.ts index 900a49d..2e5fb21 100644 --- a/backend/middleware/authNoEmailVerificication.ts +++ b/backend/middleware/authNoEmailVerificication.ts @@ -37,8 +37,8 @@ const auth = async(req: RequestType, res: Response, next: NextFunction) => { if (!user) throw new Error("No User"); if (!user.emailVerified && !env.disableEmailVerification) { - const ipAddress = req.clientIp; - user = await userUpdateCheck(res, user._id, ipAddress); + const currentUUID = req.headers.uuid as string; + user = await userUpdateCheck(res, user._id, currentUUID); } req.user = user; diff --git a/backend/middleware/authRefresh.ts b/backend/middleware/authRefresh.ts index 8e2aa75..ff92378 100644 --- a/backend/middleware/authRefresh.ts +++ b/backend/middleware/authRefresh.ts @@ -16,19 +16,20 @@ type jwtType = { time: number } -const removeOldTokens = async(userID: string, ipAddress: string | undefined, oldTime: number) => { +const removeOldTokens = async(userID: string, uuid: string | undefined, oldTime: number) => { try { - console.log("removing token with IP address", ipAddress); + console.log("removing token with uuid address", uuid); const minusTime = oldTime - (1000 * 60 * 60); + //const minusTime = oldTime - (1000); - ipAddress = ipAddress ? ipAddress : ""; + uuid = uuid ? uuid : "unknown"; - if (ipAddress === "") return; + if (uuid === "unknown") return; - await User.updateOne({_id: userID}, {$pull: {tokens: {ipAddress, time: {$lt: minusTime}}}}) + await User.updateOne({_id: userID}, {$pull: {tokens: {uuid, time: {$lt: minusTime}}}}) } catch (e) { console.log("cannot remove old tokens", e); @@ -40,6 +41,7 @@ const authRefresh = async(req: RequestType, res: Response, next: NextFunction) = try { const refreshToken = req.cookies["refresh-token"]; + const currentUUID = req.headers.uuid as string; if (!refreshToken) throw new Error("No Refresh Token"); @@ -63,7 +65,7 @@ const authRefresh = async(req: RequestType, res: Response, next: NextFunction) = if (currentEncryptedToken === encryptedToken) { tokenFound = true; - removeOldTokens(user._id, req.clientIp, time); + removeOldTokens(user._id, currentUUID, time); break; } } diff --git a/backend/middleware/authStreamVideo.ts b/backend/middleware/authStreamVideo.ts index 9de4241..f91a030 100644 --- a/backend/middleware/authStreamVideo.ts +++ b/backend/middleware/authStreamVideo.ts @@ -17,17 +17,17 @@ type jwtType = { time: number } -const removeOldTokens = async(userID: string, ipAddress: string | undefined, oldTime: number) => { +const removeOldTokens = async(userID: string, uuid: string | undefined, oldTime: number) => { try { const minusTime = oldTime - (60 * 1000 * 60 * 24); - ipAddress = ipAddress ? ipAddress : ""; + uuid = uuid ? uuid : "unknown"; - if (ipAddress === "") return; + if (uuid === "unknown") return; - await User.updateOne({_id: userID}, {$pull: {tempTokens: {ipAddress, time: {$lt: minusTime}}}}) + await User.updateOne({_id: userID}, {$pull: {tempTokens: {uuid, time: {$lt: minusTime}}}}) } catch (e) { console.log("cannot remove old tokens", e); @@ -40,6 +40,7 @@ const authStreamVideo = async(req: RequestType, res: Response, next: NextFunctio try { const accessTokenStreamVideo = req.cookies["video-access-token"]; + const currentUUID = req.headers.uuid as string; if (!accessTokenStreamVideo) throw new Error("No Access Token"); @@ -63,7 +64,7 @@ const authStreamVideo = async(req: RequestType, res: Response, next: NextFunctio if (currentEncryptedToken === encryptedToken) { tokenFound = true; - removeOldTokens(user._id, req.clientIp, time); + removeOldTokens(user._id, currentUUID, time); break; } } diff --git a/backend/models/user.ts b/backend/models/user.ts index fb3c36a..03acbbe 100644 --- a/backend/models/user.ts +++ b/backend/models/user.ts @@ -38,7 +38,7 @@ const userSchema = new mongoose.Schema({ type: String, required: true }, - ipAddress: { + uuid: { type: String, required: true, }, @@ -52,7 +52,7 @@ const userSchema = new mongoose.Schema({ type: String, required: true }, - ipAddress: { + uuid: { type: String, required: true, }, @@ -188,8 +188,8 @@ export interface UserInterface extends Document { encryptToken: (tempToken: any, key: any, publicKey: any) => any; decryptToken: (encryptedToken: any, key: any, publicKey: any) => any; findByCreds: (email: string, password: string) => Promise; - generateAuthToken: (ipAddress: string | undefined) => Promise<{accessToken: string, refreshToken: string}> - generateAuthTokenStreamVideo: (ipAddress: string | undefined) => Promise + generateAuthToken: (uuid: string | undefined) => Promise<{accessToken: string, refreshToken: string}> + generateAuthTokenStreamVideo: (uuid: string | undefined) => Promise generateEncryptionKeys: () => Promise; changeEncryptionKey: (randomKey: Buffer) => Promise; generateEmailVerifyToken: () => Promise; @@ -251,7 +251,7 @@ userSchema.methods.toJSON = function() { return userObject; } -userSchema.methods.generateAuthTokenStreamVideo = async function(ipAddress: string | undefined) { +userSchema.methods.generateAuthTokenStreamVideo = async function(uuid: string | undefined) { const iv = crypto.randomBytes(16); @@ -266,14 +266,14 @@ userSchema.methods.generateAuthTokenStreamVideo = async function(ipAddress: stri const encryptedToken = user.encryptToken(accessTokenStreamVideo, encryptionKey, iv); - ipAddress = ipAddress ? ipAddress : ""; + uuid = uuid ? uuid : "unknown"; - await User.updateOne({_id: user._id}, {$push: {"tempTokens": {token: encryptedToken, ipAddress, time}}}); + await User.updateOne({_id: user._id}, {$push: {"tempTokens": {token: encryptedToken, uuid, time}}}); return accessTokenStreamVideo; } -userSchema.methods.generateAuthToken = async function(ipAddress: string | undefined) { +userSchema.methods.generateAuthToken = async function(uuid: string | undefined) { const iv = crypto.randomBytes(16); @@ -293,9 +293,9 @@ userSchema.methods.generateAuthToken = async function(ipAddress: string | undefi //user.tokens = user.tokens.concat({token: encryptedToken}); - ipAddress = ipAddress ? ipAddress : ""; + uuid = uuid ? uuid : "unknown"; - await User.updateOne({_id: user._id}, {$push: {"tokens": {token: encryptedToken, ipAddress, time}}}) + await User.updateOne({_id: user._id}, {$push: {"tokens": {token: encryptedToken, uuid, time}}}) // console.log("saving user") // console.log("user saved") diff --git a/backend/services/UserGoogle/index.ts b/backend/services/UserGoogle/index.ts index f5ecadc..fbdc7d5 100644 --- a/backend/services/UserGoogle/index.ts +++ b/backend/services/UserGoogle/index.ts @@ -27,7 +27,7 @@ class UserGoogleService { return url; } - addGoogleStorage = async(user: UserInterface, code: string, ipAddress: string | undefined) => { + addGoogleStorage = async(user: UserInterface, code: string, uuid: string | undefined) => { const redirectURL = env.remoteURL + "/add-google-account"; @@ -51,7 +51,7 @@ class UserGoogleService { user.encryptDriveTokenData(token); - const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await user.generateAuthToken(uuid); resolve({accessToken, refreshToken}); @@ -62,14 +62,14 @@ class UserGoogleService { }) } - removeGoogleStorage = async(user: UserInterface, ipAddress: string | undefined) => { + removeGoogleStorage = async(user: UserInterface, uuid: string | undefined) => { user.googleDriveEnabled = undefined; user.googleDriveData = undefined; await user.save(); - return await user.generateAuthToken(ipAddress); + return await user.generateAuthToken(uuid); } } diff --git a/backend/services/UserPersonalService/index.ts b/backend/services/UserPersonalService/index.ts index 9b6b6f3..12e90a0 100644 --- a/backend/services/UserPersonalService/index.ts +++ b/backend/services/UserPersonalService/index.ts @@ -18,7 +18,7 @@ class UserPeronsalService { } - addS3Storage = async(user: UserInterface, s3Data: any, ipAddress: string | undefined) => { + addS3Storage = async(user: UserInterface, s3Data: any, uuid: string | undefined) => { const {id, key, bucket} = s3Data; @@ -29,10 +29,10 @@ class UserPeronsalService { await user.save(); - return await user.generateAuthToken(ipAddress); + return await user.generateAuthToken(uuid); } - removeS3Storage = async(user: UserInterface, ipAddress: string | undefined) => { + removeS3Storage = async(user: UserInterface, uuid: string | undefined) => { const date = new Date(); @@ -43,7 +43,7 @@ class UserPeronsalService { await user.save(); - return await user.generateAuthToken(ipAddress); + return await user.generateAuthToken(uuid); } downloadPersonalFileList = async(user: userAccessType) => { diff --git a/backend/services/UserService/index.ts b/backend/services/UserService/index.ts index b8a6cf2..1df9da3 100644 --- a/backend/services/UserService/index.ts +++ b/backend/services/UserService/index.ts @@ -35,7 +35,7 @@ class UserService { } - login = async(userData: UserDataType, ipAddress: string | undefined) => { + login = async(userData: UserDataType, uuid: string | undefined) => { const email = userData.email; const password = userData.password; @@ -44,7 +44,7 @@ class UserService { if (!user) throw new NotFoundError("Cannot Find User"); - const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await user.generateAuthToken(uuid); if (!accessToken || !refreshToken) throw new NotFoundError("Login User Not Found Error"); @@ -90,7 +90,7 @@ class UserService { await user.save(); } - create = async(userData: any, ipAddress: string | undefined) => { + create = async(userData: any, uuid: string | undefined) => { const user = new User({email: userData.email, password: userData.password, emailVerified: env.disableEmailVerification}); await user.save(); @@ -99,7 +99,7 @@ class UserService { await user.generateEncryptionKeys(); - const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await user.generateAuthToken(uuid); const emailToken = await user.generateEmailVerifyToken(); if (!env.disableEmailVerification) await sendEmailVerification(user, emailToken); @@ -109,7 +109,7 @@ class UserService { return {user, accessToken, refreshToken} } - changePassword = async(userID: string, oldPassword: string, newPassword: string, oldRefreshToken: string, ipAddress: string | undefined) => { + changePassword = async(userID: string, oldPassword: string, newPassword: string, oldRefreshToken: string, uuid: string | undefined) => { const user = await User.findById(userID); @@ -132,7 +132,7 @@ class UserService { await user.save(); await user.changeEncryptionKey(encryptionKey!); - const {accessToken, refreshToken} = await user.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await user.generateAuthToken(uuid); return {accessToken, refreshToken}; } diff --git a/backend/utils/userUpdateCheck.ts b/backend/utils/userUpdateCheck.ts index 8e9dea7..4170b68 100644 --- a/backend/utils/userUpdateCheck.ts +++ b/backend/utils/userUpdateCheck.ts @@ -17,7 +17,7 @@ type userAccessType = { botChecked: boolean, } -const userUpdateCheck = async(res: Response, id: string, ipAddress: string | undefined) => { +const userUpdateCheck = async(res: Response, id: string, uuid: string | undefined) => { const updatedUser = await User.findById(id); @@ -25,7 +25,7 @@ const userUpdateCheck = async(res: Response, id: string, ipAddress: string | und if (updatedUser.emailVerified) { - const {accessToken, refreshToken} = await updatedUser.generateAuthToken(ipAddress); + const {accessToken, refreshToken} = await updatedUser.generateAuthToken(uuid); createLoginCookie(res, accessToken, refreshToken); } diff --git a/package.json b/package.json index 7894c5d..04d4ab1 100755 --- a/package.json +++ b/package.json @@ -28,7 +28,9 @@ "heroku-postbuild": "npm run build", "setup": "node dist/webUI/startSetupServer.js", "remove-old-subscription-data": "node serverUtils/removeOldSubscriptionData.js", - "remove-old-personal-data": "node serverUtils/removeOldPersonalData.js" + "remove-old-personal-data": "node serverUtils/removeOldPersonalData.js", + "remove-tokens": "node serverUtils/removeTokens.js --env production", + "remove-tokens:dev": "NODE_ENV=development node serverUtils/removeTokens.js" }, "dependencies": { "@babel/core": "^7.8.4", diff --git a/serverUtils/createIndexes.js b/serverUtils/createIndexes.js index 35adcb1..641ae54 100644 --- a/serverUtils/createIndexes.js +++ b/serverUtils/createIndexes.js @@ -1,4 +1,4 @@ -const getEnvVariables = require("./getEnvVaribables"); +const getEnvVariables = require("../dist/enviroment/getEnvVariables"); getEnvVariables(); const mongoose = require("./mongoServerUtil"); const conn = mongoose.connection; diff --git a/serverUtils/removeTokens.js b/serverUtils/removeTokens.js new file mode 100644 index 0000000..a95e9d5 --- /dev/null +++ b/serverUtils/removeTokens.js @@ -0,0 +1,44 @@ +const getEnvVariables = require("../dist/enviroment/getEnvVariables"); +getEnvVariables(); +const mongoose = require("./mongoServerUtil"); +const conn = mongoose.connection; +const User = require("../dist/models/user"); + +const waitForDatabase = () => { + + return new Promise((resolve, reject) => { + + if (conn.readyState !== 1) { + + conn.once("open", () => { + + resolve(); + + }) + + } else { + + resolve(); + } + + }) +} + +const removeTokens = async() => { + + console.log("\nWaiting for database..."); + await waitForDatabase(); + console.log("Connected to database\n"); + + console.log("Removing tokens from users..."); + const userList = await User.find({}); + await User.updateMany({}, { + tokens: [], + tempTokens: [] + }) + console.log("Removed tokens from", userList.length, "users"); + + process.exit(); +} + +removeTokens(); \ No newline at end of file diff --git a/src/axiosInterceptor/index.js b/src/axiosInterceptor/index.js index 924ce80..de3a209 100644 --- a/src/axiosInterceptor/index.js +++ b/src/axiosInterceptor/index.js @@ -1,4 +1,5 @@ import axios from 'axios'; +import uuid from "uuid"; const sleep = () => { return new Promise((resolve, reject) => { @@ -12,6 +13,30 @@ const axiosRetry = axios.create(); const axiosNoRetry = axios.create(); const axios3 = axios.create(); +axiosRetry.interceptors.request.use((config) => { + + console.time("uuid-test") + let browserIDCheck = localStorage.getItem("browser-id"); + + if (!browserIDCheck) { + console.log("creating new UUID") + browserIDCheck = uuid.v4(); + localStorage.setItem("browser-id", browserIDCheck); + }; + + console.log("request interceptor") + config.headers.uuid = browserIDCheck; + + console.timeEnd("uuid-test") + + return config; + +}, (error) => { + + return Promise.reject(error); + +}) + axiosRetry.interceptors.response.use((response) => { //console.log("axios interceptor successful") return response; @@ -37,8 +62,18 @@ axiosRetry.interceptors.response.use((response) => { //console.log("error url equal to refresh token route") return reject(); } + + let browserIDCheck = localStorage.getItem("browser-id"); + + if (!browserIDCheck) { + console.log("creating new UUID") + browserIDCheck = uuid.v4(); + localStorage.setItem("browser-id", browserIDCheck); + }; - axiosNoRetry.post("/user-service/get-token").then((cookieResponse) => { + axiosNoRetry.post("/user-service/get-token", {}, {headers: { + "uuid" : browserIDCheck + }}).then((cookieResponse) => { return sleep("sleepy boi");