[Hosted] Strangers can sign up: registration, a confirmed email address, account recovery #1148

Open
opened 2026-10-12 23:26:13 +00:00 by claude-bot · 2 comments
Collaborator

Today accounts come from an identity provider the operator runs, and INVITE_CODE gates registration on a self-hosted server. A public service needs self-registration, a confirmed email address, account recovery and protection against sign-up abuse.

Decided (owner, 12 Oct 2026; see the comments): passwordless sign-in, meaning an emailed link or code plus passkeys, built into the public app. OIDC stays for instances that use it. No passwords, no Discord or Google sign-in, and not the owner's private Authentik. The second comment lists what this issue has to cover.

Today accounts come from an identity provider the operator runs, and `INVITE_CODE` gates registration on a self-hosted server. A public service needs self-registration, a confirmed email address, account recovery and protection against sign-up abuse. **Decided (owner, 12 Oct 2026; see the comments):** passwordless sign-in, meaning an emailed link or code plus passkeys, **built into the public app**. OIDC stays for instances that use it. No passwords, no Discord or Google sign-in, and not the owner's private Authentik. The second comment lists what this issue has to cover.
Author
Collaborator

Owner's decision, 2026-10-12 (chat; replaces Q176's options): no passwords at all.

The owner ruled out their private Authentik, passwords stored in Quest Board, and sign-in with Discord or Google. Of the three options put to them (a dedicated identity provider for the service; a hosted identity service; passwordless sign-in), they chose passwordless: a link or a short code sent to the person's email address, and passkeys. Nothing secret is stored (a passkey leaves a public key; a code expires in minutes); recovery is access to the email address.

Still to settle (asked in chat): where it lives.

  • Built into Quest Board, in the public app: the smallest thing to operate and useful to self-hosters who do not want to run an identity provider, at the price of owning security-critical sign-in code (single-use, short-lived, rate-limited codes; no account enumeration; session handling; passkey registration and recovery), which needs its own careful review. OIDC stays for instances that use it.
  • Inside a dedicated identity provider run only for the service, configured for passkeys and emailed codes: no sign-in code in Quest Board, one more service to run.

Whichever it is: the Discord account link for the bot stays the separate /link step and is not a way to sign in.

**Owner's decision, 2026-10-12 (chat; replaces Q176's options): no passwords at all.** The owner ruled out their private Authentik, passwords stored in Quest Board, and sign-in with Discord or Google. Of the three options put to them (a dedicated identity provider for the service; a hosted identity service; passwordless sign-in), they chose **passwordless**: a link or a short code sent to the person's email address, and passkeys. Nothing secret is stored (a passkey leaves a public key; a code expires in minutes); recovery is access to the email address. **Still to settle (asked in chat):** where it lives. - **Built into Quest Board**, in the public app: the smallest thing to operate and useful to self-hosters who do not want to run an identity provider, at the price of owning security-critical sign-in code (single-use, short-lived, rate-limited codes; no account enumeration; session handling; passkey registration and recovery), which needs its own careful review. OIDC stays for instances that use it. - **Inside a dedicated identity provider** run only for the service, configured for passkeys and emailed codes: no sign-in code in Quest Board, one more service to run. Whichever it is: the Discord account link for the bot stays the separate `/link` step and is not a way to sign in.
Author
Collaborator

Owner's decision, 2026-10-12: built into Quest Board. Passwordless sign-in (an emailed link or code, and passkeys) is part of the public app, so self-hosters who do not want to run an identity provider can use it too. Sign-in through an OIDC provider stays for instances that use it.

What this issue now has to cover

  • Design first, for the owner to read: the sign-in and registration pages, what the email says, how a passkey is added and removed, recovery (the email address), and what a self-hoster configures (OIDC, built-in, or both; the built-in one needs working outbound email).
  • Emailed codes or links: single use, short-lived, bound to the browser that asked, stored hashed, rate-limited per address and per source, and the same answer whether or not the address has an account (no account enumeration). A link must not sign someone in merely because a mail scanner fetched it: it confirms on a page, or the code is typed.
  • Passkeys (WebAuthn): registration and sign-in with a maintained library, never hand-rolled; only public keys stored; several per account; names and last-used dates; removal; never the only way in until an email address is confirmed.
  • Accounts: today a user is keyed on (oidc_sub, oidc_issuer). Built-in accounts need their own identity, a confirmed email address as the key, and a decided answer for the same person arriving both ways (no silent merging by email).
  • Registration on a public server: open on the hosted service, still gated by INVITE_CODE on a self-hosted one; protection against sign-up floods and against using the service to send mail to strangers.
  • Sessions: the existing Redis session, rotation on sign-in, sign out everywhere, and step-up for sensitive actions (deleting an account, handing on a campaign) decided, not assumed.
  • Review: this is the app's front door. It gets an independent security review before it merges, and it belongs in the launch gate (#1153).
  • Accessibility and the phone: the code field, the passkey prompts, and the emails.

Not part of this: the Discord account link for the bot, which stays the separate /link step.

**Owner's decision, 2026-10-12: built into Quest Board.** Passwordless sign-in (an emailed link or code, and passkeys) is part of the public app, so self-hosters who do not want to run an identity provider can use it too. Sign-in through an OIDC provider stays for instances that use it. **What this issue now has to cover** - **Design first, for the owner to read:** the sign-in and registration pages, what the email says, how a passkey is added and removed, recovery (the email address), and what a self-hoster configures (OIDC, built-in, or both; the built-in one needs working outbound email). - **Emailed codes or links:** single use, short-lived, bound to the browser that asked, stored hashed, rate-limited per address and per source, and the same answer whether or not the address has an account (no account enumeration). A link must not sign someone in merely because a mail scanner fetched it: it confirms on a page, or the code is typed. - **Passkeys (WebAuthn):** registration and sign-in with a maintained library, never hand-rolled; only public keys stored; several per account; names and last-used dates; removal; never the only way in until an email address is confirmed. - **Accounts:** today a user is keyed on `(oidc_sub, oidc_issuer)`. Built-in accounts need their own identity, a confirmed email address as the key, and a decided answer for the same person arriving both ways (no silent merging by email). - **Registration on a public server:** open on the hosted service, still gated by `INVITE_CODE` on a self-hosted one; protection against sign-up floods and against using the service to send mail to strangers. - **Sessions:** the existing Redis session, rotation on sign-in, sign out everywhere, and step-up for sensitive actions (deleting an account, handing on a campaign) decided, not assumed. - **Review:** this is the app's front door. It gets an independent security review before it merges, and it belongs in the launch gate (#1153). - Accessibility and the phone: the code field, the passkey prompts, and the emails. Not part of this: the Discord account link for the bot, which stays the separate `/link` step.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#1148
No description provided.