【问题标题】:NestJS Authentication with Auth0 via `passport-jwt`NestJS 通过 `passport-jwt` 使用 Auth0 进行身份验证
【发布时间】:2019-06-29 21:25:00
【问题描述】:

我正在尝试使用passport-jwt 库(与@nestjs/passport 一起)创建一个使用Auth0 进行身份验证的NestJS 项目,但我无法让它工作。我不确定我哪里出错了。我一遍又一遍地阅读文档,但仍然找不到问题。

代码

/src/auth/jwt.strategy.ts

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { passportJwtSecret } from 'jwks-rsa';
import { xor } from 'lodash';
import { JwtPayload } from './interfaces/jwt-payload.interface';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
      }),

      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      audience: 'http://localhost:3000',
      issuer: `https://${process.env.AUTH0_DOMAIN}/`,
    });
  }

  validate(payload: JwtPayload) {
    if (
      xor(payload.scope.split(' '), ['openid', 'profile', 'email']).length > 0
    ) {
      throw new UnauthorizedException(
        'JWT does not possess the requires scope (`openid profile email`).',
      );
    }
  }
}

/src/auth/interfaces/jwt-payload.interface

/* Doesn't do much, not really relevant */
import { JsonObject } from '../../common/interfaces/json-object.interface';

export interface JwtPayload extends JsonObject {
  /** Issuer (who created and signed this token) */
  iss?: string;
  /** Subject (whom the token refers to) */
  sub?: string;
  /** Audience (who or what the token is intended for) */
  aud?: string[];
  /** Issued at (seconds since Unix epoch) */
  iat?: number;
  /** Expiration time (seconds since Unix epoch) */
  exp?: number;
  /** Authorization party (the party to which this token was issued) */
  azp?: string;
  /** Token scope (what the token has access to) */
  scope?: string;
}

/src/auth/auth.module.ts

import { Module } from '@nestjs/common';
import { JwtStrategy } from './jwt.strategy';
import { PassportModule } from '@nestjs/passport';

@Module({
  imports: [PassportModule.register({ defaultStrategy: 'jwt' })],
  providers: [JwtStrategy],
  exports: [JwtStrategy],
})
export class AuthModule {}

/src/app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [AuthModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

/src/app.controller.ts

import { Controller, Get, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { AuthGuard } from '@nestjs/passport';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('protected')
  @UseGuards(AuthGuard())
  getProtected(): string {
    return 'This route is protected';
  }
}

localhost:3000/protected 的获取请求带有有效的不记名令牌会导致错误{"statusCode":401,"error":"Unauthorized"}

完整的源代码可以在https://github.com/jajaperson/nest-auth0找到

提前致谢;
詹姆斯詹森

更新

好的,在放入 bodge-y 包装函数 EVERYWHERE 之后,我想 我找到了问题的根源:每次 secretOrKeyProvider 函数运行, done 被极其熟悉的(对我来说)错误调用 SSL Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE。这是由于我学校的 烦人的防火墙/CA,这是我一生中最烦人的事情。这 到目前为止,我发现解决这个问题的唯一方法是做危险的 NODE_TLS_REJECT_UNAUTHORIZED=0(我试过用 NODE_EXTRA_CA_CERTS,但到目前为止我失败了)。出于某种原因(尽管 可能是一个好方法)我的解决方法在这种情况下不起作用。

更新

我设法让NODE_EXTRA_CA_CERTS 工作,让我跳起来 欣喜若狂地尖叫起来。

【问题讨论】:

  • 你确定你的validate函数被payload调用了吗?
  • @ChauTran 我该怎么做呢???关于这个的文档不是很清楚(或者至少对我来说不是:))。
  • 你把console.log放在验证方法中:)
  • 我会去做,然后回复你:))
  • @ChauTran 不,看起来不会。

标签: typescript jwt passport.js auth0 nestjs


【解决方案1】:

我要做的就是(一旦我停止收到UNABLE_TO_VERIFY_LEAF_SIGNATURE) 错误,我所要做的就是返回 payload 如果它是有效的。

/src/auth/jwt.strategy.ts

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
      }),

      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      audience: 'http://localhost:3000',
      issuer: `https://${process.env.AUTH0_DOMAIN}/`,
    });
  }

  validate(payload: JwtPayload): JwtPayload {
    if (
      xor(payload.scope.split(' '), ['openid', 'profile', 'email']).length > 0
    ) {
      throw new UnauthorizedException(
        'JWT does not possess the requires scope (`openid profile email`).',
      );
    }
    return payload;
  }
}

同样,完整(现在可以使用)源代码可以在 https://github.com/jajaperson/nestjs-auth0 找到。

【讨论】:

    猜你喜欢
    • 2019-03-28
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2016-06-25
    • 1970-01-01
    • 2021-09-25
    相关资源
    最近更新 更多