The operator maintains two cookies in PAF top level domain + 1:
- the list of pseudonymous identifiers associated to the user
- their preferences
Both these cookies have a source
attribute that contains the signature and some common metadata.
For details on how to calculate or verify signatures, see signatures.md.
An extra cookie, with a very short lifetime, can be created to test the support of 3d party cookies (see below for details)
Cookie name | Format | Created by |
---|---|---|
paf_identifiers |
identifiers.md | operator |
paf_preferences |
preferences.md | contracting party, usually CMP |
paf_test_3pc |
test-3pc.md | operator |
[{"version":"0.1","type":"paf_browser_id","value":"7435313e-caee-4889-8ad7-0acd0114ae3c","source":{"domain":"operator.paf-operation-domain.io","timestamp":1642504380,"signature":"bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="}}]
Which is the "stringified" version of:
[
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
]
{"version":"0.1","data":{"use_browsing_for_personalization":true},"source":{"domain":"cmp.com","timestamp":1642504560,"signature":"Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="}}
Which is the "stringified" version of:
{
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
{"timestamp":1643214240}
Which is the "stringified" version of:
{
"timestamp": 1643214240
}
To support the Operator Design, a few endpoints are needed on the operator API.
These endpoints need to handle cases when 3d party cookies (3PC) are supported by the web browser, or not.
- where 3PC are available, a simple JS call is optimum
- in this case, we favour POST calls when data is mutated ("data mutated" means when a cookie is created or updated on PAF TLD+1 domain)
- return code is HTTP 200 and return type is JSON
- where 3PC are not available, a full page redirect is required to read or write cookies on PAF TLD+1 domain
- in this context, POST is not possible
- return code is 303 with no content: data is passed as the query string of the redirect URL
In practice, this will translate into endpoints available under different root paths.
Notes:
- the endpoints called by the browser Javascript are called "REST" endpoints in this document even though they are not 100% RESTful, but this naming seems the most appropriate to distinguish them from "redirect" endpoints.
- values returned by the endpoints are based cookies stored on the web user's browser. Of course, it means the same calls on different web browsers will return different responses.
Endpoint | Description | Input | Output | REST | Redirect |
---|---|---|---|---|---|
Read ids & prefs | Read existing cookies. Return new ID if none |
- | List of persisted IDs. List of preferences newly generated PAF ID, if any |
GET /v1/ids-prefs |
GET /v1/redirect/get-ids-prefs |
Write ids & prefs | Update cookies | PAF ID preferences |
List of persisted IDs. List of preferences |
POST /v1/ids-prefs |
GET /v1/redirect/post-ids-prefs |
Get new id | Generate new ID | - | newly generated PAF ID | GET /v1/new-id |
N/A |
Verify 3PC support | Confirm if 3PC are supported | - | value of paf_test_3pc if any, error otherwise |
GET /v1/3pc |
N/A |
Get identity | Get operator public key to verify ID or responses signatures | - | list of: public key + start and end dates if any |
GET /v1/identity |
N/A |
All messages (appart from "Verify 3PC" and "Get identity") include:
- the domain name of the entity sending the message (
sender
) - the domain name of the entity the message is sent to (
receiver
) - the timestamp (in seconds) when the message is created
All requests and responses (appart from "Verify 3PC" and "Get identity") are signed.
See each "format" section below for the rules to calculate the signature input.
The following signature verifications are mandatory:
- the signature of all requests received by the operator are verified
- any cookie written by the operator is verified before writing
- this is the way requests are authenticated
- any response received by a website after a "boomerang" redirection must be verified
- to prevent a form of "Cross-Site Request Forgery" where a malicious actor pretending to be a PAF operator is trying to send PAF data to the website
The following signature verifications are optional:
- any response received by a website as part of a REST call can be verified
- this is not mandatory as the website controls who it calls (the operator) it can be trusted thanks to its SSL certificate
- it is recommended that any cookie written by a website is verified before writing
For details on how to calculate or verify signatures, see signatures.md.
Error messages are returned inside an error
object:
Message | Format |
---|---|
Error | error |
In case of error:
- for REST endpoints,
- the HTTP return code contains specific code (
40x
,50x
) - the full message body is made of an error object
- the HTTP return code contains specific code (
- for redirect endpoints,
- the HTTP return code is always
303
. The specific error code is incode
property of the response - the response body contains an
error
property of type error
- the HTTP return code is always
For endpoints that exist as "redirect", the following pattern is used:
- basically, the redirect endpoints use the same request and response models as the REST equivalent
- on the redirect endpoints:
- the request object is encapsulated in a
request
property- it has the same type as the full REST request message
- a mandatory
returnUrl
property is also added - the response object is encapsulated in a
response
property- it has the same type as the full REST response message
- an additional
code
property contains a "return code" that takes 3 digits values- it is mapped to HTTP return codes and will contain the "equivalent" to the REST HTTP return code
- for redirect endpoints the "real" HTTP return code is always
303
- in case of an error,
code
contains the appropriate HTTP coderesponse
property is undefinederror
property contains error details
- for both requests and responses:
- the request or response object is "JSON stringified" & encoded in base64
- it is passed as a single
paf
parameter of the query string
- the request object is encapsulated in a
- verify request signature
- if
paf_identifiers
cookie exists and is not an empty list, return the value - otherwise
- generate a new identifier (do not write any new cookie), and sign it
- return the newly generated identifier
- this returned identifier has
persisted
property set tofalse
- this is to avoid an extra call (and potentially, an extra "boomerang redirect")
- if
paf_preferences
cookie exists, return its values - [on REST version only] attempt to create a temporary, short-life, "test 3PC" cookie
Message | Format |
---|---|
Request | get-ids-prefs-request |
Response | get-ids-prefs-response |
Full example
- the following request is built:
{
"sender": "cmp.com",
"receiver": "operator.paf-operation-domain.io",
"timestamp": 1643041140,
"signature": "tvEjp7Fox6jxkgxgY9tjTuy3wH5imuFj63Yuub4UweelYbs8XxnP3nK5w41u13P+fOpEfEqmH/fAgC8WPZYhUQ=="
}
- and transformed into a parameter of the query string to form the URL to call:
GET /v1/ids-prefs?paf=eyJzZW5kZXIiOiJjbXAuY29tIiwicmVjZWl2ZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MzA0MTE0MCwic2lnbmF0dXJlIjoidHZFanA3Rm94Nmp4a2d4Z1k5dGpUdXkzd0g1aW11Rmo2M1l1dWI0VXdlZWxZYnM4WHhuUDNuSzV3NDF1MTNQK2ZPcEVmRXFtSC9mQWdDOFdQWlloVVE9PSJ9
Host: operator.paf-operation-domain.io
- response in case of known user
{
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "operator.paf-operation-domain.io",
"receiver": "advertiser.com",
"timestamp": 1643041150,
"signature": "1WGG+DtR5Q7JO/4w1mGoqwdB0VtdrKMNlh5jmFJRKLSOnki2WI6Pf4RnHd3bN68iCqpM/BHogM0590KVdv3+sg=="
}
- response in case of unknown user
{
"body": {
"identifiers": [
{
"persisted": false,
"version": "0.1",
"type": "paf_browser_id",
"value": "2e71121a-4feb-4a34-b7d1-839587d36390",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1643041140,
"signature": "lfvEkcQ/lw+aDAycLKwljD01BKdjfCAa/W6Uz85z/LuXRGg4L7tMJa/pEzYC5WxZSmY2jVsqCN/IF6mws8c2cA=="
}
}
]
},
"sender": "operator.paf-operation-domain.io",
"receiver": "advertiser.com",
"timestamp": 1643041150,
"signature": "eecaGYcYFkXmgFdaCwzK/93zaVnaLC0dZIDsC4IkP3WubKdSfP/u5UsrPYBhDgt0STCyBnwF6eE79vtyi2UnWA=="
}
Notice persisted
= false
, see identifier.md for details.
Message | Format |
---|---|
Request | redirect-get-ids-prefs-request |
Response | redirect-get-ids-prefs-response |
Full example
- the following request is built:
{
"request": {
"sender": "cmp.com",
"receiver": "operator.paf-operation-domain.io",
"timestamp": 1643041140,
"signature": "tvEjp7Fox6jxkgxgY9tjTuy3wH5imuFj63Yuub4UweelYbs8XxnP3nK5w41u13P+fOpEfEqmH/fAgC8WPZYhUQ=="
},
"returnUrl": "https://advertiser.com/news/2022/02/07/something-crazy-happened?utm_content=campaign%20content"
}
- and transformed into a parameter of the query string to form the URL to call:
GET /v1/redirect/get-ids-prefs?paf=eyJyZXF1ZXN0Ijp7InNlbmRlciI6ImNtcC5jb20iLCJyZWNlaXZlciI6Im9wZXJhdG9yLnBhZi1vcGVyYXRpb24tZG9tYWluLmlvIiwidGltZXN0YW1wIjoxNjQzMDQxMTQwLCJzaWduYXR1cmUiOiJ0dkVqcDdGb3g2anhrZ3hnWTl0alR1eTN3SDVpbXVGajYzWXV1YjRVd2VlbFliczhYeG5QM25LNXc0MXUxM1ArZk9wRWZFcW1IL2ZBZ0M4V1BaWWhVUT09In0sInJldHVyblVybCI6Imh0dHBzOi8vYWR2ZXJ0aXNlci5jb20vbmV3cy8yMDIyLzAyLzA3L3NvbWV0aGluZy1jcmF6eS1oYXBwZW5lZD91dG1fY29udGVudD1jYW1wYWlnbiUyMGNvbnRlbnQifQ%3D%3D
Host: operator.paf-operation-domain.io
- in case of known user, the following response is built:
{
"code": 200,
"response": {
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "operator.paf-operation-domain.io",
"receiver": "advertiser.com",
"timestamp": 1643041150,
"signature": "1WGG+DtR5Q7JO/4w1mGoqwdB0VtdrKMNlh5jmFJRKLSOnki2WI6Pf4RnHd3bN68iCqpM/BHogM0590KVdv3+sg=="
}
}
- and added as a parameter of the query string, to the redirect URL:
303 https://advertiser.com/news/2022/02/07/something-crazy-happened?utm_content=campaign+content&paf=eyJjb2RlIjoyMDAsInJlc3BvbnNlIjp7ImJvZHkiOnsiaWRlbnRpZmllcnMiOlt7InZlcnNpb24iOiIwLjEiLCJ0eXBlIjoicGFmX2Jyb3dzZXJfaWQiLCJ2YWx1ZSI6Ijc0MzUzMTNlLWNhZWUtNDg4OS04YWQ3LTBhY2QwMTE0YWUzYyIsInNvdXJjZSI6eyJkb21haW4iOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MjUwNDM4MCwic2lnbmF0dXJlIjoiYnN6RU9JSGRUZm1kUlpaelRGckZyWGlCODdwaUJreXNWWEJqdHg5dmlzb2lDZ3FtUjBBdktxaXljQVEwNDlWSWVaYThBcFFZMG5qSlV3SGJ5L1kxMGc9PSJ9fV0sInByZWZlcmVuY2VzIjp7InZlcnNpb24iOiIwLjEiLCJkYXRhIjp7InVzZV9icm93c2luZ19mb3JfcGVyc29uYWxpemF0aW9uIjp0cnVlfSwic291cmNlIjp7ImRvbWFpbiI6ImNtcC5jb20iLCJ0aW1lc3RhbXAiOjE2NDI1MDQ1NjAsInNpZ25hdHVyZSI6Ik9yNDFET0Q4T2F1M0hIeWdBaUZaempYTnZQbU14NmZPYXpjLzcyTHBtUEtNblRGZlpya3dQcENQSUdQWkt3Ri9XdWNQMU5PKy9hWDRMZlo2NWpsMlpBPT0ifX19LCJzZW5kZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInJlY2VpdmVyIjoiYWR2ZXJ0aXNlci5jb20iLCJ0aW1lc3RhbXAiOjE2NDMwNDExNTAsInNpZ25hdHVyZSI6IjFXR0crRHRSNVE3Sk8vNHcxbUdvcXdkQjBWdGRyS01ObGg1am1GSlJLTFNPbmtpMldJNlBmNFJuSGQzYk42OGlDcXBNL0JIb2dNMDU5MEtWZHYzK3NnPT0ifX0%3D
- in case of known user, the following response is built:
{
"code": 200,
"response": {
"body": {
"identifiers": [
{
"persisted": false,
"version": "0.1",
"type": "paf_browser_id",
"value": "2e71121a-4feb-4a34-b7d1-839587d36390",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1643041140,
"signature": "lfvEkcQ/lw+aDAycLKwljD01BKdjfCAa/W6Uz85z/LuXRGg4L7tMJa/pEzYC5WxZSmY2jVsqCN/IF6mws8c2cA=="
}
}
]
},
"sender": "operator.paf-operation-domain.io",
"receiver": "advertiser.com",
"timestamp": 1643041150,
"signature": "eecaGYcYFkXmgFdaCwzK/93zaVnaLC0dZIDsC4IkP3WubKdSfP/u5UsrPYBhDgt0STCyBnwF6eE79vtyi2UnWA=="
}
}
Notice persisted
= false
, see identifier.md for details.
- and added as a parameter of the query string, to the redirect URL:
303 https://advertiser.com/news/2022/02/07/something-crazy-happened?utm_content=campaign+content&paf=eyJjb2RlIjoyMDAsInJlc3BvbnNlIjp7ImJvZHkiOnsiaWRlbnRpZmllcnMiOlt7InBlcnNpc3RlZCI6ZmFsc2UsInZlcnNpb24iOiIwLjEiLCJ0eXBlIjoicGFmX2Jyb3dzZXJfaWQiLCJ2YWx1ZSI6IjJlNzExMjFhLTRmZWItNGEzNC1iN2QxLTgzOTU4N2QzNjM5MCIsInNvdXJjZSI6eyJkb21haW4iOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MzA0MTE0MCwic2lnbmF0dXJlIjoibGZ2RWtjUS9sdythREF5Y0xLd2xqRDAxQktkamZDQWEvVzZVejg1ei9MdVhSR2c0TDd0TUphL3BFellDNVd4WlNtWTJqVnNxQ04vSUY2bXdzOGMyY0E9PSJ9fV19LCJzZW5kZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInJlY2VpdmVyIjoiYWR2ZXJ0aXNlci5jb20iLCJ0aW1lc3RhbXAiOjE2NDMwNDExNTAsInNpZ25hdHVyZSI6ImVlY2FHWWNZRmtYbWdGZGFDd3pLLzkzemFWbmFMQzBkWklEc0M0SWtQM1d1YktkU2ZQL3U1VXNyUFlCaERndDBTVEN5Qm53RjZlRTc5dnR5aTJVbldBPT0ifX0%3D
- verify request signature
- verify identifier signature
- verify preferences signature
- add or replace identifier of type
paf_browser_id
inpaf_identifiers
cookie - update
paf_preferences
cookie with new value - return both values
Message | Format |
---|---|
Request | post-ids-prefs-request |
Response | post-ids-prefs-response |
Full example
- the following request is built:
{
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "cmp.com",
"receiver": "operator.paf-operation-domain.io",
"timestamp": 1643097660,
"signature": "A491+ew8CP9Yc3G3JCCqhHYIRpj5WlZwAaZFCPnXtKFh6lRGNCvY/8JRewP+B5wt7/dCMM2zITgEU2eReFL86g=="
}
- and is used as the POST payload to the following call:
POST /v1/ids-prefs
Host: operator.paf-operation-domain.io
- response
{
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "operator.paf-operation-domain.io",
"receiver": "cmp.com",
"timestamp": 1643097663,
"signature": "o4I1BMvUkUATj5l3tFyTo5zF1HRF1Yhjh+KOg5G/SchLRZPBsMzRDewCTS7ynAblwUpWLFfHYvaawW87O0/aVA=="
}
Message | Format |
---|---|
Request | redirect-post-ids-prefs-request |
Response | redirect-post-ids-prefs-response |
Full example
- the following request is built:
{
"request": {
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "cmp.com",
"receiver": "operator.paf-operation-domain.io",
"timestamp": 1643097660,
"signature": "A491+ew8CP9Yc3G3JCCqhHYIRpj5WlZwAaZFCPnXtKFh6lRGNCvY/8JRewP+B5wt7/dCMM2zITgEU2eReFL86g=="
},
"returnUrl": "https://advertiser.com/news/2022/02/07/something-crazy-happened?utm_content=campaign+content&paf=eyJjb2RlIjoyMDAsInJlc3BvbnNlIjp7ImJvZHkiOnsiaWRlbnRpZmllcnMiOlt7InBlcnNpc3RlZCI6ZmFsc2UsInZlcnNpb24iOiIwLjEiLCJ0eXBlIjoicGFmX2Jyb3dzZXJfaWQiLCJ2YWx1ZSI6IjJlNzExMjFhLTRmZWItNGEzNC1iN2QxLTgzOTU4N2QzNjM5MCIsInNvdXJjZSI6eyJkb21haW4iOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MzA0MTE0MCwic2lnbmF0dXJlIjoibGZ2RWtjUS9sdythREF5Y0xLd2xqRDAxQktkamZDQWEvVzZVejg1ei9MdVhSR2c0TDd0TUphL3BFellDNVd4WlNtWTJqVnNxQ04vSUY2bXdzOGMyY0E9PSJ9fV19LCJzZW5kZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInJlY2VpdmVyIjoiYWR2ZXJ0aXNlci5jb20iLCJ0aW1lc3RhbXAiOjE2NDMwNDExNTAsInNpZ25hdHVyZSI6ImVlY2FHWWNZRmtYbWdGZGFDd3pLLzkzemFWbmFMQzBkWklEc0M0SWtQM1d1YktkU2ZQL3U1VXNyUFlCaERndDBTVEN5Qm53RjZlRTc5dnR5aTJVbldBPT0ifX0%3D"
}
- and transformed into a parameter of the query string to form the URL to call:
GET /v1/redirect/post-ids-prefs?paf=eyJyZXF1ZXN0Ijp7ImJvZHkiOnsiaWRlbnRpZmllcnMiOlt7InZlcnNpb24iOiIwLjEiLCJ0eXBlIjoicGFmX2Jyb3dzZXJfaWQiLCJ2YWx1ZSI6Ijc0MzUzMTNlLWNhZWUtNDg4OS04YWQ3LTBhY2QwMTE0YWUzYyIsInNvdXJjZSI6eyJkb21haW4iOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MjUwNDM4MCwic2lnbmF0dXJlIjoiYnN6RU9JSGRUZm1kUlpaelRGckZyWGlCODdwaUJreXNWWEJqdHg5dmlzb2lDZ3FtUjBBdktxaXljQVEwNDlWSWVaYThBcFFZMG5qSlV3SGJ5L1kxMGc9PSJ9fV0sInByZWZlcmVuY2VzIjp7InZlcnNpb24iOiIwLjEiLCJkYXRhIjp7InVzZV9icm93c2luZ19mb3JfcGVyc29uYWxpemF0aW9uIjp0cnVlfSwic291cmNlIjp7ImRvbWFpbiI6ImNtcC5jb20iLCJ0aW1lc3RhbXAiOjE2NDI1MDQ1NjAsInNpZ25hdHVyZSI6Ik9yNDFET0Q4T2F1M0hIeWdBaUZaempYTnZQbU14NmZPYXpjLzcyTHBtUEtNblRGZlpya3dQcENQSUdQWkt3Ri9XdWNQMU5PKy9hWDRMZlo2NWpsMlpBPT0ifX19LCJzZW5kZXIiOiJjbXAuY29tIiwicmVjZWl2ZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MzA5NzY2MCwic2lnbmF0dXJlIjoiQTQ5MStldzhDUDlZYzNHM0pDQ3FoSFlJUnBqNVdsWndBYVpGQ1BuWHRLRmg2bFJHTkN2WS84SlJld1ArQjV3dDcvZENNTTJ6SVRnRVUyZVJlRkw4Nmc9PSJ9LCJyZXR1cm5VcmwiOiJodHRwczovL2FkdmVydGlzZXIuY29tL25ld3MvMjAyMi8wMi8wNy9zb21ldGhpbmctY3JhenktaGFwcGVuZWQ%2FdXRtX2NvbnRlbnQ9Y2FtcGFpZ24rY29udGVudCZwYWY9ZXlKamIyUmxJam95TURBc0luSmxjM0J2Ym5ObElqcDdJbUp2WkhraU9uc2lhV1JsYm5ScFptbGxjbk1pT2x0N0luQmxjbk5wYzNSbFpDSTZabUZzYzJVc0luWmxjbk5wYjI0aU9pSXdMakVpTENKMGVYQmxJam9pY0dGbVgySnliM2R6WlhKZmFXUWlMQ0oyWVd4MVpTSTZJakpsTnpFeE1qRmhMVFJtWldJdE5HRXpOQzFpTjJReExUZ3pPVFU0TjJRek5qTTVNQ0lzSW5OdmRYSmpaU0k2ZXlKa2IyMWhhVzRpT2lKdmNHVnlZWFJ2Y2k1d1lXWXRiM0JsY21GMGFXOXVMV1J2YldGcGJpNXBieUlzSW5ScGJXVnpkR0Z0Y0NJNk1UWTBNekEwTVRFME1Dd2ljMmxuYm1GMGRYSmxJam9pYkdaMlJXdGpVUzlzZHl0aFJFRjVZMHhMZDJ4cVJEQXhRa3RrYW1aRFFXRXZWelpWZWpnMWVpOU1kVmhTUjJjMFREZDBUVXBoTDNCRmVsbEROVmQ0V2xOdFdUSnFWbk54UTA0dlNVWTJiWGR6T0dNeVkwRTlQU0o5ZlYxOUxDSnpaVzVrWlhJaU9pSnZjR1Z5WVhSdmNpNXdZV1l0YjNCbGNtRjBhVzl1TFdSdmJXRnBiaTVwYnlJc0luSmxZMlZwZG1WeUlqb2lZV1IyWlhKMGFYTmxjaTVqYjIwaUxDSjBhVzFsYzNSaGJYQWlPakUyTkRNd05ERXhOVEFzSW5OcFoyNWhkSFZ5WlNJNkltVmxZMkZIV1dOWlJtdFliV2RHWkdGRGQzcExMemt6ZW1GV2JtRk1RekJrV2tsRWMwTTBTV3RRTTFkMVlrdGtVMlpRTDNVMVZYTnlVRmxDYUVSbmREQlRWRU41UW01M1JqWmxSVGM1ZG5SNWFUSlZibGRCUFQwaWZYMCUzRCJ9
Host: operator.paf-operation-domain.io
- the following response is built:
{
"code": 200,
"response": {
"body": {
"identifiers": [
{
"version": "0.1",
"type": "paf_browser_id",
"value": "7435313e-caee-4889-8ad7-0acd0114ae3c",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1642504380,
"signature": "bszEOIHdTfmdRZZzTFrFrXiB87piBkysVXBjtx9visoiCgqmR0AvKqiycAQ049VIeZa8ApQY0njJUwHby/Y10g=="
}
}
],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.com",
"timestamp": 1642504560,
"signature": "Or41DOD8Oau3HHygAiFZzjXNvPmMx6fOazc/72LpmPKMnTFfZrkwPpCPIGPZKwF/WucP1NO+/aX4LfZ65jl2ZA=="
}
}
},
"sender": "operator.paf-operation-domain.io",
"receiver": "cmp.com",
"timestamp": 1643097663,
"signature": "o4I1BMvUkUATj5l3tFyTo5zF1HRF1Yhjh+KOg5G/SchLRZPBsMzRDewCTS7ynAblwUpWLFfHYvaawW87O0/aVA=="
}
}
- and added as a parameter of the query string, to the redirect URL:
303 https://advertiser.com/news/2022/02/07/something-crazy-happened?utm_content=campaign+content&paf=eyJjb2RlIjoyMDAsInJlc3BvbnNlIjp7ImJvZHkiOnsiaWRlbnRpZmllcnMiOlt7InZlcnNpb24iOiIwLjEiLCJ0eXBlIjoicGFmX2Jyb3dzZXJfaWQiLCJ2YWx1ZSI6Ijc0MzUzMTNlLWNhZWUtNDg4OS04YWQ3LTBhY2QwMTE0YWUzYyIsInNvdXJjZSI6eyJkb21haW4iOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MjUwNDM4MCwic2lnbmF0dXJlIjoiYnN6RU9JSGRUZm1kUlpaelRGckZyWGlCODdwaUJreXNWWEJqdHg5dmlzb2lDZ3FtUjBBdktxaXljQVEwNDlWSWVaYThBcFFZMG5qSlV3SGJ5L1kxMGc9PSJ9fV0sInByZWZlcmVuY2VzIjp7InZlcnNpb24iOiIwLjEiLCJkYXRhIjp7InVzZV9icm93c2luZ19mb3JfcGVyc29uYWxpemF0aW9uIjp0cnVlfSwic291cmNlIjp7ImRvbWFpbiI6ImNtcC5jb20iLCJ0aW1lc3RhbXAiOjE2NDI1MDQ1NjAsInNpZ25hdHVyZSI6Ik9yNDFET0Q4T2F1M0hIeWdBaUZaempYTnZQbU14NmZPYXpjLzcyTHBtUEtNblRGZlpya3dQcENQSUdQWkt3Ri9XdWNQMU5PKy9hWDRMZlo2NWpsMlpBPT0ifX19LCJzZW5kZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInJlY2VpdmVyIjoiY21wLmNvbSIsInRpbWVzdGFtcCI6MTY0MzA5NzY2Mywic2lnbmF0dXJlIjoibzRJMUJNdlVrVUFUajVsM3RGeVRvNXpGMUhSRjFZaGpoK0tPZzVHL1NjaExSWlBCc016UkRld0NUUzd5bkFibHdVcFdMRmZIWXZhYXdXODdPMC9hVkE9PSJ9fQ%3D%3D
- verify request signature
- generate a new identifier (do not write any new cookie), and sign it
- return the newly generated identifier
- this returned identifier has
persisted
property set tofalse
- this is to avoid an extra call (and potentially, an extra "boomerang redirect")
Message | Format |
---|---|
Request | get-new-id-request |
Response | get-new-id-response |
Full example
- the following request is built:
{
"sender": "cmp.com",
"receiver": "operator.paf-operation-domain.io",
"timestamp": 1646157840,
"signature": "SaCxgYkhEh9AEFuMuRXx8rolSWx+MEsePekQR+vzWnevA9bZgqk7rb/yXpjy8h/++jcR/RwZzy400segTcQ7Mg=="
}
- and transformed into a parameter of the query string to form the URL to call:
GET /v1/ids-prefs?paf=eyJzZW5kZXIiOiJjbXAuY29tIiwicmVjZWl2ZXIiOiJvcGVyYXRvci5wYWYtb3BlcmF0aW9uLWRvbWFpbi5pbyIsInRpbWVzdGFtcCI6MTY0MzA0MTE0MCwic2lnbmF0dXJlIjoidHZFanA3Rm94Nmp4a2d4Z1k5dGpUdXkzd0g1aW11Rmo2M1l1dWI0VXdlZWxZYnM4WHhuUDNuSzV3NDF1MTNQK2ZPcEVmRXFtSC9mQWdDOFdQWlloVVE9PSJ9
Host: operator.paf-operation-domain.io
- response
{
"body": {
"identifiers": [
{
"persisted": false,
"version": "0.1",
"type": "paf_browser_id",
"value": "2e71121a-4feb-4a34-b7d1-839587d36390",
"source": {
"domain": "operator.paf-operation-domain.io",
"timestamp": 1643041140,
"signature": "lfvEkcQ/lw+aDAycLKwljD01BKdjfCAa/W6Uz85z/LuXRGg4L7tMJa/pEzYC5WxZSmY2jVsqCN/IF6mws8c2cA=="
}
}
]
},
"sender": "operator.paf-operation-domain.io",
"receiver": "cmp.com",
"timestamp": 1646157887,
"signature": "4HLqlyCKsFlBoY2JY2hvRZdZxg+QBoSdF5R+tWIDJmdahn4LdfXim9dRHkVJ7tWcpGnl4PZXUJrSXyEkv0U5pw=="
}
(notice the persisted
property)
This endpoint doesn't rely on support of 3PC or not: the REST version will work regardless so no "redirect" version is needed.
- no signature verification
- if
paf_test_3pc
exists, returntrue
. Otherwise, returnfalse
On a call to GET /v1/ids-prefs
, when no cookie is found on PAF TLD+1 domain,
the operator attempts to write a short-life paf_test_3pc
cookie.
This endpoint is only called immediately after a call to GET /v1/ids-prefs
has failed, to
check if the paf_test_3pc
cookie was indeed written by the web browser.
See website-design for the full picture.
Message | Format |
---|---|
Request | get-3pc-request (empty query string) |
Response | get-3pc-response |
Full example
- The following URL is called:
GET /v1/3pc
Host: operator.paf-operation-domain.io
- response in case of 3PC supported (test cookie was found)
HTTP code 200
{
"3pc": {
"timestamp": 1643214240
}
}
- response in case of 3PC not supported (test cookie could not be found)
HTTP code 404
{
"message": "3PC not supported"
}
This endpoint doesn't rely on support of 3PC or not: the REST version will work regardless so no "redirect" version is needed.
- simply serve the list of public keys for the operator
Message | Format |
---|---|
Request | get-identity-request.md (empty query string) |
Response | get-identity-response.md |
Full example
- The following URL is called:
GET /v1/identity
Host: operator.paf-operation-domain.io
- response:
{
"name": "Some PAF operator",
"keys": [
{
"key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEiZIRhGxNdfG4l6LuY2Qfjyf60R0\njmcW7W3x9wvlX4YXqJUQKR2c0lveqVDj4hwO0kTZDuNRUhgxk4irwV3fzw==\n-----END PUBLIC KEY-----",
"start": 1641034200,
"end": 1646132400
}
],
"type": "operator",
"version": "0.1"
}
This endpoint doesn't rely on support of 3PC or not: the REST version will work regardless so no "redirect" version is needed.