Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

mtg: OIDC login with Google

Chiusa
#139 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@omikron-agent ci sta già lavorando.

Dal 20/10/2026.

  • #176 di @omikron-agent — aperta

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rust, typescript

Direzione di ricerca

Start by reading ADR-0002 and the glossaries at libs/galvyn-identity/GLOSSARY.md and services/mtg/GLOSSARY.md, then trace IdentitySetup and the auth handlers in services/mtg/src/http/handler_frontend/auth/handler.rs. The issue names config.rs, dev/common/env.common, deploy/mtg/env.example, the frontend login and signup pages, and the admin dashboard as implementation entry points. Run the specified HTTP harness tests and just ci; done means the acceptance criteria pass, including signup, returning login, locked accounts, collision handling, and no recovery or signup mail for external accounts.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Feature branch: mtg-oidc-login (starts with the glossary commit 32be03bd).

Goal

People can sign up for and log in to mtg with their Google account, as an alternative to Passkeys. This is the first OIDC login in the repo, built as the OIDC login method of libs/galvyn-identity that ADR-0002 already decided on.

Vocabulary follows libs/galvyn-identity/GLOSSARY.md and services/mtg/GLOSSARY.md (Local Account, External Account, External identity, OpenID provider). "Social login" is not a domain term; the UI may say "Continue with Google".

Decisions

  1. Google only, through generic OIDC. An OpenID provider is configured by issuer, client id, client secret and display name. GitHub and Discord are not OIDC and stay out (a separate decision). Apple comes later as its own step; the module should leave room for a signed (JWT) client secret and a form_post callback, but builds neither now.
  2. Local or external, never both, never switching (ADR-0002). A Local Account cannot add Google; an External Account cannot add a Passkey. No migration path in either direction.
  3. Google admits people on their first OIDC login. No Registration link needed.
  4. Username step. On a first OIDC login with an unknown External identity, the person picks a username. Until then a short-lived pending state in the session holds issuer, subject and email. Identity, External identity and Account are only created when the username is submitted; abandoning the step creates nothing.
  5. Email comes from the provider and is only accepted when email_verified is true; the person never types one. It is stored once and never synced on later logins (mtg has no email change for any Account).
  6. Email collision. If the verified email already belongs to an Account, the first OIDC login is refused with a hint to use Passkey login or recovery. Revealing that the address is in use is acceptable here: only the address's owner can present it verified.
  7. No recovery for External Accounts. Whoever controls the Google account can log in; if the Google account is gone, so is the mtg Account. The Identity module may support recovery for external Identities, mtg does not offer it.
  8. Lock works as for Local Accounts: OIDC login refused with locked, existing sessions fail on their next request.
  9. Deletion removes the Identity and External identity too. A later login with the same Google account goes through the username step and creates a new Account; the old public decks stay with the Tombstone.
  10. One button "Continue with Google" on both the login and the signup page. No username asked first: a known External identity logs in, an unknown one goes to the username step.
  11. Provider configuration via env vars, loaded with EnvLoader. Each provider is optional: without its env vars it is off and its button is hidden. An open endpoint lists the active providers (id + display name) for the frontend. No admin UI for providers.
  12. Admin dashboard shows whether an Account is local or external, and the provider, in both the Account list and the Account detail. Display only. The Admin log is unchanged.

Scope

libs/galvyn-identity: new oidc cargo feature
  • Models: External identity (issuer + subject, bound to exactly one external Identity), with a unique constraint on (issuer, subject). Cascade on Identity deletion.
  • Provider setup in IdentitySetup (issuer, client id, secret, display name, whether it admits on first login), discovery from the issuer.
  • Login ceremony: authorization code flow with PKCE, state and nonce, ID token validation (issuer, audience, expiry, nonce, signature via JWKS). Session keys stay owned by the module.
  • Outcome of a finished OIDC login: either the known Identity (logged in, last_login_at updated) or an unknown External identity held as the pending state, plus the verified email for the service.
  • An operation that binds the pending External identity to a fresh Identity, called by the service inside the transaction that creates its Account.
  • An Identity is local or external: Passkey enrollment refused for an external Identity, OIDC enrollment refused for a local one.
  • Updates to the crate docs (lib.rs), its GLOSSARY.md only if a new term emerges.
services/mtg
  • Enable the oidc feature, provider env vars in config.rs, dev/common/env.common and deploy/mtg/env.example.
  • Handlers: start OIDC login, callback, submit username for the pending state, list active providers. Username validation and the taken-username error as in signup.
  • Email collision check (decision 6) before the username step.
  • Fix recover_account (src/http/handler_frontend/auth/handler.rs): an External Account gets the same silent 200 and no mail. Today it would mail a Registration link that binds a Passkey to an external Identity.
  • Fix prepare_signup (same file): the "username taken but not yet registered" branch must check "has any login method", not "has a Passkey". Today a stranger could trigger an invite mail to an External Account's address by signing up with its username.
  • Admin dashboard schema: login method (local / external + provider) on Account list and detail.
  • Migrations via just make-migrations mtg.
  • HTTP tests (harness) with a fake OpenID provider: first login + username step, returning login, email collision, locked Account, recovery for an External Account is silent, signup with an External Account's username sends nothing.
frontend/mtg
  • "Continue with Google" on login and signup, shown only when the provider is active.
  • Username step page for the pending state.
  • Error states: email in use, Account locked, email not verified.
  • Admin dashboard: login method column / field.
  • i18n keys per CODING_STANDARDS.md; just gen-api mtg.

Out of scope

  • Apple, GitHub, Discord.
  • Switching an Account between local and external.
  • Recovery for External Accounts.
  • Email change for any Account.
  • OIDC for semmelei (the module makes it possible, nothing is wired).

Acceptance

  • A new person can sign up with Google, pick a username and land logged in; the Account is external and has the Google email.
  • The same person logs in again with one click, without a username.
  • A Google login whose verified email belongs to a Local Account is refused with the hint.
  • A locked External Account cannot log in, and its sessions die.
  • Recovery and signup never mail anything for an External Account.
  • Without Google env vars the button is gone and the service starts normally.
  • Admins see local / external (+ provider) per Account.
  • just ci and the gen-api drift check pass.
Lingua principale
TypeScript
Stelle
0
Fork
1
Merge medio
10h 20m
PR unite (30g)
36

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di myOmikron/code

Tutte le issue di myOmikron/code

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.