PeS*_*PeS 4 authentication node.js passport-twitter passport.js nestjs
所以,我几乎完成了在 NestJS 支持的应用程序中实现社交登录的尝试。但我有一些问题:
首先要事。我有AuthModule并且那里有提供者TwitterGuard:
const twitterOptions: IStrategyOptionWithRequest = {
consumerKey: process.env[ENV.SOCIAL.TWITTER_CONSUMER_KEY],
consumerSecret: process.env[ENV.SOCIAL.TWITTER_CONSUMER_SECRET],
callbackURL: process.env[ENV.SOCIAL.TWITTER_CALLBACK_URL],
passReqToCallback: true,
includeEmail: true,
skipExtendedUserProfile: false,
};
export class TwitterGuard extends PassportStrategy(Strategy, 'twitter') {
constructor() {
super(twitterOptions);
}
// Magical nest implementation, eq to passport.authenticate
validate(req: Request, accessToken: string, refreshToken: string, profile: Profile, done: (error: any, user?: any) => void) {
const user: SocialAuthUser = {
id: profile.id,
nick: profile.username,
name: profile.displayName,
};
if (profile.emails) {
user.email = profile.emails.shift().value;
}
if (profile.photos) {
user.avatar = profile.photos.shift().value;
}
done(null, user);
}
}
Run Code Online (Sandbox Code Playgroud)
也AuthController:
@Controller('auth')
@ApiUseTags('auth')
export class SocialAuthController {
constructor(private us: UserService) {
}
@Get('twitter')
@UseGuards(AuthGuard('twitter'))
twitter() {
throw new UnauthorizedException();
}
@Get('twitter/callback')
@UseGuards(AuthGuard('twitter'))
async twitterCallback(@ReqUser() socialUser: SocialAuthUser, @Res() response) {
const user = await this.us.registerSocialUser(socialUser);
if (user) {
// console.log('Redirect', '/some-client-route/token');
response.redirect(`${SITE_URL}/activate/${user.token}`);
}
response.sendStatus(401);
}
}
Run Code Online (Sandbox Code Playgroud)
当我调用 URL 时,/auth/twitter警卫启动并重新路由到 Twitter 页面,要求用户授予对 Twitter 应用程序的访问权限。
如果用户授予访问权限,一切都很好,在回调路由 ( /auth/twitter/callback)上TwitterGuard,再次启动并处理用户validate,存储到request,我可以在控制器中进一步访问它。到目前为止,一切都很好。
但是,如果用户拒绝访问 Twitter 应用程序,则即使在我的任何方法被命中之前,守卫也会在回调路由上返回 401。
我尝试使用authenticate被调用的方法(现在在代码中注释掉),我可以在其中以某种方式调整它,但不知道要返回或做什么。如果这是一种方法,我如何像护照策略那样从那里重定向到 Twitter 身份验证页面?回调中返回什么以继续并设置一些访问被拒绝的标志?
还有其他方法吗?我缺少什么?
提前致谢。
编辑:如果您有疑问做什么@ReqUser(),这里是:
export const ReqUser = createParamDecorator((data, req): any => {
return req.user;
});
Run Code Online (Sandbox Code Playgroud)
没关系,我找到了解决方案,这个答案很有帮助。在这里发帖以防其他人遇到同样的麻烦。
我创建TwitterAuthGuard:
export class TwitterAuthGuard extends AuthGuard('twitter') {
handleRequest(err, user, info, context) {
return user;
}
}
Run Code Online (Sandbox Code Playgroud)
并在回调路由中使用它:
@Get('twitter/callback')
@UseGuards(TwitterAuthGuard)
async twitterCallback(@ReqUser() socialUser: SocialAuthUser, @Res() response) {
if (socialUser) {
const user = await this.us.registerSocialUser(socialUser);
if (user) {
response.redirect(`...url`);
return;
}
}
response.redirect(SocialAuthController.authFailedUrl(LoginMethod.TWITTER));
}
Run Code Online (Sandbox Code Playgroud)
现在,当 Twitter 调用回调路由时,它会进入TwitterAuthGuard handleRequest方法。
如果授予访问权限,user则参数包含来自用户配置文件的数据,并沿着链进一步传递到TwitterGuard validate方法(参见上面的问题)。
如果访问被拒绝,则user参数为false。
因此,在控制器回调路由方法中,我获取标准化的用户数据或false参数user,因此我可以检查它是否失败并采取相应的行动。