通过 `passport-jwt` 使用 Auth0 进行 NestJS 身份验证
NestJS Authentication with Auth0 via `passport-jwt`
我正在尝试使用 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.界面
/* 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
WITH 的获取请求导致错误 {"statusCode":401,"error":"Unauthorized"}
.
可以在 https://github.com/jajaperson/nest-auth0
找到完整的源代码
提前致谢;
詹姆斯·詹森
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.
UPDATE
I managed to get NODE_EXTRA_CA_CERTS
to work, causing me to jump up and
down screaming ecstatically.
我所要做的一切(一旦我停止获得 UNABLE_TO_VERIFY_LEAF_SIGNATURE
)
错误,我所要做的就是 return 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;
}
}
找到完整的(现在可以使用的)源代码
我正在尝试使用 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.界面
/* 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
WITH 的获取请求导致错误 {"statusCode":401,"error":"Unauthorized"}
.
可以在 https://github.com/jajaperson/nest-auth0
找到完整的源代码提前致谢;
詹姆斯·詹森
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) errorSSL 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 dangerousNODE_TLS_REJECT_UNAUTHORIZED=0
(I have tried usingNODE_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.UPDATE
I managed to get
NODE_EXTRA_CA_CERTS
to work, causing me to jump up and down screaming ecstatically.
我所要做的一切(一旦我停止获得 UNABLE_TO_VERIFY_LEAF_SIGNATURE
)
错误,我所要做的就是 return 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;
}
}
找到完整的(现在可以使用的)源代码