An account system that never asks for your email
Aug 25, 2026 · MolGameCat
The reason we added sign-in at all was the leaderboard. We wanted daily, weekly and
monthly halls of fame — which, it turns out, don't need accounts: pick a random ID per
browser and count people with that. What needed an account was identity:
one "me" across devices, one "me" across games, and ownership of a nickname — before, anyone
could type someone else's name.
So we put one principle in front while building it. The less you collect, the
less you can lose.
We store exactly three things
- Which provider you signed in with — Kakao, Naver or Google
- A hash of the member ID the provider gives us. The original is never
stored. Every sign-in hashes it the same way and compares, so we never need the original,
and if the table leaked, that value alone can't be traced back to your provider account.
- A nickname. Chosen by you, owned first-come. Names that differ only in
case count as the same name — treat them as different people and impersonation just
works.
Email, real name and profile photo are neither requested nor stored. Naver sends email and
name along regardless; the server discards them on the spot without reading them. What you
don't hold can't leak, and the privacy policy gets shorter.
No sign-ups under 14
Korean privacy law requires a legal guardian's consent to collect personal data from
anyone under 14. Running that verification properly is beyond a project this size. So the
sign-up screen says "14 and over", and children play everything without an
account. To move devices they use an 8-digit transfer code — the shortest thing a
child can copy down, deleted automatically after 7 days. The account isn't required; it's an
option for people who want it.
Collecting less meant less review
This was an unexpected bonus. Social sign-in usually comes with a review per provider;
we needed only Naver's. Kakao requires converting to a business app if you
ask for email, and Google treats email as a sensitive scope that triggers review — by not
asking for email we avoided both. If "let's collect email too" ever comes up, that trade-off
has to be recomputed.
Sign-out and deletion are immediate
The cookie holds one random key pointing at a session row on the server.
A signed token carrying its own contents would work too, but then sign-out and deletion
become "wait for it to expire". With a table, deleting the row ends the session that instant.
Deleting an account actually deletes the rows rather than flagging them — with
only a hash and a nickname on file, there's no reason to hesitate.
Progress follows the account
A few days after launch: "I played in the KakaoTalk browser, switched to Safari, same
account, and my achievements were gone." The sign-in cookie crosses browsers; the progress
had only ever lived in one. So distance, best scores and unlocked costumes are now kept with
the account too, and the server looks at them only to merge — the higher
value wins for distance and scores, achievements are unioned. That way an empty profile in a
fresh browser can never overwrite what the account already holds.
We count visits ourselves
We wanted to know roughly how many people sign up, visit and stay. A third-party analytics
tag is one line — but it sends visitor data out, and that didn't sit with the account
principle. So we built a first-visit counter ourselves. The IP is kept only as
a hash mixed with that day's date and a secret. We can count "people who came today", but not
who they are or whether they came yesterday — the hash changes completely with the date. It
was designed to be useless for advertising or re-identification.
The
privacy policy was written from this code. When the account
code changes, that page changes with it — a policy that contradicts the code is worse in
review than none at all.