asp.net服务器生成的JWT令牌未被nodejs服务器读取,且具有相同的密钥

asp.net服务器生成的JWT令牌未被nodejs服务器读取,且具有相同的密钥,asp.net,jwt,nestjs,passport-jwt,Asp.net,Jwt,Nestjs,Passport Jwt,我们有ASP.NET WEB API服务器盒为经过身份验证的用户生成JWT令牌。服务器正在使用一个秘密:secret。这些令牌被发送回我们的UI,所有API调用都使用该令牌显示 最近,我们开始在nestjs中编写更新的服务,并使用@nestjs/passport、passport jwt库进行授权。我们的UI将开始使用这些新API,因此我们希望通过ASP.NET WEB API服务器生成的相同令牌来授权用户。我认为这将是直截了当的,因为我只需要使用相同的秘密来解码令牌:secret。但在建立jw

我们有ASP.NET WEB API服务器盒为经过身份验证的用户生成JWT令牌。服务器正在使用一个秘密:secret。这些令牌被发送回我们的UI,所有API调用都使用该令牌显示

最近,我们开始在nestjs中编写更新的服务,并使用@nestjs/passport、passport jwt库进行授权。我们的UI将开始使用这些新API,因此我们希望通过ASP.NET WEB API服务器生成的相同令牌来授权用户。我认为这将是直截了当的,因为我只需要使用相同的秘密来解码令牌:secret。但在建立jwt战略后,我一直从nestjs获得401

尝试使用相同的秘密从nestjs创建一个令牌并使用它,结果成功了。但是ASP.NET服务器生成的令牌不起作用

从ASP.NET WEB API创建令牌的方法: (注:key=SECRET)

NestJS Passport设置: (注意:jwtConfig.secret=secret)

战略:

export class JwtStrategy extends PassportStrategy(Strategy) {

  constructor(
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: config.get('jwt.secret')
    });
  }

  async validate(payload: JwtPayload) {

    const user = <find user>;
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

预计将解密令牌,但在调用生命周期的早期就获得401。

您在ASP.NET中创建令牌的代码是错误的,因为您只使用
base64编码。
结果是一个包含保留字符的令牌(
+
/
=

JWT使用
base64Url编码
(请参阅),避免使用这些字符。这些是URI的保留字符(参见中的第2.2节),在JWT中不允许使用,因为有时令牌作为url中的参数传输

建议的解决方案是使用。在您的代码中,您是在手动执行操作(这对于学习目的很有好处),因此,要实现这种方式,您需要将
base64
编码结果转换为
base64url
编码

这可以通过
字符串来完成。替换

string payloadEncoded = UTF8Bas64Encode(payload).TrimEnd('=').Replace('+', '-').Replace('/', '_');

当然,标题和签名也是如此

这是正确的。我设法使用NestJS内部使用的
jws
模块调试令牌,并发现
jws
库中的以下行失败:

var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;

function isValidJws(string) {
  return JWS_REGEX.test(string) && !!headerFromJWS(string);
}

此外,当我查看令牌时,我发现Base64列表()中没有字符

对于C#,我切换到
System.IdentityModel.Tokens.Jwt
类,它工作了。这个类按照规范进行编码和必要的字符替换,所以我建议其他人使用它。直到现在,我们的JWT代币还没有用于系统外的索赔,因此问题没有引起注意

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiAiNDE3MSIsIlNlc3Npb25JZCI6ICI2Yjg2M2I2NS02YTM1LTQ1NDQtOTllNy0yMmJjMzEzY2M1YTMifQ==.bu+GZ+tq+Wc1Srvp/0u7jMvqBnDJqd2N5xWx2dItxlA=
string payloadEncoded = UTF8Bas64Encode(payload).TrimEnd('=').Replace('+', '-').Replace('/', '_');
var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;

function isValidJws(string) {
  return JWS_REGEX.test(string) && !!headerFromJWS(string);
}