A Verified Email Is the Whole Claim
Signing in with a provider hands you an email address and a claim about whether it was verified. Treat the address as identity without reading the claim and you have built an account takeover that works on anybody whose address somebody can guess.
Single sign-on looks like it removes a security decision and it moves one. The provider tells you who somebody is; you decide what that entitles them to. In between sits a field almost nobody reads, and reading it is the difference between a sign-in method and a way in.
What the provider actually hands over
A successful handshake yields an identifier for the account with that provider, an email address, and — crucially — a statement about whether the provider has confirmed the person controls that address.
Those last two are different things, and the gap between them is the whole problem. An email address on a provider profile can be one the person typed in. Verified means the provider proved they control it.
Without that claim, an email address in an identity payload is a self-declared string, and matching an account on it is matching on something anybody can type.
The attack, spelled out
-
Somebody creates an account with a provider
Their own account, entirely legitimately, on a provider that lets a profile address be set without proving it.
-
They set the address to a colleague's
Unverified. The provider knows it is unverified, which is why it publishes the claim.
-
They sign in to your product
The handshake succeeds, because they really do control the provider account.
-
And the product matches on the address
If it never read the claim, they are now signed in as their colleague.
No credential was stolen, no system was compromised, and nothing in any log looks unusual — the sign-in succeeded, from a real provider account, for an address that really does belong to that user.
So the connector refuses an unverified address outright, with a message saying which provider and what is wrong. It is one condition, and everything else rests on it.
Verified means different things to different providers
The complication is that there is no universal way to ask. Providers publish this differently, and one of them does not publish it at all.
| How a provider says it | What is checked |
|---|---|
| A dedicated claim in the payload | The claim is read and must be affirmative |
| The presence of a directory-owned principal name | That the identity belongs to an organisation directory rather than a personal account |
| Nothing — the provider resolves it before answering | That an address is present at all, since the provider only returns verified ones |
So the test is defined per provider rather than shared, and adding a provider means deciding explicitly how that provider proves an address rather than inheriting somebody else's answer.
That is more work and it is the only correct arrangement. A shared test would be right for one provider and would silently accept unverified addresses from the others — the exact failure the check exists to prevent, reintroduced by generalising it.
Where an address is required to be well-formed before any of this, that is checked first, so a malformed value never reaches a comparison against an account.
Matching is exact, and linking is recorded
With a verified address in hand, the account is found by exact match. Not similar, not case-insensitive-plus-normalisation, not ignoring the parts of an address some providers treat as interchangeable. Exact.
When a match is found, the provider identity is linked to that account so future sign-ins resolve directly rather than by matching again. And that linking is written to the audit trail as its own event.
The audit entry is the part worth defending. Linking an identity to an account is a security-relevant change — it creates a new way into that account — and it happens automatically, during an ordinary sign-in, with nobody clicking anything. An automatic security change with no record is exactly the thing an audit trail exists for.
And the case that is refused rather than resolved
One situation is deliberately not automated, and the choice is instructive.
If an address already has a different provider account linked to it, sign-in is refused. Not re-linked, not linked as a second identity — refused, with a message naming the alternatives: sign in with the account that is linked, or use another method and re-link from the profile.
Automatically re-linking would mean anybody who could get a verified address at a provider could replace the existing link and take over the account. Refusing costs a person one extra step and keeps the change deliberate, performed by somebody already signed in.
It is a good example of a rule worth generalising: automate the case where the outcome is unambiguous, and refuse the case where it is a decision. Matching an address with no existing link is unambiguous. Replacing one is a decision.
No account, no silent creation
A verified identity with no matching account is not turned into an account.
Started from a sign-in screen, that is somebody trying to sign in to something they do not have. Started from a registration screen, it is exactly the expected case — and the verified identity is carried into the signup form rather than a workspace being created behind them.
Signing up is a decision with commercial and organisational consequences: a workspace exists, an owner is named, a plan begins. It should be the result of somebody completing a form, not a side effect of a handshake they may have started by clicking the wrong button.
What is in place, layer by layer
What a provider identity is allowed to do
Unverified addresses refused
A provider identity whose address has not been proven is turned away with a reason, because matching an account on an unproven address is a takeover.
Verification defined per provider
Each provider's own way of stating it is read, rather than one shared test that would be right for one and wrong for the rest.
Address format checked first
A malformed value never reaches a comparison against an account.
Exact matching only
No normalisation, no near matches, no ignoring parts of an address that some providers treat as interchangeable.
Linking written to the audit trail
Attaching a provider identity to an account creates a new way in, happens automatically during sign-in, and is recorded as its own event.
An existing link never replaced silently
A different provider account already linked to an address causes a refusal naming the alternatives, rather than a takeover by re-linking.
No silent account creation
A verified identity with no account carries into the signup form rather than creating a workspace behind somebody.
Linking from a profile verified too
Attaching a provider to an account you are already signed in to requires the same proof, so the profile route is not a way around it.
The verification claim is the foundation. Every other decision here — matching, linking, refusing — assumes the address has been proven, and none of them is safe without it.
Three positions held on purpose
- An unverified address is refused rather than treated as weaker evidence. There is no safe reduced treatment: the address is either proven or it is a string somebody typed, and matching an account on the second is the whole attack.
- Verification is defined per provider rather than shared. A common test would be correct for one provider and would silently accept unproven addresses from every other — reintroducing the exact failure by generalising the fix.
- An existing link is never replaced automatically. Automating the unambiguous case and refusing the case that is a decision is what keeps a convenience from becoming a takeover path.
Five questions about sign-on identity
Do you check the email is verified?
A good answer sounds like
Yes, and refuse otherwise.
What ours actually is
An unverified provider address is turned away with a reason naming the provider.
How do you match to an account?
A good answer sounds like
Exactly.
What ours actually is
An exact address match, with no normalisation or near matching.
Is linking recorded?
A good answer sounds like
In the audit trail.
What ours actually is
Attaching an identity creates a new way in and is written as its own event.
What if another provider account is already linked?
A good answer sounds like
Refused.
What ours actually is
Sign-in stops with a message naming the alternatives, rather than re-linking.
Does signing in create an account if there is none?
A good answer sounds like
No.
What ours actually is
The verified identity is carried into the signup form; a workspace is never created behind somebody.
Our take
Single sign-on gets adopted as a security improvement and it is one — provided you read the field that says whether the thing you are matching on was proven. Skip it and you have not weakened your authentication, you have replaced it with the ability to type an address into a profile somewhere. The field is right there in the payload, it takes one condition to check, and it is genuinely easy to miss because the handshake succeeds either way and the address looks identical. If you have implemented this yourself, that condition is worth going and finding this afternoon.
Check the claim, not just the address
A provider identity carries a statement about whether the address was proven. Everything you do with that address rests on reading it.
Talk through sign-in securityFrequently asked questions
What happens if our Google account email is not verified?
Sign-in is refused, with a message saying the address must be verified first. An unverified address on a provider profile is a value somebody typed rather than one the provider proved, and matching an account on it would let anybody sign in as anybody whose address they knew.
How is a provider identity matched to our account?
By an exact match on the verified email address. No normalisation, no near matching, and no ignoring the parts of an address some providers treat as interchangeable — those conveniences are how two different addresses become one account.
Is it recorded when a provider identity is linked?
Yes, as its own audit event. Linking creates an additional way into an account and it happens automatically during an ordinary sign-in, which is exactly the kind of change that should leave a record.
What if somebody else has already linked a Google account to our address?
Sign-in is refused with a message naming the options: use the account that is linked, or sign in another way and re-link from the profile. Replacing the link automatically would let anybody with a verified address at that provider take over the account.
Does signing in with Google create an account if we do not have one?
No. Coming from the sign-in screen, that is somebody trying to reach something they do not have. Coming from registration, the verified identity is carried into the signup form so the account is created by somebody completing it — not as a side effect of a handshake.