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

NestJS中使用SuperTokens管理会话遇权限验证及路由问题

问题:NestJS中SuperTokens AuthGuard验证失败,返回未授权

我在NestJS应用中使用supertokens-node库管理用户,通过SuperTokens的verifySession方法实现了AuthGuard来保护部分路由,但用Postman测试时一直返回未授权。

实现的AuthGuard代码

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly verifyOptions?: VerifySessionOptions) {}
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const ctx = context.switchToHttp();

    let err = undefined;
    const resp = ctx.getResponse();
    // You can create an optional version of this by passing {sessionRequired: false} to verifySession
    await verifySession(this.verifyOptions)(ctx.getRequest(), resp, (res) => {
      err = res;
    });

    if (resp.headersSent) {
      throw new STError({
        message: 'RESPONSE_SENT',
        type: 'RESPONSE_SENT',
      });
    }
    if (err) {
      throw err;
    }
    return true;
  }
}

应用AuthGuard的端点代码

@Post('/bulkAddUpdate')
@UseGuards(new AuthGuard())
async builkAddUpdate(
  @Body() bulkData: any,
  @Session() session: SessionContainer
) {
  console.log(session.getUserId());

  const user = await this.applicationService.bulkAction(bulkData.data);
  if (user) {
    return utils.sendSuccess(SUCCESS.S200.DEFAULT, user);
  } else {
    throw new NotFoundException();
  }
}

测试异常情况

  • 按SuperTokens文档,登录时设置请求头rid:session会返回404路由不存在,移除该头后登录正常;
  • 访问受保护路由时设置rid:session头,返回未授权。

测试用cURL请求:

curl --location --request POST 'http://localhost:9000/applications' \
--header 'rid: thirdpartyemailpassword' \
--header 'Content-Type: application/json' \
--header 'Cookie: pga4_session=887a38e7-589c-4faa-9bbe-139e9145b535!iTseBPH6uzAlV9Mbaap/agtBJ6GymXNDEp+4cgySEdA=; sFrontToken=eyJ1aWQiOiJkMzU0ZTJlOS1hNGVlLTQwOGYtYTQ5My0yYjQ1NjBhYWFiYzkiLCJhdGUiOjE2NzU0MjMzODc4NDAsInVwIjp7ImlzUGFzc3dvcmRsZXNzIjpmYWxzZX19; sIRTFrontend=d131494f-dbd8-4a21-a5a8-3959bb2d4fd1' \
--data-raw '{
    "userID": 2,
    "applicationContent": "<html><body>Anything...</body></html>",
    "applicationType": 200
}'

解决方案

1. 修正AuthGuard中verifySession的调用方式

原代码使用回调函数处理错误的方式不符合异步逻辑,改用try/catch直接捕获验证异常:

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly verifyOptions?: VerifySessionOptions) {}
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const ctx = context.switchToHttp();
    const req = ctx.getRequest();
    const resp = ctx.getResponse();

    try {
      // 直接await verifySession的执行结果,无需回调
      await verifySession(this.verifyOptions)(req, resp);
      return true;
    } catch (err) {
      if (resp.headersSent) {
        throw new STError({
          message: 'RESPONSE_SENT',
          type: 'RESPONSE_SENT',
        });
      }
      throw err;
    }
  }
}

2. 正确设置rid请求头

  • 登录接口(thirdpartyemailpassword)对应的rid值是thirdpartyemailpassword,而非session,手动设置rid:session会导致路由匹配失败,返回404;
  • 受保护路由的会话验证不需要手动添加rid头,SuperTokens SDK会自动处理路由标识,手动添加反而会干扰验证流程。

3. 检查会话凭证与CORS配置

  • 确保请求中的sFrontToken和Cookie是登录后获取的有效凭证,过期或篡改的令牌会触发未授权;
  • 在NestJS主文件中配置正确的CORS规则,允许携带Cookie:
// main.ts
app.enableCors({
  origin: ['http://localhost:3000'], // 替换为你的前端域名
  credentials: true,
});

4. 确认@Session()装饰器的配置

确保已在应用模块中正确注册SuperTokens模块:

import { Module } from '@nestjs/common';
import { SuperTokensModule } from 'supertokens-node/nestjs';

@Module({
  imports: [
    SuperTokensModule.forRoot({
      connectionURI: "你的SuperTokens实例地址",
      apiKey: "你的API密钥(如有)",
      appInfo: {
        appName: "你的应用名称",
        apiDomain: "http://localhost:9000",
        websiteDomain: "http://localhost:3000"
      },
      recipeList: [/* 你使用的SuperTokens recipe,比如ThirdPartyEmailPassword.init() */]
    }),
  ],
})
export class AppModule {}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:21:31