← All posts
·4 min read·Reuben Santoso

Claude Code Auth Bug: When Your AI Locks Users Out of Their Accounts

Claude Code inverts auth logic by default. Users locked out. Tests pass. api-doctor catches it before deploy.

Quick Answer

The classic Claude Code auth bug is authentication logic written backwards: the AI checks if (!user) where you meant if (user), or redirects on success instead of failure. Nobody can log in. The code compiles fine. The tests pass, because the AI wrote those too. And the whole thing only shows its face in production, right about when your users start emailing to say they're locked out.

The problem: auth logic is so easy to invert

Auth flows look simple, which is exactly why they bite. There are a dozen small ways to get them wrong. The model has seen heaps of auth code, some checking if (user), some checking if (!user), and it copies a shape without really grasping what the shape means. One stray ! and the whole thing runs backwards.

Here are the inversions I run into most.

Wrong: redirecting on success instead of failure

if (response.ok) {
  window.location.href = '/login-failed'; // wrong
} else {
  window.location.href = '/dashboard';    // wrong
}

Wrong: checking the token before it's even set

// This runs BEFORE useEffect
if (!user) {
  return <Redirect to="/login" />; // always fires before auth loads
}

useEffect(() => {
  loadUser(); // token loads here, too late
}, []);

A real example: the Firebase auth timing trap

Your AI hands you a component that checks auth state with the condition reversed:

useEffect(() => {
  auth.onAuthStateChanged((user) => {
    if (!user) {
      // "If no user, set logged in to true" (backwards)
      setIsLoggedIn(true);
    }
  });
}, []);

Follow the sequence and it's almost funny. A user shows up, isLoggedIn starts false, so they see the login page. Then onAuthStateChanged fires, sees no user, and sets isLoggedIn to true. Now they're staring at the dashboard while Firebase still considers them logged out. Everything downstream falls apart.

Firebase's docs put it plainly: a non-null user means logged in, null means logged out. The AI just got the condition exactly backwards.

How api-doctor catches this

✗ Firebase: 1 issue

  firebase-auth-inverted-logic
    src/App.tsx:12
    Authentication logic is inverted. Redirecting logged-out users instead of logged-in.
    Severity: critical
    Security

How to fix it: get the logic right

export default function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((firebaseUser) => {
      setUser(firebaseUser ?? null);
      setLoading(false);
    });
    return unsubscribe;
  }, []);

  if (loading) return <LoadingSpinner />;

  // user is not null = logged in
  return user ? <Dashboard user={user} /> : <LoginPage />;
}

And for the redirects:

const handleLogin = async (email, password) => {
  const response = await fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify({ email, password }),
  });

  if (!response.ok) {
    setError('Login failed'); // failure = show error
  } else {
    window.location.href = '/dashboard'; // success = redirect
  }
};

Frequently asked questions

Q: Why does this happen so often? Inverted auth logic shows up all over the training data. The model picks up several patterns at once and occasionally crosses the wires, especially between providers that each use slightly different conventions.

Q: How can api-doctor catch a logical inversion? It ships provider-specific rules that look for inverted conditionals, backwards redirect logic, and missing loading states, one set per auth provider.

Q: What if I test this locally? Here's the catch. If your AI-generated tests are inverted the same way the code is, they'll pass while the app is broken. You need deterministic rules that compare against known-correct patterns, not tests written by the same model that wrote the bug.

Q: Is this only a Firebase thing? Not at all. Auth0, Clerk, Supabase Auth, and the rest have their own timing traps and inverted-logic failure modes.

Next Steps

Try api-doctor

Deterministic AST rules for AI-generated API integrations. Not a prompt.

npx @api-doctor/cli .