LoginLens
A local-only map of how you sign in to everything.
A browser extension that records which account, OAuth provider and MFA method you used on each site — the layer above passwords that nothing else tracks. It never asks for, reads or stores a password, and runs entirely on-device with no server and no account.
Built with
Highlights
- ▸Answers the question a password manager cannot: which of your accounts, and which provider button, you used on this specific site.
- ▸Detects password reuse without ever handling a password, via HMAC-SHA256 fingerprints under a random 256-bit device key — unlike a bare hash, they cannot be attacked offline.
- ▸Captures OAuth sign-ins across nine providers by watching the redirect chain, then queues them for one-click confirmation rather than saving anything silently.
- ▸Off by default: capture must be switched on, and manual recording stops itself after 15 minutes.
- ▸Groups the popup by the domain you are actually on — that site, its parent and subdomains first, the rest of the vault behind a toggle.
The problem underneath
Password managers solved storage and left identity selection unsolved. Knowing the password is no help when the question is which of three Google accounts you used, or whether you signed up with the Google button at all. That information is not written down anywhere, so it is reconstructed by trial and error at every login. LoginLens records the choice at the moment it is made.
Why reuse detection without passwords is possible
Reuse detection normally requires the passwords. Hashing them is not a fix: a plain SHA-256 of a human-chosen password falls to a wordlist in seconds. Keying the hash changes that — an HMAC under a random 256-bit key generated on the device still produces equal outputs for equal inputs, which is all reuse detection needs, but the fingerprints are worthless to anyone without the key. The comparison works and the vault stays uninteresting to steal.
From the README
LoginLens 🔍
A local-only map of how you sign in to everything.
Which account did you use on that site? Was it the Google button or a password? Which authenticator guards it? LoginLens answers those questions without ever storing a password and without a server to store it on.
Website · Documentation · Privacy · Permissions · Contributing
What it is
A password manager remembers your passwords. LoginLens remembers your choices — the layer above them that nothing else keeps track of:
- You signed up to Figma with Google, not email. Two years later you have no idea which of your three Google accounts.
- You have an authenticator entry called
Acmeand no memory of which of your two Acme logins it belongs to. - You changed one password and want to know which other sites shared it.
It runs entirely inside your browser. There is no server, no account, and no sync unless you deliberately turn it on.
What it stores — and what it doesn't
Not stored: your passwords. LoginLens never asks for one, never reads one out of a form, and has nothing to leak if the vault file is read. The autofill overlay fills the username and puts a placeholder in the password field.
Stored, locally: which usernames you use where, which OAuth provider backs each login, which MFA method guards it, your notes and labels, and any API keys you paste in yourself.
Full detail — every storage key, every encryption boundary — is in docs/privacy.md.
Features
- OAuth capture — detects sign-ins with Google, GitHub, Microsoft, Apple, X/Twitter, Facebook, Discord, LinkedIn and Slack by watching the redirect chain, then queues them for one-click confirmation rather than saving anything behind your back. It is off until you turn it on, and manual recording stops itself after 15 minutes.
- Password reuse detection without passwords — reuse is inferred from HMAC-SHA256 fingerprints computed under a random 256-bit key generated on your device. Equal passwords produce equal fingerprints; without the key a fingerprint cannot be attacked offline, which a bare SHA-256 hash of a human password very much can.
- Weak-password flagging — the same keyed scheme flags the two dozen passwords that are broken on sight.
- MFA registry — track which authenticator, hardware key, or passkey covers which account, and get warned about accounts with none.
- Mirror-domain linking — tell it that
9anime.toand9anime.idare the same place, and reuse warnings between them stop being noise. - Security review — a single view of reused passwords, weak passwords, and unprotected accounts, with the fixes grouped by what to do first.
- Local restore points — automatic and manual snapshots of the vault, capped and rotated, restorable in one click.
- Optional encrypted cloud sync — off by default. When on, the vault is compressed, encrypted with AES-256-GCM under a passphrase-derived key, chunked, and handed to your browser's own sync. Ciphertext is all that is replicated.
- Import and export — CSV import from other managers, and export as
encrypted
.LLBAK, plaintext.json, or.csv. The.LLBAKformat is documented well enough to decrypt offline in Python, and the extension will hand you that script. - Export & Leave — a proper exit: take a backup, wipe the local vault, and clear the copy your browser already synced to your other devices.
- Local-only favicons by default — site icons are drawn from the domain name on your machine. Fetching real favicons from Google is available in Settings and is opt-in, because the domain would travel in the request URL.
Permissions
storage, tabs, clipboardWrite, alarms — and no host permissions.
See PERMISSIONS.md.
Install
Store listings are pending. Until then, load it unpacked:
npm install
npm run build:chrome
Then open chrome://extensions, enable Developer mode, choose Load
unpacked, and select build/chrome-mv3-prod.
docs/installation.md covers Firefox, Edge, Brave, Opera, and Safari.
Development
npm install
npm run dev
Plasmo writes a live-reloading build to build/edge-mv3-dev (change the target
in the dev script for another browser). Load that directory unpacked.
Build targets
npm run build:chrome
npm run build:edge
npm run build:brave
npm run build:opera
npm run build:firefox
npm run build:firefox-mv2
npm run build:safari
Quality gates
npm test
npm run typecheck
npm run lint
npm run test:coverage produces a coverage report. Every push and pull request
to main runs the same gates via GitHub Actions
(.github/workflows/ci.yml).
Tech stack
| Layer | Choice |
|---|---|
| Extension framework | Plasmo 0.90, Manifest V3 |
| UI | React 18, TailwindCSS 3, Framer Motion 11, Lucide |
| Storage | @plasmohq/storage over chrome.storage.local / .sync / .session |
| Crypto | WebCrypto — AES-256-GCM, PBKDF2-HMAC-SHA256 (600k iterations), HMAC-SHA256 |
| Language | TypeScript 5.4, strict |
| Tests | Vitest 3 |
The injected overlay renders inside a closed Shadow DOM, so host-page CSS
cannot reach it, it cannot leak styles back into the page, and page script
cannot read the accounts it is showing you out of host.shadowRoot.
Contributing
CONTRIBUTING.md covers the setup, the architecture, and what a change needs before it can land. Security issues go to SECURITY.md, not the public issue tracker.
License
Apache-2.0. See LICENSE.