yikart/AiToEarn · error · UnauthorizedException

需要管理员权限2

Error message

需要管理员权限2

What it means

The catch-all of ManagerGuard.canActivate: any failure during jwtService.verifyAsync (expired token, bad signature, malformed token) is swallowed and rethrown as UnauthorizedException '需要管理员权限2'. This masks the underlying JWT error, so any invalid manager token produces this message — including the inner '需要管理员权限1' being caught and replaced.

Source

Thrown at project/aitoearn-electron/server/src/auth/manager.guard.ts:62

    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);
    if (!token) {
      throw new UnauthorizedException('token不存在,需要管理员权限');
    }

    try {
      const payload = await this.jwtService.verifyAsync(token, {
        secret: process.env.AUTH_SECRET,
      });

      if (!payload.isManager) {
        throw new UnauthorizedException('需要管理员权限1');
      }

      request['user'] = payload;
    } catch {
      throw new UnauthorizedException('需要管理员权限2');
    }
    return true;
  }

  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Re-login as manager to get a fresh valid token.
  2. Refactor the catch to rethrow the inner UnauthorizedException instead of masking it.
  3. Log the original error in the catch block to see whether it was expiry, signature, or the isManager check.
  4. Confirm AUTH_SECRET env var is set and identical on all instances.

Example fix

// before
} catch {
  throw new UnauthorizedException('需要管理员权限2');
}
// after
} catch (e) {
  if (e instanceof UnauthorizedException) throw e;
  throw new UnauthorizedException('需要管理员权限2');
}
Defensive patterns

Strategy: try-catch

Validate before calling

function tokenLooksValid(token) {
  const t = token.replace(/^Bearer\s+/, '');
  if (t.split('.').length !== 3) return false;
  const payload = JSON.parse(atob(t.split('.')[1]));
  return payload.exp * 1000 > Date.now() && payload.isManager === true;
}

Try / catch

try {
  await adminApi.call(managerToken);
} catch (e) {
  if (e?.response?.status === 401 && e.message.includes('需要管理员权限2')) {
    await reloginAsManager(); // verify 失败:过期/签名错误/格式错误,重新登录
  } else throw e;
}

Prevention

When it happens

Trigger: verifyAsync throws — expired JWT, wrong AUTH_SECRET, malformed token, or the inner UnauthorizedException from the isManager check being caught by this catch block.

Common situations: Expired manager session; secret mismatch after deploy; debugging confusion because the '权限1' message never surfaces and always becomes '权限2'.

Related errors


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