Ошибка с passport js vkontakte(nest js)
Всем привет. Я пытаюсь настроить выполнение входа через vk, для этого использую @nestjs/passport passport-vkontakte. Собственно, почти такой же функционал я уже реализовал для входа ччерез google и там все работает хорошо. Но при входе через вк, почему-то, возникает ошибка VKontakteStrategy: verify callback must take 4 or 5 parameters. Все те параметры, которые должна принимать функция она принимает. Но, кажется, VKStrategy вызывает, почему-то, не тот метод. Я открыл исходный код, где как раз и высчитавается количество аргументов, которое принимает метод, поставил там console.log(verify.length), которые выводит значение 0.
Вот код моей стратегии:
import {Injectable} from "@nestjs/common";
import {PassportStrategy} from "@nestjs/passport";
import {Strategy, Profile, VerifyCallback} from "passport-vkontakte";
import {HelperService} from "../../helper/helper.service";
@Injectable()
export class VKStrategy extends PassportStrategy(Strategy, "vkontakte") {
constructor(private helperService: HelperService) {
super({
clientID: process.env.VK_CLIENT_ID,
clientSecret: process.env.VK_SECRET,
callbackURL: process.env.VK_REDIRECT_URI,
scope: ['profile'],
});
}
async validate(accessToken: string, refreshToken: string, profile: Profile, done: VerifyCallback): Promise<any> {
console.log('verify')
const payload = this.helperService.createAuthPayload(profile);
done(null, payload);
}
}
Ответы (2 шт):
я не так давно тоже столкнулся с этой проблемой - насколько я понял в пакете passport-vkontakte реализация немного отличается от остальных (могу судить по Google и Yandex, подключение которых было идентичным). В данном случае метод validate(...) не вызовется, вместо него нужно передать обработчик в конструкторе вторым аргументом после options примерно так:
constructor(private helperService: HelperService) {
super({
clientID: process.env.VK_CLIENT_ID,
clientSecret: process.env.VK_SECRET,
callbackURL: process.env.VK_REDIRECT_URI,
scope: ['profile'],
}, function (
accessToken: string,
refreshToken: string,
params: Params,
profile: Profile,
done: VerifyCallback
) {
// ...какая-то логика
return done(null, {
profile: {
name: profile.displayName,
// ...любые другие данные
}
});
});
}
После этого данные будут доступны в в колбеке после редиректа в req.user.profile
Мне помог комментарий с ответом. Скину немного доработанную версию, как оставить логику через метод validate + возможность использовать заинжекченные сервисы
import { Injectable, Inject } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, Params, Profile, VerifyCallback } from 'passport-vkontakte';
import { ConfigService } from '@nestjs/config';
import { AuthService} from '../servcies/AuthService';
@Injectable()
export class VkStrategy extends PassportStrategy(Strategy, 'vk') {
private authService: AuthService; // Объявляем свойство с сервисом
constructor(
private readonly configService: ConfigService,
@Inject(AuthService) authService: AuthService, // инжектим сервис
) {
super({
clientID: configService.get<string>('VK_CLIENT_ID'),
clientSecret: configService.get<string>('VK_CLIENT_SECRET'),
callbackURL: configService.get<string>('SERVER_HOST') + '/api/auth/vk/callback',
scope: ['email'],
profileFields: ['id', 'displayName'],
},
// Явно задаём функцию обработчик
async (
accessToken: string, refreshToken: string, params: Params,
profile: Profile, done: VerifyCallback) => {
return this.validate(
accessToken, refreshToken, params, profile, done);
});
this.authService = authService; // Передаём сервис в свойство
}
async validate(
accessToken: string,
refreshToken: string,
params: Params,
profile: Profile,
done: VerifyCallback,
) {
const { id, displayName } = profile;
// Используем подключённый сервис
const user = await this.authService.validateOauthUser(displayName, id);
return done(null, user);
}
}