typescript 如何从@types/jsonwebtoken向JwtPayload类型添加其他属性

y4ekin9u  于 2023-03-19  发布在  TypeScript
关注(0)|答案(3)|浏览(223)

我刚接触typescript,正在尝试移植一个express应用程序来使用typescript。服务器使用JWT进行身份验证/授权,我有一个实用函数来解码和验证给定的令牌。该函数被 Package 在一个promise中,这样我就可以在实现它的中间件中使用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
}

我的问题是来自@types/jsonwebtoken的JwtPayload的类型不包含role,因此当Promise解析时,我在尝试访问身份验证中间件中的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类型以添加role属性?我尝试定义自己的自定义类型并完全覆盖从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) => {

谢谢。

8tntrjer

8tntrjer1#

使用扩展的有效负载重新声明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
    }
}
xzabzqsa

xzabzqsa2#

您应该能够通过声明合并来实现这一点。
在代码的某个地方添加以下内容:

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

这应该可以扩展您想要的接口。

5anewei6

5anewei63#

import { Jwt } from 'jsonwebtoken';

export type Token = Jwt;

相关问题