What it does
People
Sign up with an email code or Google. Secure the account with a passkey (up to 10) or an authenticator app with 5 single-use recovery codes. One profile holds names, email, picture, passkeys, connections, a data export and account deletion. Signing out anywhere signs out everywhere.
Apps
Standard OpenID Connect with a stable per-pool identifier, the verified email, names and picture. Sign-in pages carry the app's own look. Each app has an allow list of exact emails and domains, changed without a deploy. Signed notices arrive when an email changes or an account is deleted.
AI clients
One-click MCP connecting with no pre-registration. The person signs in and approves the app name, redirect host and scopes. A hub at mcp.my-login.app relays the tools of every connected app, named by app.
Operator
One Worker serves every pool. A new app is configuration, not code. Alerts reach privacy@my-login.app.
Out of scope: passwords, SMS codes, "trust this device", personal API keys, an operator console, native mobile apps, and offering the service to other companies.
High-level architecture
- Pools. A pool is a set of accounts plus the apps registered in it. The Worker picks the pool from the host name alone, never from a header, path or query. An unknown host gets 404 and touches no database. Each pool has its own database, library secret, signing keys, Google client and Turnstile widget.
- Tokens. Access tokens are ES256 JWTs that last one hour and are bound to one resource (
aud). Refresh tokens last 30 days by default, configurable per app, and rotate on every use. - Email. Resend sends the codes and notices. The service keeps its own daily budget of 90 code emails, shared equally between pools. When it runs out, passkey sign-in still works.
- Failure behaviour. If Google is down, codes and passkeys still work. If the Limiter is down, no code is sent. If D1 is down, sign-in shows a plain error and writes nothing partial. Notices retry for 7 days.
Security
| Pool isolation | Each pool has its own database, library secret, signing keys and issuer. The registry refuses a resource or app domain that two pools share. |
| Sign-in | Email codes are 6 digits, allow 3 attempts and last 5 minutes. Turnstile guards the email step. Send limits are checked in the Limiter and fail closed, and responses do not reveal whether an address has an account. Passkeys are bound to the app domain and use single-use 5-minute challenges. An account with an authenticator app needs its code after the email code. Authenticator keys are encrypted with AES-GCM, and recovery codes are stored only as HMACs. |
| OAuth / OIDC | PKCE S256, exact redirect match, and single-use 10-minute codes. iss is in every response. Refresh-token reuse after 30 seconds revokes the whole family. Notices are ES256-signed. Keys rotate every 90 days. Only a fixed list of library endpoints is reachable from outside. |
| Sessions | The session is read from the database on every request, with no cookie cache, so a revocation takes effect at once. The cookie is host-only, Secure, HttpOnly and SameSite=Lax. Email change, passkeys, the authenticator, the data export and deletion need a sign-in within the last hour. |
| Web | Strict CSP with no third-party script except Turnstile, frame-ancestors 'none', HSTS, an origin check on every form, and return paths confined to the sign-in host. |
| Hub | The hub never forwards a client's token. Each call gets a fresh 5-minute token carrying only the scopes the person granted. Tool groups start at Read, or None for personal details. The hub allows 120 requests a minute per network and per account. |
| Privacy | GDPR and CCPA compliant: a record of processing, a privacy notice on every page, an EU representative, self-service data export and deletion, and breach reporting within 72 hours. All data is in the EU. Logs hold no personal data, and query strings are redacted. Alerts carry counts only. Ended sessions, codes and tokens are removed within a day, and an inactive account is deleted after one year, with a warning first. Secrets live only as Worker secrets. D1 Time Travel can restore 7 days back. |
| Risks | Google's verified email is trusted. On cold code paths, CPU time measured above the 10 ms per-request limit. |