我目前面临使用 Google OAuth 进行身份验证的 Nest.js 应用程序的问题。 Nest.js 后端在端口 5000 上运行,前端 (Next.js) 在端口 3000 上运行。我已使用正确的源 URI 和重定向 URI 设置 Google Cloud Console,两者均设置为“http:// /本地主机:3000"。
我在前端 Next.js 中遇到以下错误
通过“https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000&scope=email%20profile&client_id=${GOOGLE_OAUTH_CLIENT_ID}”访问 XMLHttpRequest (从“http://localhost:5000/auth/google”重定向)来自源“http://localhost:3000”已被 CORS 策略阻止: 上不存在“Access-Control-Allow-Origin”标头请求资源。
GET https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000&scope=email%20profile&client_id=${GOOGLE_OAUTH_CLIENT_ID} 网络:: ERR_FAILED 302(已找到)
这是我的 Nest.js Auth 控制器、Google OAuth 策略和 Google OAuth Guard 的片段:
// Nest.js google oauth 策略
export class GoogleOAuthStrategy extends PassportStrategy(Strategy, 'google') {
constructor(private readonly configService: ConfigService) {
super({
clientID: configService.get('googleOAuthClientId'),
clientSecret: configService.get('googleOAuthClientSecret'),
callbackURL: configService.get('googleOAuthCallbackURL'),
scope: ['email', 'profile'],
});
}
async validate(
accessToken: string,
refreshToken: string,
profile: Profile,
done: VerifyCallback,
): Promise<any> {
const { id, name, emails, photos } = profile;
const user: User = {
type: 'individual',
email: emails[0].value,
firstName: name.givenName,
lastName: name.familyName,
picture: photos[0].value,
authenticationProviders: [{ name: 'google', id }],
};
done(null, user);
}
}
// Nest.js 谷歌 oauth 守卫
export class GoogleOAuthGuard extends AuthGuard('google') {
constructor() {
super({
accessType: 'offline',
});
}
}
// Nest.js 身份验证控制器
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('google')
@UseGuards(GoogleOAuthGuard)
async googleAuth() {
return HttpStatus.OK;
}
@Get('google-redirect')
@UseGuards(GoogleOAuthGuard)
googleAuthRedirect(
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
) {
return this.authService.login(req, res, 'google');
}
}
// Nest.js 身份验证服务
export class AuthService {
constructor(
private readonly configService: ConfigService,
private readonly usersService: UsersService,
private readonly jwtService: JwtService,
) {}
async login(req: Request, res: Response, provider: Provider): Promise<void> {
const user = req.user as User;
if (!user) {
throw new NotFoundException(`No user from ${provider}`);
}
let userPayload: User;
let accessTokenPayload: string;
const foundUser = await this.usersService.findByEmail(user.email);
if (foundUser) {
const providerExists = foundUser.authenticationProviders.some(
(provider) => provider.name === user.authenticationProviders[0].name,
);
// User found with different provider
if (!providerExists) {
foundUser.authenticationProviders.push(user.authenticationProviders[0]);
await foundUser.save();
}
userPayload = foundUser;
accessTokenPayload = foundUser._id.toString();
} else {
// Save user to mongodb if it does not exists already
const newUser = await this.usersService.create(user);
userPayload = newUser;
accessTokenPayload = newUser._id.toString();
}
const accessToken = this.jwtService.sign({ id: accessTokenPayload });
res.cookie('CARDTRIKA_ACCESS_TOKEN', accessToken, {
maxAge: this.configService.get('cookieMaxAge'),
httpOnly: true,
});
res.status(HttpStatus.OK).json({
statusCode: HttpStatus.OK,
success: true,
message: 'User information',
data: userPayload,
});
}
}
如果我直接从浏览器向
http:localhost:5000/auth/google
发出get请求,它会重定向到google api>同意屏幕,然后我可以通过gmail帐户登录,最后可以成功获取用户信息。
但 Next.js 却没有发生同样的情况。我一提出请求,它就说 CORS 错误。
很乐意为您提供帮助
我认为问题是您没有在后端设置
cors
域,以允许接收来自其他域的请求。
在引导程序中,写入
app.enableCors({origin: corsDomains})
,其中 corsDomains
是域数组,(例如 http://localhost:3000
)