【问题标题】:How to add additional properties to JwtPayload type from @types/jsonwebtoken如何从 @types/jsonwebtoken 向 JwtPayload 类型添加其他属性
【发布时间】:2021-09-24 22:58:43
【问题描述】:

我是 typescript 的新手,我正在尝试移植一个 express 应用程序以使用 typescript。服务器使用 JWT 进行身份验证/授权,我有一个实用程序函数可以解码和验证给定的令牌。该函数封装在一个 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 类型以添加​​角色属性?我尝试定义自己的自定义类型并完全覆盖从 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) => {

谢谢。

【问题讨论】:

    标签: typescript types jwt definitelytyped express-jwt


    【解决方案1】:

    使用扩展的 Payload 重新声明 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
        }
    }
    

    【讨论】:

      【解决方案2】:

      您应该可以通过declaration merging 实现此目的。

      在你的代码中添加这个:

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

      这应该可以根据需要扩展接口。

      【讨论】:

      • 谢谢!我试过这个,但是我没有在模块名称周围加上“”。因此它没有携带,我认为这不是正确的做法。干杯。
      • 这仅适用于您只需要解析一种类型的 JwtPayload 对吗?
      • @pasquers 如果你有几种类型,你可以使用联合类型。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 1970-01-01
      相关资源
      最近更新 更多