Let me tell you about the time I wrote a document called AUTH_INVESTIGATION.md. And then, when that didn't work, wrote SECOND_AUTH_INVESTIGATION.md.
The existence of the second document tells you everything you need to know about AWS Cognito.
The Pattern That Saved Every Hard Problem After This One
- Hit the wall. AI gets you 80% fast. The last 20% is where the real engineering happens.
- Write an investigation doc. Not code. A document. What you tried. What happened. What you expected vs. what you observed.
- Feed the document to Claude. Not as a prompt. As a file in the project. Let it read the whole thing.
- If that doesn't work, write another document and ask Claude to compare both.
"Fix my auth" is a terrible prompt. "Here are two weeks of structured findings in AUTH_INVESTIGATION.md and SECOND_AUTH_INVESTIGATION.md, synthesize a unified solution" is a great one.
Your debugging context is valuable. Don't throw it away between sessions. Write it down, store it in the project, and let the AI compound on your investigation work. Claude produced a working auth flow in one session after reading both documents. Not because it's magic, but because I'd done the investigation work that gave it enough structured context to reason about the problem correctly.
Why Cognito Is Genuinely Hard
When you're stuck long enough, you start writing documents about being stuck. This is either mature engineering practice or a cry for help. I maintain it was both.
Cognito is genuinely, architecturally complex:
Three token types that look identical. ID Token (who you are), Access Token (what you can do), Refresh Token (get new ones). They're all JWTs. They all look the same in your browser's DevTools. Mix them up and you get errors that don't tell you what you mixed up.
Hosted UI vs. Custom UI. The hosted UI works but looks like a government login page from 2014. The custom UI looks right but breaks in ways that are impossible to debug. NotAuthorizedException could mean wrong password, expired token, wrong client ID, wrong pool ID, or misconfigured app client settings. It means all of these things and tells you none of them.
The production-only logout bug. After weeks of getting auth working, I discovered logout was broken, but only in production. Next.js Server Actions with redirect() behave differently deployed than in development. The final fix:
} finally {
// Always redirect to login, regardless of API response
router.push("/admin/login");
router.refresh();
}
"Always redirect to login, regardless of API response." This is the "I'm done debugging this" school of authentication engineering.
What Claude Couldn't Fix
Here's the real lesson: AI doesn't eliminate complexity. It compresses the time to encounter it.
With Claude, I hit the Cognito wall on day 2 instead of day 20. The basic setup (user pool, app client, hosted UI) happened in a single session. Then I spent three weeks on edge cases that exist at the boundaries between services, where Cognito meets Next.js meets browser security policies meets your specific deployment configuration.
Claude can write the code. It can't predict which combination of settings will produce a NotAuthorizedException in production but not in development. The integration boundaries, where services meet your specific configuration, are still yours to debug.
What Claude can do is help you investigate faster. But only if you give it structured context instead of frustrated one-liners.
The Takeaway
Some things are just hard, regardless of who's typing. AI-assisted development doesn't mean "everything is easy now." It means "you encounter the hard parts faster, and you have a better process for investigating them." That process (hit wall, write doc, feed to AI, iterate) became my default workflow for every hard problem after Cognito.
If you find yourself writing SECOND_AUTH_INVESTIGATION.md, you're either building character or you need a different auth provider. Both are valid conclusions.