agentleFS
thomaslimitedthomaslimited/chrome-extension-skills/skills/chrome-extension-auth/SKILL.md

chrome-extension-auth

Skill2 starsChanged 51 days agoMITView on GitHub

Add user accounts to a Chrome MV3 extension with a backend. Covers Google SSO via chrome.identity.launchWebAuthFlow (OIDC id_token + server nonce, JWKS verification with jose) and manual email/password sign-in (argon2id hashing, email verification, password reset, account linking). Use for "login in chrome extension", "Google sign in extension", "launchWebAuthFlow", "chrome.identity", "OAuth chrome extension", "email password auth extension", "SSO", "session JWT extension", "sign in with Google MV3", "auth chrome-extension:// CORS", "extension ID redirect URI mismatch". Includes session storage (storage.local vs storage.session), 401/token-refresh handling, JWT secret rotation, and server-side revocation. Does NOT cover payments/entitlements, Chrome Web Store listing, or build/publish pipelines — see sibling skills.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Add sign-in and sessions to a Manifest V3 extension backed by a server.

    line 9
  2. Very specific:

    Read references/troubleshooting.md before debugging a "sign-in opens and closes immediately" or "nonce mismatch" report — both have a …

    line 56
  3. Very specific:

    Add schema: password_hash, password_algo on users.

    line 61

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Chrome Extension Auth

Add sign-in and sessions to a Manifest V3 extension backed by a server. Two proven paths, one shared session contract.

Scope

This skill covers: Google SSO (OAuth "Web application" client + launchWebAuthFlow), email/password sign-in, session issuance and verification, extension-side storage and API calls, CORS, rate limiting, and revocation.

This skill does not cover:

  • Payments, subscriptions, entitlements → chrome-extension-payments
  • Chrome Web Store listing content, screenshots, review policy → chrome-web-store-listing
  • Extension scaffolding, build tooling, content scripts → chrome-extension-dev
  • Packaging and publishing → chrome-extension-deploy

Decision table

SituationChooseWhy
Want the fastest signup, no password support burdenGoogle SSO onlyNo password storage/reset flow to build or secure
Users without Google accounts, enterprise, or privacy-sensitive audienceEmail/password (or passwordless OTP)Not everyone has/wants a Google account
Want maximum reach, willing to build bothBoth, with account linkingSame email can arrive via either path — link, don't duplicate
Want passwordless but no OAuth complexityEmail OTP (magic code)Simpler than full password flow; still needs an email provider

Both paths must converge on the same session contract: a server-issued session JWT, verified the same way, stored the same way in the extension. Do not build two different session formats.

Workflow A — Google SSO

  1. Register a Google OAuth Web application client (not "Chrome App" — see references/google-sso-extension.md#oauth-client-setup). Add the redirect URI https://<extension-id>.chromiumapp.org/ for both the dev extension ID (pinned via a manifest key) and the Chrome Web Store ID (assigned after first publish, unknown until then).
  2. In the extension manifest, add the identity permission and pin a dev key so the extension ID is stable across rebuilds — see references/google-sso-extension.md#manifest-and-dev-key.
  3. Implement beginGoogleSignIn: fetch a server-issued nonce, build the Google authorization URL with response_type=id_token, launch chrome.identity.launchWebAuthFlow, parse the ID token out of the redirect fragment. Full code in references/google-sso-extension.md#client-flow.
  4. On the server, verify the ID token against Google's JWKS with jose (aud, iss, exp, nonce, email_verified), burn the nonce, upsert the user, issue a session JWT. Full code in references/google-sso-backend.md.
  5. Store the session in chrome.storage.local from the background script only; attach it as a Bearer header on every API call made from the background script. See references/google-sso-extension.md#session-and-api-calls.
  6. Handle sign-out and 401s (session invalid/expired → clear and prompt re-login). See references/sessions-cors-security.md#401-and-refresh.

Read references/troubleshooting.md before debugging a "sign-in opens and closes immediately" or "nonce mismatch" report — both have a specific, known root cause.

Workflow B — Email/password

  1. Add schema: password_hash, password_algo on users; email_verifications and password_reset_tokens tables. SQL in references/email-password.md#schema.
  2. Signup: create an unverified user, send a 6-digit code (hashed, expiring, attempt-limited) via an email provider behind an interface (Resend/SES/SMTP). Code in references/email-password.md#signup-and-verification.
  3. Password hashing: argon2id by default; node:crypto scrypt fallback when a native module is not an option. Never roll your own KDF loop count. Code in references/email-password.md#password-hashing.
  4. Login: constant-time password compare, generic error message ("invalid email or password") for both "no such user" and "wrong password", per-IP and per-account throttling. Code in references/email-password.md#login.
  5. Password reset: request → emailed single-use token (hashed, expiring) → reset endpoint that invalidates the token and bumps token_version (see revocation below). Code in references/email-password.md#password-reset.
  6. Account linking: if a Google sign-in's verified email matches an existing password account, link google_sub onto that row instead of creating a duplicate — only when email_verified is true. Never auto-link an unverified email. Code in references/email-password.md#account-linking.
  7. Issue the same session JWT shape as Workflow A step 4 so extension-side code (storage, API client, use-session hook) doesn't fork per auth method.
  8. Build popup/options forms (signup, login, verify, forgot/reset password) that submit through the background script, same as billing messages — never let a content script or a form directly hold credentials outside the extension's own pages. UI notes in references/email-password.md#ui-forms.

Alternative: skip passwords entirely with email OTP (passwordless) — same schema minus password_hash, same session issuance. See references/email-password.md#passwordless-otp-simpler-alternative.

Security checklist

  • identity permission present; optional_permissions unaffected by auth
  • OAuth client is "Web application" type, both dev and store extension IDs registered as redirect URIs
  • Nonce is server-issued, single-use, and expires (10 min is reasonable) — never trust a client-generated nonce for replay protection
  • ID token verified against live JWKS (aud, iss, exp, nonce, email_verified) — never decode without verifying
  • Session JWT is HS256 (or better) with a real expiry, signed with a secret ≥32 random bytes, never the placeholder default
  • Session stored in chrome.storage.local, read/written only by the background script, never exposed to content scripts or web pages
  • Every extension→server call carries Authorization: Bearer <token> and runs from the background script only
  • runtime.onMessage handler validates the sender is the extension's own page before acting on any auth/account message (see references/sessions-cors-security.md#sender-validation)
  • Server CORS allowlist matches exact chrome-extension://<id> origins — no wildcard, no prefix match
  • Rate limiting on nonce issuance, token exchange, login, signup, and password reset request
  • Passwords hashed with argon2id or scrypt with real cost parameters — never plaintext, never unsalted, never fast hashes (MD5/SHA-1/SHA-256 alone)
  • Password/email-verification/reset codes are hashed at rest, expiring, and attempt-limited
  • Generic error messages on login (do not reveal whether the email exists)
  • Account linking only on a verified email match
  • A token_version (or equivalent) column exists so sessions can be revoked server-side without waiting for natural expiry
  • Client secret (if any OAuth flow needs one) never ships in the extension bundle — only the public client ID does

Reference files

  • references/google-sso-extension.md — manifest, dev key, launchWebAuthFlow client flow, session storage, background-only API calls, sender validation
  • references/google-sso-backend.md — Hono routes, jose JWKS verification, nonce issuance, session JWT issuance/verification, user upsert, CORS, rate limiting
  • references/email-password.md — full email/password design: schema, signup/verification, hashing, login, reset, account linking, UI forms, passwordless OTP alternative
  • references/sessions-cors-security.md — storage.local vs storage.session, secret rotation, revocation, 401/refresh handling, sender validation detail
  • references/troubleshooting.md — known failure modes and their fixes, including the extension-ID redirect-URI mismatch bug

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.