使用@ AuthGuard,Passport

时间:2019-11-08 17:36:38

标签: node.js authentication passport.js nestjs passport-twitter

所以,我几乎已经完成了在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;
});

1 个答案:

答案 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() ,因此我可以检查其是否失败并采取相应措施。