UNPKG

supertokens-node

Version:
279 lines (278 loc) 13.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const SessionFunctions = require("./sessionFunctions"); const cookieAndHeaders_1 = require("./cookieAndHeaders"); const utils_1 = require("./utils"); const sessionClass_1 = require("./sessionClass"); const error_1 = require("./error"); const utils_2 = require("../../utils"); const utils_3 = require("../../utils"); const constants_1 = require("./constants"); const processState_1 = require("../../processState"); const normalisedURLPath_1 = require("../../normalisedURLPath"); class RecipeImplementation { constructor(querier, config, isInServerlessEnv) { this.handshakeInfo = undefined; this.createNewSession = ({ res, userId, jwtPayload = {}, sessionData = {} }) => __awaiter(this, void 0, void 0, function* () { let response = yield SessionFunctions.createNewSession(this, userId, jwtPayload, sessionData); utils_1.attachCreateOrRefreshSessionResponseToExpressRes(this.config, res, response); return new sessionClass_1.default( this, response.accessToken.token, response.session.handle, response.session.userId, response.session.userDataInJWT, res ); }); this.getSession = ({ req, res, options }) => __awaiter(this, void 0, void 0, function* () { let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; let idRefreshToken = cookieAndHeaders_1.getIdRefreshTokenFromCookie(req); if (idRefreshToken === undefined) { // we do not clear cookies here because of a // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 if (options !== undefined && typeof options !== "boolean" && options.sessionRequired === false) { // there is no session that exists here, and the user wants session verification // to be optional. So we return undefined. return undefined; } throw new error_1.default({ message: "Session does not exist. Are you sending the session tokens in the request as cookies?", type: error_1.default.UNAUTHORISED, }); } let accessToken = cookieAndHeaders_1.getAccessTokenFromCookie(req); if (accessToken === undefined) { // maybe the access token has expired. throw new error_1.default({ message: "Access token has expired. Please call the refresh API", type: error_1.default.TRY_REFRESH_TOKEN, }); } try { let antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); if (doAntiCsrfCheck === undefined) { doAntiCsrfCheck = utils_2.normaliseHttpMethod(req.method) !== "get"; } let response = yield SessionFunctions.getSession( this, accessToken, antiCsrfToken, doAntiCsrfCheck, cookieAndHeaders_1.getRidFromHeader(req) !== undefined ); if (response.accessToken !== undefined) { cookieAndHeaders_1.setFrontTokenInHeaders( res, response.session.userId, response.accessToken.expiry, response.session.userDataInJWT ); cookieAndHeaders_1.attachAccessTokenToCookie( this.config, res, response.accessToken.token, response.accessToken.expiry ); accessToken = response.accessToken.token; } return new sessionClass_1.default( this, accessToken, response.session.handle, response.session.userId, response.session.userDataInJWT, res ); } catch (err) { if (err.type === error_1.default.UNAUTHORISED) { cookieAndHeaders_1.clearSessionFromCookie(this.config, res); } throw err; } }); this.refreshSession = ({ req, res }) => __awaiter(this, void 0, void 0, function* () { let inputIdRefreshToken = cookieAndHeaders_1.getIdRefreshTokenFromCookie(req); if (inputIdRefreshToken === undefined) { // we do not clear cookies here because of a // race condition mentioned here: https://github.com/supertokens/supertokens-node/issues/17 throw new error_1.default({ message: "Session does not exist. Are you sending the session tokens in the request as cookies?", type: error_1.default.UNAUTHORISED, }); } try { let inputRefreshToken = cookieAndHeaders_1.getRefreshTokenFromCookie(req); if (inputRefreshToken === undefined) { throw new error_1.default({ message: "Refresh token not found. Are you sending the refresh token in the request as a cookie?", type: error_1.default.UNAUTHORISED, }); } let antiCsrfToken = cookieAndHeaders_1.getAntiCsrfTokenFromHeaders(req); let response = yield SessionFunctions.refreshSession( this, inputRefreshToken, antiCsrfToken, cookieAndHeaders_1.getRidFromHeader(req) !== undefined ); utils_1.attachCreateOrRefreshSessionResponseToExpressRes(this.config, res, response); return new sessionClass_1.default( this, response.accessToken.token, response.session.handle, response.session.userId, response.session.userDataInJWT, res ); } catch (err) { if ( (err.type === error_1.default.UNAUTHORISED && err.payload.clearCookies) || err.type === error_1.default.TOKEN_THEFT_DETECTED ) { cookieAndHeaders_1.clearSessionFromCookie(this.config, res); } throw err; } }); this.revokeAllSessionsForUser = ({ userId }) => { return SessionFunctions.revokeAllSessionsForUser(this, userId); }; this.getAllSessionHandlesForUser = ({ userId }) => { return SessionFunctions.getAllSessionHandlesForUser(this, userId); }; this.revokeSession = ({ sessionHandle }) => { return SessionFunctions.revokeSession(this, sessionHandle); }; this.revokeMultipleSessions = ({ sessionHandles }) => { return SessionFunctions.revokeMultipleSessions(this, sessionHandles); }; this.getSessionData = ({ sessionHandle }) => { return SessionFunctions.getSessionData(this, sessionHandle); }; this.updateSessionData = ({ sessionHandle, newSessionData }) => { return SessionFunctions.updateSessionData(this, sessionHandle, newSessionData); }; this.getJWTPayload = ({ sessionHandle }) => { return SessionFunctions.getJWTPayload(this, sessionHandle); }; this.updateJWTPayload = ({ sessionHandle, newJWTPayload }) => { return SessionFunctions.updateJWTPayload(this, sessionHandle, newJWTPayload); }; this.getHandshakeInfo = (forceRefetch = false) => __awaiter(this, void 0, void 0, function* () { if (this.handshakeInfo === undefined || forceRefetch) { let antiCsrf = this.config.antiCsrf; if (this.isInServerlessEnv && !forceRefetch) { let handshakeInfo = yield utils_3.getDataFromFileForServerlessCache( constants_1.SERVERLESS_CACHE_HANDSHAKE_INFO_FILE_PATH ); if (handshakeInfo !== undefined) { handshakeInfo = Object.assign(Object.assign({}, handshakeInfo), { antiCsrf }); this.handshakeInfo = handshakeInfo; return this.handshakeInfo; } } processState_1.ProcessState.getInstance().addState( processState_1.PROCESS_STATE.CALLING_SERVICE_IN_GET_HANDSHAKE_INFO ); let response = yield this.querier.sendPostRequest( new normalisedURLPath_1.default("/recipe/handshake"), {} ); let signingKeyLastUpdated = Date.now(); if (this.handshakeInfo !== undefined) { if ( response.jwtSigningPublicKeyExpiryTime === this.handshakeInfo.jwtSigningPublicKeyExpiryTime && response.jwtSigningPublicKey === this.handshakeInfo.jwtSigningPublicKey ) { signingKeyLastUpdated = this.handshakeInfo.signingKeyLastUpdated; } } this.handshakeInfo = { signingKeyLastUpdated, jwtSigningPublicKey: response.jwtSigningPublicKey, antiCsrf, accessTokenBlacklistingEnabled: response.accessTokenBlacklistingEnabled, jwtSigningPublicKeyExpiryTime: response.jwtSigningPublicKeyExpiryTime, accessTokenValidity: response.accessTokenValidity, refreshTokenValidity: response.refreshTokenValidity, }; if (this.isInServerlessEnv) { utils_3.storeIntoTempFolderForServerlessCache( constants_1.SERVERLESS_CACHE_HANDSHAKE_INFO_FILE_PATH, this.handshakeInfo ); } } return this.handshakeInfo; }); this.updateJwtSigningPublicKeyInfo = (newKey, newExpiry) => { if (this.handshakeInfo !== undefined) { if ( this.handshakeInfo.jwtSigningPublicKeyExpiryTime !== newExpiry || this.handshakeInfo.jwtSigningPublicKey !== newKey ) { this.handshakeInfo.signingKeyLastUpdated = Date.now(); } this.handshakeInfo.jwtSigningPublicKey = newKey; this.handshakeInfo.jwtSigningPublicKeyExpiryTime = newExpiry; } }; this.getAccessTokenLifeTimeMS = () => __awaiter(this, void 0, void 0, function* () { return (yield this.getHandshakeInfo()).accessTokenValidity; }); this.getRefreshTokenLifeTimeMS = () => __awaiter(this, void 0, void 0, function* () { return (yield this.getHandshakeInfo()).refreshTokenValidity; }); this.querier = querier; this.config = config; this.isInServerlessEnv = isInServerlessEnv; // Solving the cold start problem this.getHandshakeInfo().catch((_) => { // ignored }); } } exports.default = RecipeImplementation; //# sourceMappingURL=recipeImplementation.js.map