diff --git a/src/core/server/app/middleware/passport/index.ts b/src/core/server/app/middleware/passport/index.ts index 693d7d912..7da5288b1 100644 --- a/src/core/server/app/middleware/passport/index.ts +++ b/src/core/server/app/middleware/passport/index.ts @@ -128,9 +128,15 @@ export async function handleSuccessfulLogin( const expiresIn = DateTime.fromJSDate(coral.now).plus({ days: 1 }); // Grab the token. - const token = await signTokenString(signingConfig, user, tenant, { - expiresIn: Math.floor(expiresIn.toSeconds()), - }); + const token = await signTokenString( + signingConfig, + user, + tenant, + { + expiresIn: Math.round(expiresIn.toSeconds()), + }, + coral.now + ); // Set the cache control headers. res.header("Cache-Control", "private, no-cache, no-store, must-revalidate"); @@ -184,9 +190,15 @@ export async function handleOAuth2Callback( const expiresIn = DateTime.fromJSDate(req.coral!.now).plus({ days: 1 }); // Grab the token. - const token = await signTokenString(signingConfig, user, tenant, { - expiresIn: Math.floor(expiresIn.toSeconds()), - }); + const token = await signTokenString( + signingConfig, + user, + tenant, + { + expiresIn: Math.round(expiresIn.toSeconds()), + }, + req.coral!.now + ); res.cookie( COOKIE_NAME, token, diff --git a/src/core/server/app/middleware/passport/strategies/verifiers/jwt.ts b/src/core/server/app/middleware/passport/strategies/verifiers/jwt.ts index 21d232d82..9f3af3f83 100644 --- a/src/core/server/app/middleware/passport/strategies/verifiers/jwt.ts +++ b/src/core/server/app/middleware/passport/strategies/verifiers/jwt.ts @@ -30,12 +30,15 @@ export const JWTTokenSchema = Joi.object().keys({ sub: Joi.string().required(), iat: Joi.number().required(), iss: Joi.string().required(), + nbf: Joi.number(), exp: Joi.number(), pat: Joi.boolean(), }); export function isJWTToken(token: JWTToken | object): token is JWTToken { - const { error } = Joi.validate(token, JWTTokenSchema); + const { error } = Joi.validate(token, JWTTokenSchema, { + allowUnknown: true, + }); return isNil(error); } diff --git a/src/core/server/services/jwt/index.ts b/src/core/server/services/jwt/index.ts index 63a38519f..614101259 100644 --- a/src/core/server/services/jwt/index.ts +++ b/src/core/server/services/jwt/index.ts @@ -156,6 +156,10 @@ export interface JWTSigningConfig { algorithm: JWTSigningAlgorithm; } +export function dateToSeconds(date: Date): number { + return Math.round(DateTime.fromJSDate(date).toSeconds()); +} + export function createAsymmetricSigningConfig( algorithm: AsymmetricSigningAlgorithm, secret: string @@ -215,23 +219,31 @@ export const signTokenString = async ( { algorithm, secret }: JWTSigningConfig, user: Pick, tenant: Pick, - options: SigningTokenOptions = {} + options: SigningTokenOptions = {}, + now = new Date() ) => - jwt.sign({}, secret, { - jwtid: uuid(), - expiresIn: "1 day", - ...options, - issuer: tenant.id, - subject: user.id, - algorithm, - }); + jwt.sign( + { + iat: dateToSeconds(now), + }, + secret, + { + jwtid: uuid(), + expiresIn: "1 day", + ...options, + issuer: tenant.id, + subject: user.id, + algorithm, + } + ); export const signPATString = async ( { algorithm, secret }: JWTSigningConfig, user: User, - options: SigningTokenOptions + options: SigningTokenOptions, + now = new Date() ) => - jwt.sign({ pat: true }, secret, { + jwt.sign({ pat: true, iat: dateToSeconds(now) }, secret, { ...options, subject: user.id, algorithm, diff --git a/src/core/server/services/users/index.ts b/src/core/server/services/users/index.ts index 5cd42b09a..6431e028b 100644 --- a/src/core/server/services/users/index.ts +++ b/src/core/server/services/users/index.ts @@ -275,16 +275,21 @@ export async function createToken( const result = await createUserToken(mongo, tenant.id, user.id, name, now); // Sign the token! - const signedToken = await signPATString(config, user, { - // Tokens are issued with the token ID as their JWT ID. - jwtid: result.token.id, + const signedToken = await signPATString( + config, + user, + { + // Tokens are issued with the token ID as their JWT ID. + jwtid: result.token.id, - // Tokens are issued with the tenant ID. - issuer: tenant.id, + // Tokens are issued with the tenant ID. + issuer: tenant.id, - // Tokens are not valid before the creation date. - notBefore: Math.round(DateTime.fromJSDate(now).toSeconds()), - }); + // Tokens are not valid before the creation date. + notBefore: 0, + }, + now + ); return { ...result, signedToken }; }