通过``passport-jwt''与Auth0进行NestJS身份验证 [英] NestJS Authentication with Auth0 via `passport-jwt`

查看:101
本文介绍了通过``passport-jwt''与Auth0进行NestJS身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用passport-jwt库(与@nestjs/passport结合使用)创建一个使用Auth0进行身份验证的NestJS项目,尽管我无法使其正常工作.我不确定我要去哪里.我已经读了一遍又一遍的文档,但是仍然找不到问题.

I'm trying to create a NestJS project that uses Auth0 for authentication, with the passport-jwt library (in conjunction with @nestjs/passport), though I am unable to get it to work. I'm not sure where I'm going wrong. I've read the docs over and over again but still can't find the problem.

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"}.

A get request to localhost:3000/protected WITH a valid bearer token results in the error {"statusCode":401,"error":"Unauthorized"}.

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

预先感谢;
詹姆斯·詹森

Thanks in advance;
James Jensen

更新

好吧,在放置了bodge-y包装函数 任何地方 之后,我认为 我发现了问题的根源:每次 secretOrKeyProvider函数运行, done 被调用时遇到了非常熟悉的错误(对我来说) SSL Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE.这是由于我学校的 烦人的防火墙/CA,这是我一生中最烦人的事情.这 到目前为止,我发现绕过这个问题的唯一方法就是做危险的事情 NODE_TLS_REJECT_UNAUTHORIZED=0(我尝试使用 NODE_EXTRA_CA_CERTS,但到目前为止我失败了.由于某些原因(尽管 可能是个不错的选择),我的解决方法在这种情况下不起作用.

UPDATE

Okay, after putting bodge-y wrapper functions EVERYWHERE, I think I've found the source of the problem: Every time the secretOrKeyProvider function is run, done gets called with the incredibly familiar (for me) error SSL Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE. This is due to my school's annoying firewall/CA, which is the most annoying thing in my life. The only way I've found to get around this so far is doing the dangerous NODE_TLS_REJECT_UNAUTHORIZED=0 (I have tried using NODE_EXTRA_CA_CERTS, but so far I've failed). For some reason (though probably a good one) my workaround doesn't work in this situation.

我设法使NODE_EXTRA_CA_CERTS正常工作,导致我跳了起来, 欣喜若狂地尖叫.

I managed to get NODE_EXTRA_CA_CERTS to work, causing me to jump up and down screaming ecstatically.

推荐答案

我所要做的(一旦我停止获取UNABLE_TO_VERIFY_LEAF_SIGNATURE) 错误,我所要做的就是返回payload如果有效.

All I had to do (once I stopped getting the UNABLE_TO_VERIFY_LEAF_SIGNATURE) error, all I had to do was return payload if it was valid.

@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 .

Again, full (now functional) source code can be found at https://github.com/jajaperson/nestjs-auth0.

这篇关于通过``passport-jwt''与Auth0进行NestJS身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆