Skip to content

docs(verify): caveat that email proves control, not stable identity#276

Merged
umputun merged 1 commit into
go-pkgz:masterfrom
tsoderstrom:docs/verify-email-identity-caveat
May 6, 2026
Merged

docs(verify): caveat that email proves control, not stable identity#276
umputun merged 1 commit into
go-pkgz:masterfrom
tsoderstrom:docs/verify-email-identity-caveat

Conversation

@tsoderstrom
Copy link
Copy Markdown
Contributor

Summary

The verify provider derives the local user id from the verified address:

u := token.User{
    Name: user,
    ID:   e.ProviderName + "_" + token.HashID(sha1.New(), address),
}

The confirmation round-trip proves current control of the address at login time, but it does not guarantee a stable+unique identity over time. The owner of an address can change without the address changing — employer offboarding, recycled free-mail handles, recycled domains. Any application that keys its own records directly on the returned id will treat the new owner of an address as the original user.

This is inherent to email-as-identity (the verify flow has no upstream identifier such as an OIDC sub to fall back on), so the right fix is integrator-side: map the verified address to a server-side immutable user id at first verify and key application records on that id. But the property is non-obvious and easy to miss, so this PR documents it where readers will look.

Changes

Documentation only:

  • provider/verify.goVerifyHandler doc comment gains an "Identity caveat" paragraph pointing at the README section.
  • v2/provider/verify.go — same paragraph (v2 has no separate README, so the godoc link is the only in-package surface).
  • README.md — new #### Email-as-identity caveat subsection under Verified authentication, listing the failure modes (employer offboarding, lapsed free-mail accounts, recycled domains) and the integrator-side mitigation pattern. The tone matches the existing ### Allowed redirect hosts section.

No behaviour change.

Why now

Surfaced from a downstream identity-key audit (we work on a Paperclip company that hosts security-content reviews of OAuth/OIDC libraries). The verify flow's id derivation is technically correct for what go-pkgz/auth controls — there's nothing to fix in the library proper — but several integrators we surveyed had assumed the returned id was a stable account key rather than a live "currently controls this address" assertion. A documentation note seemed like the lowest-friction way to set expectations without changing behaviour or the API surface. Happy to drop, narrow, or split if you'd prefer.

Future direction (not in this PR)

If you'd be open to a follow-up, an IDFunc hook on VerifyHandler (mirroring the one already on direct.go) would let integrators substitute a registry-side immutable id without keeping a parallel mapping table. Filing this PR as docs-only first; happy to discuss a hook if you'd like.

The verify provider derives the local user id from the verified address
(ProviderName + "_" + HashID(address)). The confirmation round-trip
proves current control of the address at login time, but does not
guarantee a stable+unique identity over time -- the owner of an address
can change without the address changing (employer offboarding, recycled
free-mail handles, recycled domains). Any application that keys its own
records directly on the returned id will treat the new owner of an
address as the original user.

This is inherent to email-as-identity, not a bug in this library: the
verify flow has no upstream identifier (such as an OIDC sub) to fall
back on. The right place to address it is integrator-side -- map the
verified address to a server-side immutable user id at first verify --
but the property is non-obvious and easy to miss, so this commit calls
it out where readers will look:

  - VerifyHandler doc comment in provider/verify.go (v1)
  - VerifyHandler doc comment in v2/provider/verify.go
  - new "Email-as-identity caveat" subsection under "Verified
    authentication" in the root README

Documentation only; no behaviour change.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@tsoderstrom tsoderstrom requested a review from umputun as a code owner May 2, 2026 00:15
Copy link
Copy Markdown
Member

@umputun umputun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thx.

for the IDFunc hook idea, pls open a separate issue so we can discuss the v2 design there.

@umputun umputun merged commit 66189f0 into go-pkgz:master May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants