【发布时间】:2020-09-01 23:12:27
【问题描述】:
我研究了 passport-facebook 和 passport-facebook-token 与 NestJS 的集成。问题在于 NestJS 使用自己的实用程序(例如 AuthGuard)抽象了护照实现。
因此,记录在案的ExpressJS 样式实现不适用于NestJS。例如,这不符合 @nestjs/passport 包:
var FacebookTokenStrategy = require('passport-facebook-token');
passport.use(new FacebookTokenStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET
}, function(accessToken, refreshToken, profile, done) {
User.findOrCreate({facebookId: profile.id}, function (error, user) {
return done(error, user);
});
}
));
This blog post 展示了一种使用不符合AuthGuard 的不熟悉接口实现passport-facebook-token 的策略。
@Injectable()
export class FacebookStrategy {
constructor(
private readonly userService: UserService,
) {
this.init();
}
init() {
use(
new FacebookTokenStrategy(
{
clientID: <YOUR_APP_CLIENT_ID>,
clientSecret: <YOUR_APP_CLIENT_SECRET>,
fbGraphVersion: 'v3.0',
},
async (
accessToken: string,
refreshToken: string,
profile: any,
done: any,
) => {
const user = await this.userService.findOrCreate(
profile,
);
return done(null, user);
},
),
);
}
}
这里的问题是,这似乎与 NestJS 期望您处理护照策略的方式完全不同。它是一起被黑的。它也可能在未来的 NestJS 更新中中断。这里也没有异常处理;我无法捕获 InternalOAuthError 之类的异常,这些异常由 passport-facebook-token 抛出,因为正在使用回调性质。
是否有一种干净的方法来实现passport-facebook 或passport-facebook-token 之一,以便它使用@nestjs/passport 的validate() 方法?来自文档:对于每个策略,Passport 将调用验证函数(使用 @nestjs/passport 中的 validate() 方法实现)。应该有办法在构造函数中传递一个clientId、clientSecret,然后把剩下的逻辑放到validate()方法中。
我会想象最终结果看起来类似于以下内容(这不起作用):
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import FacebookTokenStrategy from "passport-facebook-token";
@Injectable()
export class FacebookStrategy extends PassportStrategy(FacebookTokenStrategy, 'facebook')
{
constructor()
{
super({
clientID : 'anid', // <- Replace this with your client id
clientSecret: 'secret', // <- Replace this with your client secret
})
}
async validate(request: any, accessToken: string, refreshToken: string, profile: any, done: Function)
{
try
{
console.log(`hey we got a profile: `, profile);
const jwt: string = 'placeholderJWT'
const user =
{
jwt
}
done(null, user);
}
catch(err)
{
console.log(`got an error: `, err)
done(err, false);
}
}
}
在我的特殊情况下,我对callbackURL 不感兴趣。我只是在验证客户端已转发到服务器的访问令牌。我只是把上面说的很明确。
此外,如果您好奇,上面的代码会生成一个InternalOAuthError,但我无法在策略中捕获异常来查看真正的问题是什么,因为它没有正确实现。我知道在这种特殊情况下,我传递的access_token 是无效的,如果我传递一个有效的,代码就可以工作。通过适当的实现,虽然我将能够捕获异常、检查错误并能够向用户发出适当的异常,在本例中为 HTTP 401。
InternalOAuthError: Failed to fetch user profile
很明显,异常是在validate() 方法之外引发的,这就是为什么我们的try/catch 块没有捕获InternalOAuthError。处理此异常对于正常的用户体验至关重要,我不确定在此实现中 NestJS 处理它的方式是什么,或者应该如何进行错误处理。
【问题讨论】:
标签: node.js passport.js nestjs passport-facebook passport-facebook-token