A user who registered in your Amazon Cognito user pool with email and password later signs in with "Continue with Google" and lands in an empty account with none of their data. Explain what Cognito did and how you would fix it.
answer
- email is a claim, not an identity
- each provider gets its own record
- two records, two different sub values
- link, but prove control first
- auto-merge on email is takeover
basics
~20 sCognito created a second, separate user in the pool for the Google identity, with its own sub, so your application saw a new customer. Fix it by linking the federated identity to the existing native user with the AdminLinkProviderForUser API, and only after proving the two really are the same person.
solid answer
~50 sFederated sign-in does not match on email. When a user pool receives a first-time assertion from an external provider, it provisions a **new** user record for that provider identity, distinct from any native user with the same address. Your app keys data on `sub`, sees a `sub` it has never met, and shows an empty account. The remedy is Cognito's `AdminLinkProviderForUser`, which attaches the external provider identity to an existing user pool user so subsequent federated sign-ins resolve to the original record and the original `sub`. Two cautions. First, if the duplicate has already been auto-created you generally have to remove it before linking. Second, and more important, linking on a matching email address is an account-takeover primitive if the provider's email is not genuinely verified — an attacker who can assert someone else's email at a sloppy IdP would inherit their account. Link only on a provider-verified email, or make the user prove control of the existing account first.
go deeper
Understand that signing in with Google creates a separate user record in the pool and that email addresses do not automatically join two accounts together.
Explain that sub differs between the native and federated records, and name account linking as the mechanism that makes both sign-ins resolve to one user.
Show the security reasoning: when auto-linking on email is an account-takeover path, and why proving control of the existing account before linking is the safe order.
Own where identity is anchored across the product — an internal user id with a provider mapping versus the pool's sub — and the migration cost of getting that wrong before launch.
## What actually happened A Cognito user pool treats each identity provider as a separate namespace. A native sign-up creates a user record authenticated by the pool itself. A federated sign-in through Google, Apple, an OIDC provider or a SAML IdP creates a *different* user record the first time that provider identity is seen, typically with a provider-prefixed username, populated from your attribute mapping. The two records have different `sub` values. Since `sub` is the stable identifier your application should be keying customer data on, the second sign-in looks to your system like an entirely new customer. Nothing malfunctioned; email addresses are simply not treated as identity by default, and for good reason — an email address is a claim from a provider, not a proof. ## Repairing it Cognito's remedy is `AdminLinkProviderForUser`. You call it with the destination user (the existing native account) and the source provider identity — the provider name and the attribute value that identifies the user there, typically the provider's subject identifier. After linking, a sign-in through that provider resolves to the destination user, returns that user's `sub`, and your application sees the original account. Two practical constraints shape how you deploy this: - **Link before the first federated sign-in if you can.** If the duplicate profile already exists, you generally must delete that auto-created user before the link will take, which means reconciling anything already written against the orphan `sub`. - **Linking is not unlimited.** A single user can carry only a small number of linked provider identities, so "link every provider a user ever touches" is not an unbounded strategy. A pre-sign-up Lambda trigger is the usual place to intervene: it fires when a federated user is about to be provisioned, and can look up an existing native user and perform the link before the duplicate is created. ## The security question that decides the design The naive implementation matches on email: "if a user with this email exists, link." This is where interviews go, because it is an account-takeover vector. If an identity provider will assert an `email` claim that the user has not proven control of, then anyone who can register that address at that provider inherits the corresponding account in your system — password, MFA and all, because federated sign-in bypasses both. Defensible approaches, roughly in order of strength: 1. **Do not auto-link.** Detect the collision, tell the user "an account with this email already exists — sign in with your password to connect Google", and perform the link only from inside an authenticated session. The user proves control of the existing account first. This is the answer that survives scrutiny. 2. **Auto-link only on a provider-verified email**, and only for providers you have specifically vetted as verifying it. Treat `email_verified` from an arbitrary OIDC provider as an assertion by that provider, not as a fact. 3. **Send a verification challenge** to the address before linking, which reduces the problem back to proving control of the mailbox. What you should not do is silently merge because two strings matched. ## The design decision behind it Stepping back, the durable lesson is where identity is anchored. If your application stores customer data keyed by the user pool `sub`, then anything that changes `sub` — a duplicate record, a pool migration, a provider switch — is a data-loss event from the user's point of view. Some teams therefore keep their own internal user identifier, map one-to-many from provider identities onto it in their own database, and treat the pool `sub` as merely one credential among several. That costs a table and a lookup, and it makes linking, unlinking and provider migration ordinary operations rather than emergencies. Whichever you choose, decide it before launch. Reconciling duplicated accounts after a year of production is a data migration with unhappy customers attached.
- Why is matching on email considered dangerous rather than convenient?Because the email claim is only as trustworthy as the provider asserting it. If an IdP will emit an address the user never proved control of, an attacker registers that address there, signs in federated, and is auto-merged into the victim's account — bypassing the victim's password and MFA entirely. Convenience here is a privilege-escalation path.
- Where in the sign-in flow would you intervene to link accounts automatically?In the pre-sign-up Lambda trigger, which fires before the pool provisions a federated user. It can detect an existing native user and perform the link there, so the duplicate is never created. That avoids the cleanup problem of linking after a duplicate profile already exists and has data written against it.
- How would you design so that a provider change is not a crisis?Do not let the identity provider's subject be your primary customer key. Keep your own internal user id, and maintain a mapping table from provider identities to it. Then adding a provider, linking a second one, or migrating pools is an insert into that table rather than a data migration, and the application layer never notices which credential was used.
saying these in an interview costs you the question
- Assumes Cognito merges accounts sharing an email
- Auto-links on email without verifying the provider asserts it
- Thinks federated users are not stored in the user pool
- Keys application data on an identifier that changes per provider
- Deletes the native account instead of linking the identity