Supabase auth replaced end-to-end with Cognito User Pool, Identity Pool, and Amplify

dropthejase completes a full Supabase-to-Cognito auth migration across 25 commits: CDK stacks, API Gateway authorizer, frontend contexts, signup/login flows, and user deletion. The access-token versus id-token gotcha for AgentCore calls (`95d538d`) is a real footgun worth knowing about before you start.

securitycompliance

The sequence matters. An initial AuthStack adds a Lambda Token authorizer that validates Supabase JWTs against the JWKS endpoint (0ae592f). This gets replaced within the same feature branch by a native API Gateway Cognito User Pools authorizer (810abde), eliminating the Lambda cold-start on every request. The old authorizer Lambda is deleted in d6dbb5e.

On the frontend, Amplify Auth lands as a thin wrapper module (dfd69c1), then AuthContext and AwsContext are rewritten to call fetchAuthSession and getIdToken() instead of supabase.auth.getSession() - that call-site replacement happens across eight files in 358951f. The signup page picks up email verification and a TOTP MFA setup flow (99aa05a).

Two architectural decisions are worth calling out. First, the pre-token-generation Lambda injects role: "authenticated" into id tokens to satisfy Supabase RLS - but Supabase RLS is later removed when Aurora replaces Supabase Postgres, so the Lambda becomes dead weight and is removed in 5e6962d. Don't import it unless you're keeping Supabase on the database side. Second, user deletion: the pattern in 2847ef2 cascades all user data synchronously inside DELETE /user/account before calling AdminDeleteUser, which is the right shape for any compliance-driven delete requirement.

The AgentCore token bug (95d538d) is concrete: AgentCore's JWT authorizer validates the client_id claim, which is present in the Cognito access token but absent from the id token. The fork initially sent the id token, got failures, and fixed it to send the access token instead. The allowedAudience field in the AgentCore authorizer config also needed removing (ecc808c). If you integrate Cognito + AgentCore, read those two commits before wiring anything.

TOTP MFA goes through two reversals: disabled (943914b) then re-enabled as optional (7d621a0). The final state is optional TOTP.

So what Worth a look if you're migrating away from Supabase auth on AWS. The synchronous cascade-then-delete pattern for account deletion (`2847ef2`) and the access-token fix for AgentCore (`95d538d`) are the most transferable pieces. Avoid importing the Identity Pool wiring unless you also keep direct browser-to-S3 uploads - it's removed later in the fork when presigned URLs take over.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

25 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
0ae592f4 feat(infra): add AuthStack with Identity Pool, Lambda authorizer, per-user S3 policy Jason Lee 2026-05-06 ↗ GitHub
2d294a87 feat(infra): add pre-token-gen Lambda for Cognito role claim injection Jason Lee 2026-05-07 ↗ GitHub
810abdef feat(infra): Cognito User Pool (TOTP MFA, strong passwords, required attrs); native API Gateway Cognito authorizer Jason Lee 2026-05-07 ↗ GitHub
d6dbb5ef chore(infra): delete unused Lambda Token authorizer Jason Lee 2026-05-07 ↗ GitHub
c95ee849 feat(backend): read userId from Cognito authorizer claims instead of Lambda context Jason Lee 2026-05-07 ↗ GitHub
dfd69c1b feat(frontend): Amplify Auth module; update Identity Pool to use Cognito id token Jason Lee 2026-05-08 ↗ GitHub
559f50b7 feat(frontend): rewrite AuthContext and AwsContext to use Amplify Auth instead of supabase.auth Jason Lee 2026-05-08 ↗ GitHub
358951f9 feat(frontend): replace supabase.auth.getSession() with getIdToken() across all callers Jason Lee 2026-05-08 ↗ GitHub
99aa05a4 feat(frontend): signup page with email verification and TOTP MFA setup flow Jason Lee 2026-05-08 ↗ GitHub
67850660 feat(frontend): login page using Amplify signIn Jason Lee 2026-05-08 ↗ GitHub
28290d3c feat(task-13): env vars, replace supabase direct query with backend session-id endpoint Jason Lee 2026-05-08 ↗ GitHub
f99ecb08 docs: update README and ARCHITECTURE for Cognito User Pool auth migration Jason Lee 2026-05-08 ↗ GitHub
396019f8 docs: redraw architecture diagram to show Cognito User Pool, Pre-Token Gen Lambda, Identity Pool Jason Lee 2026-05-08 ↗ GitHub
fe40ca91 feat(auth): post-confirmation and post-deletion lambdas, move supabase secret to AuthStack Jason Lee 2026-05-08 ↗ GitHub
ce910c1e feat: replace Supabase deleteUser with Cognito AdminDeleteUser Jason Lee 2026-05-08 ↗ GitHub
DELETE /user/account now calls AdminDeleteUserCommand. Lambda role gets
cognito-idp:AdminDeleteUser on the user pool ARN. USER_POOL_ID injected
as Lambda env var from CDK.
5e6962d9 Remove pre-token-gen Lambda (Supabase RLS role claim, unused on Aurora) Jason Lee 2026-05-08 ↗ GitHub
2847ef2b fix(backend): cascade delete user data before Cognito AdminDeleteUser Jason Lee 2026-05-08 ↗ GitHub
30088221 feat(infra): store email in user_profiles on Cognito post-confirmation Jason Lee 2026-05-08 ↗ GitHub
7b649fc4 Remove post-deletion Lambda (redundant - DELETE /user/account already cascades synchronously) Jason Lee 2026-05-08 ↗ GitHub
0a1d1a51 Merge feature/cognito-auth: AWS migration complete (Aurora, AgentCore, Cognito) Jason Lee 2026-05-09 ↗ GitHub
943914bd chore: disable TOTP MFA on Cognito User Pool Jason Lee 2026-05-09 ↗ GitHub
95d538d8 fix: use access token for AgentCore calls (id token missing client_id claim) Jason Lee 2026-05-11 ↗ GitHub
ecc808c6 fix: remove allowedAudience from AgentCore JWT authorizer config Jason Lee 2026-05-11 ↗ GitHub
fdffba97 docs(readme): add MFA configuration note Jason Lee 2026-05-15 ↗ GitHub
7d621a00 feat(auth): enable optional TOTP MFA on Cognito User Pool Jason Lee 2026-05-15 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-336.md from inside the repo you want the changes in.

⬇ Download capture-thread-336.md