All files / app/routes/auth/jwt jwt-util.ts

100% Statements 21/21
100% Branches 14/14
100% Functions 4/4
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 981x 1x 1x 1x                                 1x   374x 2x         372x                                           1x 177x 176x             1x                         1x 181x 12x     169x       169x     167x 167x   2x                 1x  
import config from '@config';
import jwt from 'jsonwebtoken';
import {User, UserDto} from '@models';
import {NotLoggedInError} from '@errors';
import {RequestHandler} from 'express';
 
/**
 * Generates a jwt token with the given payload.
 *
 * If the payload is an instance of the class {@link User}
 * and the csrf parameter is provided, the method
 * {@link generatePayloadFromUserModel} is used to
 * generate the payload from the user.
 * @param payload - Payload of the token
 * @param subject - If the payload is not an instance of the model User
 *                This parameter is needed to set the subject header
 *                in the jwt header.
 * @returns   The jwt which contains the given payload as data and the given
 *    subject in the sub field.
 */
export function generateToken(payload: Record<string, unknown>,
    subject?: string): string {
  if (payload instanceof User) {
    return jwt.sign(
        convertUserToJwtPayload(payload),
        config.jwt.secret,
        config.jwt.getOptions(payload.username));
  } else {
    return jwt.sign(
        payload,
        config.jwt.secret,
        config.jwt.getOptions(subject));
  }
}
 
export interface UserJwtPayload {
  username: string;
  id: number;
  isBetaUser: boolean;
  loggedIn: boolean;
}
/**
 * Generates the payload for a jwt token for the given user.
 *
 * The payload should includes the following:
 * - Username       `username`
 * - whether or not the user has beta access `isBetaUser`
 * @param user - The user for which the payload should be generated.
 * @returns   The user converted into a jwt payload
 */
export function convertUserToJwtPayload(user: User | UserDto): UserJwtPayload {
  if (user) {
    return {
      username: user.username,
      isBetaUser: user.isBetaUser,
      id: user.id,
      loggedIn: true,
    };
  } else {
    throw new TypeError('Can\' generate payload if ' +
        'no user is given');
  }
}
 
/**
 * Request handler which throws an `UnauthorizedError` if
 * the provided jwt token (which is expected to be in `req.auth`)
 * was created before the user logged in or after it.
 * @param req  - Http request
 * @param res  - Http response
 * @param next - Next handler
 */
export const postLoginJwtValidator: RequestHandler = (req, res, next) => {
  if (!req.auth || !req.auth.loggedIn || !req.auth.id) {
    next(new NotLoggedInError());
  } else {
    // Check if a user with the user id exists
    User.findByPk(
        req.auth.id,
        {attributes: {exclude: ['password']}},
    ).then((user) => {
      if (user !== null &&
          (user.deletedAt === null ||
            user.deletedAt >= new Date())) {
        req.user = user.get({plain: true}) as Express.User;
        next();
      } else {
        next(new NotLoggedInError());
      }
    });
  }
};
 
/**
 * Cookie options for the jwt. Same is in `config.jwt.cookieOptions`.
 */
export const cookieOptions = config.jwt.cookieOptions;