Skip to main content

Case Study: The 401 Unauthorized Mystery

📌 What is this for? (Quick Summary for New Interns)​

In Simple Words:
When testing locally on localhost:5173, user login succeeded, but every single API call afterwards returned 401 Unauthorized and the dashboard sat on GATEWAY OFFLINE. At the exact same time, the deployed site at dashboard.tutr.tech worked fine!

Why? Our local .env file was logging into an old staging user pool (bg6ZECDii), while our cloud API Gateway was set up to only accept tokens from the production user pool (IXNCZVwj4).

This page explains how we used Chrome DevTools Protocol to inspect the live tokens and fix it in minutes.


1. What Happened?​

  • The Symptoms:
    • You open http://localhost:5173 and log in with username thirumalai and password.
    • The login works! Amplify says: "Signed in successfully!"
    • But immediately on the main dashboard, your console turns red with:
      apiClient.js:74 POST https://npig3gpgck.execute-api.ap-south-1.amazonaws.com/api 401 (Unauthorized)
      Telemetry Sync Error: Error: Unauthorized
    • The pod wouldn't move, and the battery buttons were disabled.

2. How We Diagnosed It​

We attached a WebSocket debugger to the browser and inspected the token payload in localStorage:

{
"iss": "https://cognito-idp.ap-south-1.amazonaws.com/ap-south-1_bg6ZECDii",
"aud": "7br9pgbrnsuvrr3gfao7v48u21",
"cognito:username": "thirumalai"
}

Notice the issuer: ap-south-1_bg6ZECDii!
Then we inspected the AWS API Gateway authorizer configuration:

  • Authorizer Name: CognitoAuth
  • Expected Issuer: https://cognito-idp.ap-south-1.amazonaws.com/ap-south-1_IXNCZVwj4
  • Expected Audience: 5eup0104notrn3fn4415u3fq3b

The Aha! Moment:​

There were two user pools in AWS history:

  1. bg6ZECDii: An old testing pool.
  2. IXNCZVwj4: The real production pool.

Because the user thirumalai existed in both pools, the login worked, but the token came from the wrong pool. When API Gateway inspected the token, it saw iss: bg6ZECDii instead of iss: IXNCZVwj4 and rejected it immediately!


3. How to Fix It​

  1. Update .env in your dashboard folder:

    VITE_MAIN_API_URL=https://npig3gpgck.execute-api.ap-south-1.amazonaws.com/api
    VITE_USER_POOL_ID=IXNCZVwj4
    VITE_COGNITO_CLIENT_ID=5eup0104notrn3fn4415u3fq3b
    VITE_REGION=ap-south-1
  2. Update defaults in src/main.jsx:

    const DEFAULT_CLIENT_ID = "5eup0104notrn3fn4415u3fq3b";
    const DEFAULT_USER_POOL_ID = "IXNCZVwj4";
  3. Clear your browser's local storage and log in again: Run localStorage.clear() in your browser console to wipe the old token, refresh, and log in fresh. Data will immediately begin streaming with 200 OK.