Как добавить дополнительные свойства к типу JwtPayload из @types/jsonwebtoken

Я новичок в машинописном тексте и экспериментирую с портированием экспресс-приложения для использования машинописного текста. Сервер использует JWT для аутентификации/авторизации, и у меня есть служебная функция, которая декодирует и проверяет данный токен. Функция заключена в обещание, поэтому я могу использовать async/await в промежуточном программном обеспечении, которое ее реализует.

import httpError from 'http-errors';
import jwt from 'jsonwebtoken';

const { ACCESS_TOKEN_SECRET } = process.env;

export function verifyAccessToken(token: string): Promise<jwt.JwtPayload | undefined> {
  return new Promise((resolve, reject) => {
    jwt.verify(token, ACCESS_TOKEN_SECRET as string, (err, payload) => {
      if (err) {
        return reject(new httpError.Unauthorized());
      }
      return resolve(payload);
    });
  });
}

Эта функция работает нормально, однако у меня есть дополнительная информация в JWT. В частности, у меня есть свойство role, поэтому полезная нагрузка имеет тип:

{
  sub: string,  // ID issued by mongoose
  role: string, // My new information that is causing error
  iat: number,
  exp: number
}

Моя проблема в том, что тип для JwtPayload из @types/jsonwebtoken не содержит role, поэтому, когда обещание разрешается, я получаю ошибку машинописного текста при попытке доступа к payload.role в промежуточном программном обеспечении аутентификации.

import { RequestHandler } from 'express';
import httpError from 'http-errors';
import { verifyAccessToken } from '../utils'

export const authenticate: RequestHandler = async (req, res, next) => {
  try {
    const authHeader = req.headers['authorization'] as string;
    if (!authHeader) {
      throw new httpError.Unauthorized();
    }

    const accessToken = authHeader.split(' ')[1];
    if (!accessToken) throw new httpError.Unauthorized();

    const payload = await verifyAccessToken(accessToken);
// If I try to access payload.role here I get an error that type JwtPayload does not contain 'role'

    next();
  } catch (err) {
    next(err);
  }
};

Как расширить тип JwtPayload, чтобы добавить свойство роли? Я попытался определить свой собственный пользовательский тип и полностью переопределить тип, возвращенный из jwt.verify(), но это выдает ошибку, что ни одна перегрузка не соответствует этому вызову.

interface MyJwtPayload {
  sub: string;
  role: string;
  iat: number;
  exp: number;
}

// ... then in the utility function replace jwt.verify() call with
jwt.verify(token, ACCESS_TOKEN_SECRET as string, (err, payload: MyJwtPayload) => {

Спасибо.


person Braden    schedule 16.07.2021    source источник


Ответы (2)


Вы должны иметь возможность добиться этого с помощью слияния объявлений .

Где-то в вашем коде добавьте это:

declare module "jsonwebtoken" {
    export interface JwtPayload {
        role: string;
    }
}

Это должно расширить интерфейс, как вы этого хотите.

person Krisztián Balla    schedule 18.07.2021
comment
Спасибо! Я пробовал это, однако не указал имя модуля. Следовательно, это не сработало, и я не думал, что это правильно. Ваше здоровье. - person Braden; 25.07.2021

повторно объявите модуль jsonwebtoken с расширенной полезной нагрузкой, затем проанализируйте/приведите проверенный токен соответствующим образом.

import * as jwt from 'jsonwebtoken'

declare module 'jsonwebtoken' {
    export interface UserIDJwtPayload extends jwt.JwtPayload {
        userId: string
    }
}

export const userIdFromJWT = (jwtToken: string): string | undefined => {
    try {
        const { userId } = <jwt.UserIDJwtPayload>jwt.verify(jwtToken, process.env.JWT_COOKIE_SECRET || 'MISSING_SECRET')

        return userId
    } catch (error) {
        return undefined
    }
}
person S..    schedule 03.08.2021