FocusBottle, and the Sign-In That Needed No Identity Service

2026-09-27 · 4 min read

Nineteen minutes into a FocusBottle block my hand drifted toward the phone and the light in the bottle dimmed before it got there. I had gone to look up how other apps handle login. Nearly all of them hand the whole question to someone else — and it turns out you do not have to.

Nothing between you and the timer

FocusBottle keeps almost nothing in front of you on purpose. You pick twenty-five, fifty or ninety minutes, and a bottle of small light particles dims as your attention drifts. There is no account, no preferences screen, no setup step standing between you and the block you sat down to do.

That is exactly why, the week sign-in finally became necessary, I wanted the smallest version of it. I was nineteen minutes into a fifty-minute session when my hand went toward the phone, and the light in the bottle dimmed before my fingers arrived. What I had wanted to look up was how other apps handle login. The answer, over and over, was that they hand the entire question to someone else.

A token you can verify yourself

Google sign-in does not require Firebase, and most of the confusion between the two is branding. The library that opens the account chooser belongs to Google; what it hands back is an `id_token`, a signed JWT that states who just agreed to sign in. Everything after that point is a verification you can run on your own machine.

On the server, one auth library checks three things: the token's signature, its expiry, and its audience. Clear those and you trust the identity without ever asking a third party whether it is real. You then find or create a user by their `google_sub`, return a token of your own, and let the app store it. A single verification call replaces an identity service.

The one client ID you cannot skip

One constraint catches nearly everyone: the token's audience — its `aud` claim — must equal a *Web*-type OAuth client ID. Not an Android one. So even a phone-only app needs exactly one Web client, created once and pasted into both the app and the server, so the two sides agree on who the token was issued for.

It reads like a formality until it is not. The phone can only produce a token stamped with that audience, and the server can only accept that same audience. Get it wrong and every login fails at the single step that has no user-facing error message.

Why this fits an app that asks for nothing

The shape of the result ends up matching the rest of the product. FocusBottle's whole promise is that there is nothing to configure before you begin, so its login could not be a vendor dashboard, a config file to download, or a second project to keep alive.

A signed token, one key, and a server small enough to read in an afternoon keep the same promise for the part users never see. That turned out to be the design constraint worth keeping — not the vendor's, mine.

EngineeringAuthReact Native
"One verification call replaces an entire identity service — as long as you get the audience right."
Start a 25-minute FocusBottle session — no signup, no settings →