Consent Docs

Identifiers

How a person is named in a consent record, how identifiers are hashed, and what linked identifiers, fingerprints and identity proofs do.

Concept4 min readFor web, backend and mobile developers

Every consent record is kept under one identifier that you choose: an email address, a phone number or your own user id. The service stores a keyed hash of it, not the value. The identifier you pick decides how you find, withdraw and erase the record later.

Subject types#

subjectType says what kind of identifier subjectId is.

subjectType Use it for
EMAIL An email address
PHONE A phone number
USER_ID Your own user or customer id, or an opaque token you issue
DEVICE_ID A device or app installation id
SESSION_ID A session id your site issues, one that signs nobody in
COOKIE_ID The random id the browser runtime makes for itself. This is the default.

Always send the type from your server

recordConsent defaults to COOKIE_ID. An email address recorded without subjectType: 'EMAIL' keeps its capital letters, and a later look-up by EMAIL does not find it. Send the same type every time for the same identifier.

How identifiers are stored#

The service keeps only a keyed hash for each record:

subject hash = hex( HMAC-SHA256( pepper, identifier ) )
  • The pepper is a secret held in the deployment's configuration, outside the database. A copy of the database alone cannot be turned back into identities.
  • Spaces around the identifier are removed first.
  • An email address is put in lower case. Every other type keeps its exact case, so aB3x and Ab3X are two different people.
  • Phone numbers are not changed. Put them in one form yourself, such as E.164 (+919846011223), before you send them.

The record you read back from the API never contains the identifier. Identifier hashing describes the design.

Keep a readable copy

Your team can turn on Store a reversible subject identifier in the console's settings. Each new record then also keeps an encrypted copy of the identifier it was recorded under. Webhooks send it back as data.subject.reference or subjectReference. Linked identifiers are never kept in readable form.

The setting suits opaque tokens. With email addresses or phone numbers it makes the stored data more sensitive.

Direct identifiers or tokens#

There are two ways of working.

Direct identifiers. Record consent under the person's email address or phone number. A rights request made on the hosted request form asks for an email address or account id by default. It finds the records straight away.

Tokens only. Record consent under your own user id or a token, and keep the link from token to person in your own systems. The service then holds nothing that names the person. You need that link to prove consent, to act on withdrawals and rights requests, and to tell people about a breach.

Linked identifiers#

A record has one subject. A write can also attach other identifiers of the same person, such as the session id, email address and phone number of a signed-in visitor. The record can then be found, exported, withdrawn and erased by its subject or by any linked identifier.

JSON
{
  "formKey": "kalpa-account",
  "subjectId": "usr_8f2K1xQz",
  "subjectType": "USER_ID",
  "decisions": [
    { "purposeKey": "course-updates-by-email", "granted": true }
  ],
  "identifiers": [
    { "subjectType": "EMAIL", "subjectId": "kavya.menon@example.in" },
    { "subjectType": "PHONE", "subjectId": "+919846011223" }
  ]
}
  • One call takes up to five identifiers, without repeats.
  • Each linked identifier is stored only as its keyed hash.
  • Linking is part of the evidence: the event that adds identifiers seals their hashes and types.
  • Erasing a record deletes its linked identifiers.

Who may link what depends on the key:

Caller COOKIE_ID, SESSION_ID EMAIL, PHONE, USER_ID, DEVICE_ID
Publishable key (browser or app) Always Only with the identity proof for that exact identifier
Secret key (your server) Always Always

A browser holds its own cookie id and session id, so it may link them freely. The other types are someone's identity. Without a proof, anyone who copied your publishable key could make a stranger's email address find their own record.

Subject fingerprints#

A fingerprint lets you tell which of your people a webhook or a receipt is about, without the service knowing who they are.

fingerprint = hex( HMAC-SHA256( fingerprint key, identifier ) )

Each project has one fingerprint key, sfk_…. It never changes, so old receipts always match. The identifier is prepared the same way as for the hash.

A fingerprint appears as data.subject.fingerprint on consent webhooks and on subject.erased. It appears as receipt.subjectFingerprint on signed receipts, and as fingerprint in the answer to a look-up.

A record's fingerprint is made from the identifier it was recorded under, not from identifiers linked to it. It is null on erased records. Match events to your users shows how to compute and compare it.

Identity proofs#

A publishable key is public. On its own it may record consent only under the random id the browser made, or the device id an app made. An identity proof is how your server vouches for a signed-in person, so the browser or app may use their real identity.

proof = hex( HMAC-SHA256( identity secret, subjectType + ":" + subjectId ) )
  • The identity secret, idv_…, belongs to the key and must never reach a browser or an app.
  • The proof covers the exact text of subjectId. Nothing is trimmed or put in lower case.
  • A proof is 64 hex characters. It stays valid until the identity secret is rotated.

A browser or app needs a proof to record consent under an EMAIL, USER_ID or PHONE identity. It also needs one to link an EMAIL, PHONE, USER_ID or DEVICE_ID. Record consent for signed-in visitors has the code.

↑↓ to move, Enter to open