yikart/AiToEarn · warning · BadRequestException

无效的state参数

Error message

无效的state参数

What it means

The 'state' query parameter in the OAuth callback must be a URI-encoded JSON string containing originalState, userId and email. If decodeURIComponent(state) or JSON.parse fails, BadRequestException '无效的state参数' (invalid state parameter) is thrown.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/youtube/youtube.controller.ts:86

  @Public()
  @Get('auth/callback')
  async handleAuthCallback(
    // @GetToken() systemToken: TokenInfo,
    @Query('code') code: string,
    @Query('state') state: string,
    // @Query('userId') userId: string,
    @Res() res: Response
  ) {

    if (!code || !state) {
      throw new BadRequestException('授权参数不完整');
    }
      // 解析state参数以获取token
      let stateData;
      try {
        stateData = JSON.parse(decodeURIComponent(state));
      } catch (error) {
        throw new BadRequestException('无效的state参数');
      }

      const { originalState, userId, email } = stateData;

      // 现在您可以使用token变量
      console.log('Retrieved userId and originalState:', userId, originalState, email);

    try {
      const results = await this.youtubeAuthService.handleAuthorizationCode(code, originalState, userId);
      // 重定向到前端页面,带上token
      // return res.redirect(`/auth/success?token=${token}`);
      // return results
      const render_msg = {
        message: "授权成功! 这里是添加账号成功后的前端页面," ,
        datas: results
      };

      return res.render('google/index', render_msg);

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. When creating the auth URL, always URI-encode the JSON: encodeURIComponent(JSON.stringify({originalState, userId, email}))
  2. Log the received raw state value before parsing to spot encoding issues
  3. Ensure no middleware/proxy double-decodes the query string
  4. Align the state schema between the code that builds the URL and the callback handler

Example fix

// before
const state = JSON.stringify({ originalState, userId, email }); // raw JSON in URL
const url = `${authUrl}&state=${state}`;
// after
const state = encodeURIComponent(JSON.stringify({ originalState, userId, email }));
const url = `${authUrl}&state=${state}`;
Defensive patterns

Strategy: type-guard

Validate before calling

const raw = decodeURIComponent(state);
const parsed = JSON.parse(raw); // wrap in try
if (!('originalState' in parsed) || !('userId' in parsed) || !('email' in parsed)) {
  throw new Error('state JSON missing required fields');
}

Type guard

function isValidState(v: unknown): v is { originalState: string; userId: string; email: string } {
  return !!v && typeof v === 'object' &&
    typeof (v as any).originalState === 'string' &&
    typeof (v as any).userId === 'string' &&
    typeof (v as any).email === 'string';
}

Try / catch

try {
  stateData = JSON.parse(decodeURIComponent(state));
  if (!isValidState(stateData)) throw new Error('bad state schema');
} catch {
  return res.status(400).send('invalid state');
}

Prevention

When it happens

Trigger: The state value was double-encoded or not encoded at all so JSON.parse receives malformed input; a client modified/truncated the state; the callback is invoked manually with a non-JSON state value.

Common situations: Building the auth URL manually and passing JSON without encodeURIComponent (raw {,}," characters break parsing after framework decoding); passing state that was already decoded once by a proxy; frontend builds state differently than the callback expects (schema mismatch).

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/15a70756f6a1167d. Report an issue: GitHub.