registry: sign-in through GitHub, GitLab and Codeberg, OAuth 2.0 with PKCE (slice 2 of #16) #224

Closed
opened 2026-10-08 21:26:56 +00:00 by orion · 3 comments
Collaborator

Goal

A person signs up and signs in to the registry through GitHub, GitLab or Codeberg. A first sign-in creates an account whose owner name the person chooses; a later one opens a session for the account the identity is linked to; a signed-in person can link a further provider to the same account.

Owner decision (recorded on #16)

  • Identity = provider + the provider's user id, never the e-mail address; several identities per account; owner name chosen at first sign-up, first come, under the similarity rules of RELEASE.md 7.1.
  • The owner registers one OAuth application per provider at deployment (callback under the registry's host) and puts client id and secret into the registry's environment. The repository work needs no credentials: tests run against recorded provider responses.
  • No e-mail sign-up yet.

Pinned records

Acceptance criteria

  • Authorization code flow with PKCE (S256) and a single-use state bound to the browser session, for GitHub, GitLab and Codeberg (Codeberg is a Forgejo: the same code as a configurable Forgejo/Gitea instance); the redirect URI is fixed per provider, never taken from the request.
  • The provider's numeric user id (GitHub id, GitLab id, Forgejo id) is the identity's subject; login names and e-mail addresses are display data only.
  • First sign-in: the person chooses an owner name, refused under the existing name and similarity rules; the account, its person owner and the identity are created in one transaction.
  • Linking a further provider to a signed-in account; an identity already linked to another account is refused.
  • Configuration per provider from the environment (REGISTRY_GITHUB_CLIENT_ID/_SECRET and the GitLab and Codeberg equivalents, names final in the PR); a provider without configuration is not offered.
  • Tests against recorded token and user responses served by a stand-in over loopback (no network, no credentials): every step once as it works and once as it is refused (wrong state, reused state, wrong PKCE verifier, provider error, unknown provider, taken name); torb test tools/registry/tests green natively and in the VM.
  • tools/registry/README.md and RELEASE.md "Not built yet" updated.

Seed impact

None: TorbScript in tools/registry over std/http, std/json, std/digest (SHA-256 for PKCE) and std/random; no syntax change, no native, no driver flag, no looked-up std name.

Size and dependencies

One PR, one or two Conventional Commits. Depends on slice 1 (#223, sessions, identities, account page). Parent: #16. Not ready until slice 1 (#223) has landed. Security-relevant: architect review of the diff.

## Goal A person signs up and signs in to the registry through GitHub, GitLab or Codeberg. A first sign-in creates an account whose owner name the person chooses; a later one opens a session for the account the identity is linked to; a signed-in person can link a further provider to the same account. ## Owner decision (recorded on #16) - Identity = provider + the provider's user id, never the e-mail address; several identities per account; owner name chosen at first sign-up, first come, under the similarity rules of RELEASE.md 7.1. - The owner registers one OAuth application per provider at deployment (callback under the registry's host) and puts client id and secret into the registry's environment. The repository work needs no credentials: tests run against recorded provider responses. - No e-mail sign-up yet. ## Pinned records - [RELEASE.md 7.1 Owners](https://git.torb.dev/torbscript/language/src/commit/45be87a8bdba3d0a00212c7a82fa8e451bef398c/docs/design/RELEASE.md#L866) - [RELEASE.md 7.6 Security](https://git.torb.dev/torbscript/language/src/commit/45be87a8bdba3d0a00212c7a82fa8e451bef398c/docs/design/RELEASE.md#L1029) - RFC 6749 (authorization code), RFC 7636 (PKCE, `S256`), RFC 9700 (OAuth 2.0 security best current practice) ## Acceptance criteria - [ ] Authorization code flow with PKCE (`S256`) and a single-use `state` bound to the browser session, for GitHub, GitLab and Codeberg (Codeberg is a Forgejo: the same code as a configurable Forgejo/Gitea instance); the redirect URI is fixed per provider, never taken from the request. - [ ] The provider's numeric user id (GitHub `id`, GitLab `id`, Forgejo `id`) is the identity's subject; login names and e-mail addresses are display data only. - [ ] First sign-in: the person chooses an owner name, refused under the existing name and similarity rules; the account, its person owner and the identity are created in one transaction. - [ ] Linking a further provider to a signed-in account; an identity already linked to another account is refused. - [ ] Configuration per provider from the environment (`REGISTRY_GITHUB_CLIENT_ID`/`_SECRET` and the GitLab and Codeberg equivalents, names final in the PR); a provider without configuration is not offered. - [ ] Tests against recorded token and user responses served by a stand-in over loopback (no network, no credentials): every step once as it works and once as it is refused (wrong `state`, reused `state`, wrong PKCE verifier, provider error, unknown provider, taken name); `torb test tools/registry/tests` green natively and in the VM. - [ ] `tools/registry/README.md` and RELEASE.md "Not built yet" updated. ## Seed impact None: TorbScript in `tools/registry` over `std/http`, `std/json`, `std/digest` (SHA-256 for PKCE) and `std/random`; no syntax change, no native, no driver flag, no looked-up std name. ## Size and dependencies One PR, one or two Conventional Commits. Depends on slice 1 (#223, sessions, identities, account page). Parent: #16. Not `ready` until slice 1 (#223) has landed. Security-relevant: architect review of the diff.
Author
Collaborator

[loop:torbscript] intake: in scope (author orion, label loop), slice 2 of #16 filed by the split, not a duplicate, no collision with a design record, no seed impact. next: waiting (slice 1 #223 has not landed; PR #249 is open) until 2026-10-10T04:00:00Z

[loop:torbscript] intake: in scope (author orion, label loop), slice 2 of #16 filed by the split, not a duplicate, no collision with a design record, no seed impact. next: waiting (slice 1 #223 has not landed; PR #249 is open) until 2026-10-10T04:00:00Z
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261009 until 2026-10-09T12:25Z

[loop:torbscript] claim implement by session:loop-torbscript-20261009 until 2026-10-09T12:25Z
argus closed this issue 2026-10-09 08:20:48 +00:00
Author
Collaborator

[loop:torbscript] close: PR #257 merged by argus (merge commit 2b17439f), issue closed. Claim released.

[loop:torbscript] close: PR #257 merged by argus (merge commit 2b17439f), issue closed. Claim released.
Sign in to join this conversation.
No labels
loop
ready
No milestone
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.

Reference
torbscript/language#224
No description provided.