所以,我几乎已经完成了在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);
}
/* authenticate(req: Request, options?: any): void {
console.log(req.body);
// super.(req, options);
}*/
// 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);
}
}
以及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);
}
}
当我呼叫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;
});
答案 0 :(得分:0)
没关系,我找到了解决方法,this answer帮了大忙。如果有人遇到同样的麻烦,请在此处发布。
我创建了export class TwitterAuthGuard extends AuthGuard('twitter') {
handleRequest(err, user, info, context) {
return user;
}
}
:
@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));
}
并将其用于回调路由:
TwitterAuthGuard
现在,当Twitter调用回调路由时,它将进入handleRequest
user
方法。
如果授予访问权限,则TwitterGuard
参数包含来自用户配置文件的数据,并进一步沿链向下传递到validate
user
方法(请参见问题上方)。
如果访问被拒绝,则false
参数为false
。
因此,在控制器回调路由方法中,我可以在user
参数中获取规范化的用户数据或sv.data() + sv.size() < s.data() + s.size()
,因此我可以检查其是否失败并采取相应措施。