Ga naar inhoud

Consent facility

The consent facility (toestemmingsvoorziening) is where the citizen gives, views and revokes consent. It also tells every source, at every request, whether a consent still holds. It has three components: the consent portal (toestemmingsportaal) frontend and backend (PSA capability S02) and the consent register (toestemmingsregister) (S01). The Consent concept page has the detail and the links to the code.

Overview › DvTP channel › Consent facility

Components and interfaces

flowchart LR burger(["Citizen<br/>browser"]) dv["Service provider"] subgraph tv["Consent facility"] direction TB pf("Portal frontend<br/>request, login, choice,<br/>overview, revoke") pb("Portal backend<br/>keeps the BSN away<br/>from the register") subgraph tr["Consent register"] direction TB api("Portal API<br/>create, list, revoke") st("Status listener<br/>status only") jw("JWKS<br/>public keys") db[("Consents,<br/>PI + PP per citizen")] end end digid["DigiD<br/><i>mock</i>"] bsnk["BSNk PP<br/><i>mock</i>"] inw("Register Inway<br/>FSC service consent-status") pdp("PDP of a source") log[("LDV logbook<br/>consent facility")] dv -- "redirect: consumer, service,<br/>data sets, return address" --> pf burger --> pf pf -- "login" --> digid pf --> pb pb -- "activate once,<br/>transform per consent" --> bsnk pb -- "only the backend" --> api api --- db st --- db pf -- "proof in the URL fragment" --> dv pdp -- "over FSC" --> inw --> st pdp -. "keys, cached 5 min" .-> jw api -.-> log st -.-> log %% GBO diagram palette: the same colors as the Globaal Ontwerp classDef basis fill:#DCFCE7,stroke:#16A34A,color:#0F172A classDef dvtp fill:#FEDCD8,stroke:#E28F80,color:#1E293B classDef eudi fill:#FFEDD5,stroke:#EA580C,color:#0F172A classDef source fill:#DDEBF7,stroke:#6F94B8,color:#1E293B classDef ext fill:#F1EFE8,stroke:#5F5E5A,color:#444441 classDef store fill:#EDE9FE,stroke:#7C3AED,color:#1E1B4B classDef mock fill:#F3F4F6,stroke:#9CA3AF,color:#374151,stroke-dasharray:4 3 classDef planned fill:#FFFFFF,stroke:#9CA3AF,color:#6B7280,stroke-dasharray:6 4 classDef zoom stroke-width:3px class burger source class dv,digid,bsnk ext class pf,pb,api,st,jw dvtp class db,log store class inw,pdp basis class pdp,bsnk zoom style tv fill:#F4F5F7,stroke:#E28F80 style tr fill:#FFFFFF,stroke:#E28F80 click pdp "../../gbo-basis/authorization/" "Authorization" click bsnk "../../../concepts/pseudonymization/" "Pseudonymization"

Figure 1: The components of the consent facility and their interfaces.

Each component has one job:

Component Job Never does
Portal frontend Shows the request in plain language, one choice per data set. Shows the consents of the citizen and lets the citizen revoke one. Picks fields inside a data set (REQ-10)
Portal backend Recognizes the citizen with a keyed hash of the BSN. Asks BSNk for the values per source. Talks to the register. Sends a BSN to the register (REQ-23)
Register: portal API Creates, lists and revokes consents. Signs the consent proof. Only the portal backend can call it. Serves the status to a source
Register: status listener Answers one question per request: is this consent active? It is reachable only over FSC. Serves anything else
Register: JWKS Publishes the public keys that the PDP uses to check a proof. —

The register signs a consent proof when the citizen gives consent. The service provider (dienstverlener) keeps it and sends it unchanged with every query:

flowchart LR subgraph jwt["Consent proof: ES256 JWT, type gbo-consent+jwt"] direction TB h["Header<br/>algorithm, type, key ID"] subgraph claims["Claims"] direction TB id["consent_id · jti"] sc["scopes · scope_entries<br/>data sets per source"] who["dienstverlener_oin<br/>the party it is for"] t["valid_until = exp<br/>iss · aud · iat · nbf"] subgraph es["encrypted_subject: one entry per source OIN"] direction LR vp["pseudonym (VP)<br/>for every source"] vi["identity (VI)<br/>only for a source that<br/>may process the BSN"] end end end sig["Signature of<br/>the register"] jwt --- sig %% GBO diagram palette: the same colors as the Globaal Ontwerp classDef basis fill:#DCFCE7,stroke:#16A34A,color:#0F172A classDef dvtp fill:#FEDCD8,stroke:#E28F80,color:#1E293B classDef eudi fill:#FFEDD5,stroke:#EA580C,color:#0F172A classDef source fill:#DDEBF7,stroke:#6F94B8,color:#1E293B classDef ext fill:#F1EFE8,stroke:#5F5E5A,color:#444441 classDef store fill:#EDE9FE,stroke:#7C3AED,color:#1E1B4B classDef mock fill:#F3F4F6,stroke:#9CA3AF,color:#374151,stroke-dasharray:4 3 classDef planned fill:#FFFFFF,stroke:#9CA3AF,color:#6B7280,stroke-dasharray:6 4 classDef zoom stroke-width:3px class h,id,sc,who,t dvtp class vp,vi store class sig ext style jwt fill:#FFFFFF,stroke:#E28F80 style claims fill:#F4F5F7,stroke:#D1D5DB style es fill:#F5F3FF,stroke:#7C3AED

Figure 2: The parts of the consent proof.

The proof holds no BSN. The service provider can read which data sets it can ask for. It cannot read who the citizen is: each value in encrypted_subject can be decrypted only by the source it was made for (REQ-80). The decision for this form is ADR-0032.

The proof works as a bearer token. The binding to the service provider stops use by another party, but not replay by the same party within the validity (R4).

stateDiagram-v2 direction LR [*] --> Active: citizen gives consent,<br/>register signs the proof Active --> Active: service provider queries<br/>(as often as needed) Active --> Revoked: citizen revokes Active --> Expired: valid_until passes Revoked --> [*] Expired --> [*] classDef active fill:#DCFCE7,stroke:#16A34A,color:#0F172A classDef stop fill:#FEDCD8,stroke:#E28F80,color:#1E293B class Active active class Revoked,Expired stop

Figure 3: The states of a consent.

The register stores ACTIVE or REVOKED. Expired follows from the date in the proof. A consent can be used again within its validity: the design does not require single use (Q-04). A revocation takes effect on the next request, because the PDP asks the status every time (REQ-14).

Why the status stays online

The proof carries the content of the consent, and the register keeps the status. Each part has its own freshness:

What How fresh Why
Content: data sets, party, validity Fixed at consent, checked locally The register signed it. The PDP needs no call for it.
Public keys At most five minutes old Keys change rarely. An unknown key ID triggers a fetch at once.
Status Live at every request A revocation must stop the next request.

The price is a hard dependency: if the register does not answer, the PDP denies every DvTP request (REQ-75). The target values for availability and delay are open (Q-47).

Open points

The main open points in the consent facility are these:

  • Whether the register and the portal backend are one system, and which one is the BSNk participant (Q-49).
  • Who sets the validity period, and whether the citizen can change it (Q-13).
  • When a consent counts as "retrieved", and how the register learns that (Q-42).
  • Where the signing key lives and how it rotates (Q-55).
  • Whether the register must authenticate the portal backend, or whether network isolation is enough (Q-58).

Traceability