feat: identify accounts by a uuid in the oauth2 sub claim

This commit is contained in:
2026-09-23 15:17:09 +02:00
parent cc3d32fcbb
commit bad916cfb7
6 changed files with 153 additions and 7 deletions
+5 -3
View File
@@ -380,7 +380,7 @@ Responses:
OIDC-style claims for the authenticated user. The response contains only the claims covered by the granted scopes:
- always: `sub` (string), `email`
- always: `sub` (UUID string, see below), `email`
- scope `id`: `person_id`, `address_id`
- scope `roles`: `roles` (array; only the roles that actually grant something are exported — the implicit baseline role is stripped, and so are the `*_PENDING` markers of roles the BusPro CRM claims but nobody has approved yet, see `docs/buspronet-schema/crm-selection-queries.md#from-claim-to-role`)
- scope `profile`: `profile` object:
@@ -407,8 +407,10 @@ All of those accounts report the **same** `person_id` and `address_id`, and the
`profile.communication.email` — that value is the first contact address on the BusPro record and
is **not necessarily** the one signed in with. So:
- **`sub`** — opaque, stable, unique per MyE&P account. The only claim that identifies an account.
Match your local user on it and store it.
- **`sub`** — a **UUID (v4, RFC 4122, 36 characters)**, stable for the life of the account and
unique across accounts. The only claim that identifies an account. Match your local user on it
and store it. Size the column at 36 characters and treat the value as opaque: it is random, it
carries no timestamp and no ordering, and nothing about it should be parsed or derived from.
- **`email`** — the address this session actually authenticated with. Distinct per account, but
treat it as a display and contact value; it is not the account key.
- **`person_id` / `address_id`** — the BusPro person behind the account. Shared between that