You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在NestJS中实现多ClientID/Secret的Passport谷歌、Facebook认证

实现NestJS多应用动态Passport认证(Google/Facebook)

核心需求

通过请求参数appID匹配数据库中对应应用的OAuth配置(clientID、clientSecret、callbackURL等),让不同应用使用专属密钥完成Google/Facebook认证。

具体实现方案

1. 自定义动态AuthGuard

替换默认AuthGuard,实现从请求中获取appID并动态加载应用配置:

import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthService } from './auth.service';

@Injectable()
export class DynamicGoogleAuthGuard extends AuthGuard('google') {
  constructor(private readonly authService: AuthService) {
    super();
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const appID = request.query.appID;

    // 从数据库查询对应应用的Google OAuth配置
    const oauthConfig = await this.authService.getAppOAuthConfig(appID, 'google');

    // 动态覆盖Passport认证配置
    this.authenticate(request, {
      clientID: oauthConfig.clientID,
      clientSecret: oauthConfig.clientSecret,
      callbackURL: oauthConfig.callbackURL,
      scope: oauthConfig.scope || ['email', 'profile'],
    });

    return super.canActivate(context);
  }
}

2. 调整GoogleStrategy为基础策略

移除硬编码配置,保留基础逻辑:

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      scope: ['email', 'profile'], // 默认权限,可被动态覆盖
    });
  }

  async validate(
    accessToken: string,
    refreshToken: string,
    profile: any,
    done: VerifyCallback,
  ): Promise<any> {
    // 可根据appID和用户信息完成关联逻辑
    const user = {
      email: profile.emails[0].value,
      firstName: profile.name.givenName,
      lastName: profile.name.familyName,
      avatar: profile.photos[0].value,
      accessToken,
    };
    done(null, user);
  }
}

3. 控制器使用自定义Guard

更新控制器,替换为动态Guard:

import { Controller, Get, Req, Query } from '@nestjs/common';
import { UseGuards } from '@nestjs/common';
import { DynamicGoogleAuthGuard } from './dynamic-google-auth.guard';
import { GoogleAuthService } from './google-auth.service';

@Controller('google-auth')
export class GoogleAuthController {
  constructor(private readonly googleAuthService: GoogleAuthService) {}

  @Get('login')
  @UseGuards(DynamicGoogleAuthGuard)
  login(@Query('appID') appID: string) {}

  @Get('redirect')
  @UseGuards(DynamicGoogleAuthGuard)
  redirect(@Req() req) {
    return this.googleAuthService.handleAuthSuccess(req.user);
  }

  @Get('status')
  status() {}

  @Get('logout')
  logout() {}
}

4. 实现配置查询服务

创建AuthService负责从数据库读取应用OAuth配置:

import { Injectable, NotFoundException } from '@nestjs/common';
import { AppRepository } from './app.repository';

@Injectable()
export class AuthService {
  constructor(private readonly appRepository: AppRepository) {}

  async getAppOAuthConfig(appID: string, provider: 'google' | 'facebook') {
    const app = await this.appRepository.findOne({ where: { id: appID } });
    if (!app) throw new NotFoundException('应用不存在');
    
    const config = app.oauthConfigs[provider];
    if (!config) throw new NotFoundException('该应用未配置对应认证服务');
    
    return config;
  }
}

5. 模块注入依赖

确保所有组件被正确注入:

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { GoogleStrategy } from './google.strategy';
import { GoogleAuthController } from './google-auth.controller';
import { GoogleAuthService } from './google-auth.service';
import { DynamicGoogleAuthGuard } from './dynamic-google-auth.guard';
import { AuthService } from './auth.service';
import { AppRepository } from './app.repository';

@Module({
  imports: [PassportModule],
  controllers: [GoogleAuthController],
  providers: [
    GoogleStrategy,
    GoogleAuthService,
    DynamicGoogleAuthGuard,
    AuthService,
    AppRepository,
  ],
})
export class AuthModule {}

Facebook认证复用逻辑

只需复制上述流程:

  • 创建FacebookStrategy继承PassportStrategy(Strategy, 'facebook')
  • 实现DynamicFacebookAuthGuard,查询配置时指定provider: 'facebook'
  • 控制器对应接口使用DynamicFacebookAuthGuard

内容的提问来源于stack exchange,提问作者umer jamal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:40:25