Teaching a face-scan login to ask: "Is this still your number?"
Our insurance site logs people in with a face scan through MyID, Uzbekistan's national ID system. A face proves who you are - but not how to reach you. I rebuilt the login so that every sign-in also checks whether the phone number on the account is still real.

On gross.uz, an insurance website used by tens of thousands of people, you can log in with a face scan - no password, no typing. It works through MyID, the national digital ID service. Sounds perfect. But it hid a quiet problem: the system knew who you were, yet often had no idea how to reach you.
The problem, in plain terms
When you log in by face, the system finds your account through your passport data. The phone number sitting on that account might be five years old - from a SIM card you threw away long ago.
Why does that matter? Because that number is where everything important goes:
- confirmation codes and payment messages,
- policy notifications,
- account recovery if something goes wrong.
A wrong phone number is a silent time bomb. And there was a second twist: one passport can end up with several accounts over the years - and the old login just picked one for you, without asking.
One rule fixed both: a code you type is the only proof
MyID does send us a phone number along with the passport data. But it's a snapshot with no date on it - nobody can say when it was last checked. So I made a strict rule: the only proof that a number is yours is a code we text you, that you type back. Everything else is just a hint.
The new login flow follows that rule:
- You pass the face scan as before.
- If your number was confirmed within the last 6 months - you go straight in. Nothing changes for you.
- If it's older than that (a "stale" account), a small window appears: enter your current number, get an SMS code, type it in - done.
- If several accounts share your passport, the number you confirm also chooses which account you enter.
The nice side effect: the user база heals itself. Every login quietly refreshes the one piece of data that goes stale the fastest.
What I built
The work spanned both halves of the product:
- On the server (PHP): after a successful scan, the system now decides instead of blindly logging in. When a check is needed, it hands the browser a short-lived signed "ticket" - it contains no personal data at all and dies in 10 minutes, so it's useless to steal.
- In the browser (Nuxt/Vue): a clean verification window - phone field, a "Get code" button with an anti-spam countdown, and wording that adapts: it says one thing when you're confirming your own number, another when the number picks between accounts.
- Nothing is ever lost: when someone attaches a new number, the old one isn't overwritten - it's moved into a history log, so support can always see the full story of an account.
What I'm proud of
The restraint. The obvious path was to build new infrastructure; instead I reused the SMS-code system the site already trusted for years, and put the whole feature on top of it. No new moving parts, no new places to break - just one new rule, enforced everywhere: *if we haven't heard from your phone in six