Jwt 格式错误。向服务器发出身份验证请求

问题描述 投票:0回答:1

我正在使用 Angular、NestJS 和 PostgreSQL 构建全栈项目。尝试使用 Auth0 构建 Authn 和 Authz。用户可以将数据存储在数据库中,其中一列是来自 Auth0 的唯一子 ID。我的想法是:当用户登录客户端并想要检索数据时,向服务器发出请求,其中应该使用 DB-Sub 检查客户端 JWT-Sub。

所以问题来了。检索客户端令牌并将其发送到服务器,但此 Guard 出现错误:

PS:快速编辑。当我在 Postman 中手动传递 JWT 令牌时,请求正常,数据已完全检索。也许是客户端的问题?

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  handleRequest(
    ...args: Parameters<
      InstanceType<ReturnType<typeof AuthGuard>>['handleRequest']
    >
  ) {
    console.log(args);
    return super.handleRequest(...args);
  }
}

这是错误:

[
  null,
  false,
  JsonWebTokenError: jwt malformed
      at module.exports [as verify] (C:\Projects\dnd-server\node_modules\jsonwebtoken\verify.js:70:17)
      at module.exports [as JwtVerifier] (C:\Projects\dnd-server\node_modules\passport-jwt\lib\verify_jwt.js:4:16)
      at C:\Projects\dnd-server\node_modules\passport-jwt\lib\strategy.js:104:25
      at JwtStrategy.secretProvider [as _secretOrKeyProvider] (C:\Projects\dnd-server\node_modules\jwks-rsa\src\integrations\passport.js:42:14)
      at JwtStrategy.authenticate (C:\Projects\dnd-server\node_modules\passport-jwt\lib\strategy.js:99:10)
      at attempt (C:\Projects\dnd-server\node_modules\passport\lib\middleware\authenticate.js:378:16)
      at authenticate (C:\Projects\dnd-server\node_modules\passport\lib\middleware\authenticate.js:379:7)
      at C:\Projects\dnd-server\node_modules\@nestjs\passport\dist\auth.guard.js:88:3
      at new Promise (<anonymous>)
      at C:\Projects\dnd-server\node_modules\@nestjs\passport\dist\auth.guard.js:80:83,
  ExecutionContextHost {
    args: [ [IncomingMessage], [ServerResponse], [Function: next] ],
    constructorRef: [class CharacterController],
    handler: [AsyncFunction: findOne],
    contextType: 'http',
    getRequest: [Function: getRequest],
    getResponse: [Function: getResponse],
    getNext: [Function: getNext]
  },
  undefined
]

这是我的

auth.strategy.ts

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import * as jwksRsa from 'jwks-rsa';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      // Extract JWT from the Authorization header
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),

      // Validate the token's issuer and audience
      issuer: `https://${process.env.AUTH0_DOMAIN}/`,
      audience: process.env.AUTH0_AUDIENCE,

      // Use Auth0's public key to verify the token's signature
      secretOrKeyProvider: jwksRsa.passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
      }),

      algorithms: ['RS256'],
    });
  }

  async validate(payload: any) {
    return {
      sub: payload.sub, // 'sub' claim
    };
  }
}

这是我的

character.controller.ts
,我从数据库检索数据:

import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  Req,
  UseGuards,
} from '@nestjs/common';
import { CharacterService } from './character.service';
import { Character } from './character.model';
import { JwtAuthGuard } from 'src/auth/auth.guard';

@Controller('character')
export class CharacterController {
  constructor(private readonly characterService: CharacterService) {}

  @Post()
  async create(@Body() character: Character): Promise<Character> {
    const createdCharacter = await this.characterService.create(character);
    console.log('Character created successfully:', createdCharacter);
    return createdCharacter;
  }

  @Get(':id')
  @UseGuards(JwtAuthGuard)
  async findOne(@Param('id') id: string, @Req() req): Promise<Character> {
    const sub = req.user?.sub;
    if (!sub) {
      console.error("The 'sub' parameter is undefined or null.");
      throw new Error("Invalid 'sub' parameter");
    }

    console.log('Server SUB:', sub);

    const character = await this.characterService.findOne(+id);
    if (!character) {
      console.error(`Character with ID ${id} not found.`);
      throw new Error('Character not found');
    }

    if (character.sub !== sub) {
      console.error(
        `Server SUB ${sub} does not match character sub ${character.sub}.`,
      );
      throw new Error('Unauthorized access');
    }

    return character;
  }
}

这是我的

creator.component.ts
的一部分,我试图向服务器发出请求:

saveFormDataToFile() {
    const data = this.characterCreationForm.value;
    this.http.post("http://localhost:3000/character", data).subscribe(
      (response) => {
        console.log("Form data saved successfully:", response);
      },
      (error) => {
        console.error("Error saving form data:", error);
      }
    );
  }

  retrieveFormDataFromServer(id: number) {
    const authToken = this.auth.idTokenClaims$;

    authToken.subscribe((token) => {
      if (token) {
        const headers = new HttpHeaders().set(
          "Authorization",
          `Bearer ${token.__raw}`
        );

        console.log("FULL TOKEN:", token);
        console.log("Access token retrieved successfully:", token.__raw);
        this.http
          .get(`http://localhost:3000/character/${id}`, { headers })
          .subscribe(
            (response: any) => {
              console.log("Form data retrieved successfully:", response);
              this.characterCreationForm.patchValue(response);
            },
            (error) => {
              console.error("Error retrieving form data:", error);
            }
          );
      } else {
        console.error("Error retrieving access token.");
      }
    });
  }
angular jwt nestjs token auth0
1个回答
0
投票

我是个白痴。在我的角度 app.module.ts 中,它是: allowedList: ["http://localhost:3000/*"],

删除“*”,现在可以使用了。

© www.soinside.com 2019 - 2024. All rights reserved.