Итак, у меня почти закончена попытка реализовать социальный вход в приложение с поддержкой 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
метод, который вызывается (теперь закомментирован в коде), где я мог бы каким-то образом настроить это, но понятия не имею, что возвращать или делать. Если это путь, как мне перенаправить оттуда на страницу авторизации в твиттере, как это делает стратегия паспорта? Что вернуть при обратном вызове, чтобы продолжить работу и установить какой-то флаг, чтобы доступ был запрещен?
Есть ли другой способ сделать это? Что мне не хватает?
Заранее спасибо.
Редактировать: Если у вас есть вопросы, что делает @ReqUser()
, вот оно:
export const ReqUser = createParamDecorator((data, req): any => {
return req.user;
});