Cookie Consent with ForgeRock Identity Platform

Stéphane Orluc
10 min readNov 13, 2020

--

When we talk about consent and GDPR we also very often talk about Cookie management. In this post, I’ll walk you through how you can manage that with the ForgeRock Identity Platform.
Cookie consent management can be done with an integration of ForgeRock Identity platform and one of our partners but it can also be done with the ForgeRock Identity platform alone. In this blog note we’ll see how to do this just with the ForgeRock platform.

Cookies consent and Identities

Every time you browse a website that uses cookies you are asked to accept or deny the use of cookies in your browser. This is happening whether you are authenticated or not. So, how do we manage this consent and where do we store this information ? To answer these questions, let’s consider two populations :

  1. Anonymous users: they are simple unknown user that browse your website. The only thing you may know about them is their device fingerprint.
  2. Authenticated users: they are the person that have an account in your user store and you know well because they went through and authentication journey.

Anonymous users
For this population, most of the time the consent is stored somewhere either in a cookie or in a store that pairs a device fingerprint with the consent decision.
Note: To simplify this blog note, I won’t talk about these cases (but it could be done easily with the ForgeRock platform).

Authenticated users
If we are dealing with authenticated users we want to store their cookie consent directly in the user store as a consent decision. By doing this we’ll allow the user to have a centralized view of all their consented cookies and they’ll be able to revoke them any time they want.
Note: sometimes an anonymous user become an authenticated user but has already answered for cookie consent; we don’t want to ask him again when he becomes an authenticated user. We’ll see later how to deal with this use case.

The following figure shows the various Cookie consent journeys depending if user is authenticated or not and how it will interact with ForgeRock IDM.

Anonymous and authenticated users cookie consent journey

How to do it with the ForgeRock Identity Platform ?

To configure cookie management in ForgeRock Identity Platform we have to follow these steps:

  1. Define and configure the data model and relationships in ForgeRock Identity Management,
  2. Customize End-user UI - optional,
  3. Create a client-side Javascript.

Note: in this post I’ll focus on the Identity Management part.

Data Model and relationship in ForgeRock Identity Management

One of the real power of the ForgeRock Identity Platform is the capacity to manage anything: Customers, Employee, Users, IoT, … and to create links between the objects we manage. Here, we want to manage cookies, users and the link between them (i.e. approved or not). The following figures shows this data model.

Managed User and Cookie data model

To implement this data model follow theses steps:

  1. Login to ForgeRock Identity Management (IDM) and browse to Configure > Managed object section,
  2. Click on New Managed Object,
  3. Enter the “Managed Object Name”, “Readable Title”, “Managed Object Icon”, and “Description” and then click on Save to create the Cookie Managed Object type.
Create Cookie Managed Object type

Now add Properties to the Cookie definition.

  1. In the Cookie definition section, click on Add a property, in the then “Property Name” column enter “name”, in the “Label” column enter “Name”, for the “Type” column select “String” and make this property as “Required” and then click Save.
  2. Repeat these operations for “Description” and “Users” properties.
    Note: Description property note required and Users property should be of type “Relationship”.

The figure below shows the how it looks like at this stage.

Cookie properties definition

We will now configure the relationship between a Cookie and a User.

  1. On the Cookie properties definition, click on the “Users” line.
  2. Then in Details tab, configure the “Relationship Configuration”. Click on Related Resource, and in the popup select user as Resource, then click Save.
  3. Click on the pen in the right part of User line (above Related Resource), and in the “Display Properties” field select “userName” and click Save.
  4. Click on Has one users and select Has many.
  5. Click on Two-way Relationship and select Has many.
  6. In the “Reverse property name” field of the new Popup, enter “Cookies” and click Save.
  7. Finally click on Save to validate the modification on the Relationship attribute.

The figure below shows how the configuration of the relationship property “users”.

Relationship configuration

After configuring the Cookie managed object, configure relationship on the User managed object:

  1. browse to Configure > Managed object section, and click on User,
  2. On the User properties definition, click on the “Cookies” line.
  3. Then in Details tab, Click on the pen in the right part of Cookie line (above Related Resource), and in the “Display Properties” field select “name” and click Save.
  4. Finally click on Save to validate the modification on the Relationship attribute.

Once the data model is setup, we have to define access right to be sure the user will be able to edit the consent (i.e. the user attribute where we store the link with the cookie he approved ). To do this follow these steps:

  1. Login to ForgeRock Identity Management (IDM) and browse to Manage > Role section,
  2. Click on Internal tab and click on New Internal Role,
  3. Enter this value for the “Name” field “User Access right for Cookie Consent” (add anything you want in the description field) and then click on Save,
  4. On the Details tab activate “Condition”, select “The value for”, then select the field “Username” and select “is present” and click Save,
  5. Click on Privileges tab and click on Add Privileges,
  6. In the popup enters “User” for “Privileges Name” field, select “User” for “Object” field,
  7. In the “Permissions” section of the popup select “Can View” and “Can Update”,
  8. In the “Attributes” section select “Read” for “UserName”, “Read/Write” for “Cookies” and “None” for all the rest,
  9. In the “Query filter” section, select “The value for” and enter “Username” “is equall to” {{userName}}, and click Save,
  10. Repeat steps from 4 to 7 with the following parameters: Privileges Name = Cookies, Objects = Cookies, Permissions = Can View, Name & Description = Read, Users = None, and no “Query filter”.
  11. Finally, click Save.

The result should look like the figure below.

Access right configuration

And that’s all for the ForgeRock Identity Platform configuration. The cookie consent logic is in place and operational and every operation is audited.Now any user can add or remove a link with a cookie (i.e. consent or deny a Cookie).

How a user sees his cookie consents in ForgeRock self-service UI

The ForgeRock Identity platform includes an end-user self-service user interface. Depending on the access rights you set for users, they can see different things in the interface. So now if a customer logs in to the self-service he’ll see a dedicated section to manage his cookie consents.

Default ForgeRock self-service interface

Note: this is the ForgeRock default end-user interface, it is available as a GitHub project so it is possible to download and modify to better fit your needs (underlying technology is VueJS).

This self-service interface is cool but maybe you want to integrate this with your own website. Let’s see how to use it using the REST API.

Use it with the REST API

The whole ForgeRock Identity Platform can be operated (from configuration to data management) using the REST API. All the Web interfaces provides Out of the Box by are using this REST interface. We will use the REST interface to do the classical cookie consent management you may need:

  1. List all Cookies,
  2. List user’s Cookie consents,
  3. Add Cookie consent,
  4. Revoke Cookie consent,
  5. Get user’s consent history.

List cookies
To list all available cookies execute the following REST call:

curl --location --request GET 'http://<IDM_SERVER>:<IDM_PORT>/openidm/managed/Cookie?_fields=name%2Cdescription&_queryFilter=true' \
--header 'X-OpenIDM-Username: <IDM_username>' \
--header 'X-OpenIDM-Password: <IDM_userpassword>'

where <IDM_SERVER> is the IDM server name, <IDM_PORT> is the IDM port, <IDM_username> is the username of the user and <IDM_userpassword> is the password of the user.
The result of this call is:

{
"result": [
{
"_id": "8df2eb7f-e4cc-410e-aeb4-27144e18b3a5",
"_rev": "00000000527d672e",
"name": "Analytics Cookie",
"description": "This is a demo cookie"
},
{
"_id": "80b3152b-0980-4299-9a02-fddf6cccea66",
"_rev": "00000000556558cb",
"name": "Marketing Cookie",
"description": "this cookie is used for marketing"
},
{
"_id": "69255a20-6c07-419e-a23d-f2fa0c0ee76a",
"_rev": "00000000d1a75e20",
"name": "Security Cookie",
"description": "This cookie is mandatory for the website to work"
}
],
"resultCount": 3,
"pagedResultsCookie": null,
"totalPagedResultsPolicy": "NONE",
"totalPagedResults": -1,
"remainingPagedResults": -1
}

This JSON contains a table with a list of Cookies managed in IDM. For each cookie we have his_id, name, description and _rev. Note: The _id of the Cookie is used to add or remove a consent.

List user’s Cookie consents
To list user’s consented Cookies execute the following REST call:

curl --location --request GET 'http://<IDM_SERVER>:<IDM_PORT>/openidm/managed/user?_fields=Cookies&_queryFilter=true' \
--header 'X-OpenIDM-Username: <IDM_username>' \
--header 'X-OpenIDM-Password: <IDM_userpassword>'

where <IDM_SERVER>, <IDM_PORT>, <IDM_username> and <IDM_userpassword> have the same meaning as for the first example.
The result of this call is:

{
"result": [{
"_id": "ac42dc30-7d39-4fc8-825c-aa5818105626",
"_rev": "00000000ec962b70",
"Cookies": [{
"_ref": "managed/Cookie/8df2eb7f-e4cc-410e-aeb4-27144e18b3a5",
"_refResourceCollection": "managed/Cookie",
"_refResourceId": "8df2eb7f-e4cc-410e-aeb4-27144e18b3a5",
"_refProperties": {
"_id": "6ece678b-917a-449b-9cd8-c3239b319595",
"_rev": "00000000152aa095"
}
}]
}],
"resultCount": 1,
"pagedResultsCookie": null,
"totalPagedResultsPolicy": "NONE",
"totalPagedResults": -1,
"remainingPagedResults": -1
}

This JSON contains a table with a list of relations (i.e. consents) the user has with Cookies. In the example above, the user has only one consent with the Cookie "_ref": "managed/Cookie/8df2eb7f-e4cc-410e-aeb4-27144e18b3a5" and this consent’s id is "_id:"6ece678b-917a-449b-9cd8-c3239b319595" .

Add Cookie consent
To add Cookie consent execute the following REST call:

curl --location --request PATCH 'http://<IDM_SERVER>:<IDM_PORT>/openidm/managed/user/<USER_ID>' \
--header 'X-OpenIDM-Username: <IDM_username>' \
--header 'X-OpenIDM-Password: <IDM_userpassword>'
--header 'Accept-API-Version: resource=1.0' \
--header 'Content-Type: application/json' \
--data-raw '[{
"operation":"add",
"field":"/Cookies/-","value":{
"_ref":"managed/Cookie/<COOKIE_ID>"
}
}]'

where <IDM_SERVER>, <IDM_PORT>, <IDM_username> and <IDM_userpassword> have the same meaning as for the first example. And <USER_ID> refers to the ID of the user for which we will consent this Cookie and <COOKIE_ID> is the ID of the Cookie for which the user is consenting.
The result of this call is:

{
"_id": "ac42dc30-7d39-4fc8-825c-aa5818105626",
"_rev": "00000000ec962b70",
"preferences": {
"updates": false,
"marketing": false
},
"mail": "stephane.orluc@gmail.com",
"sn": "Orluc",
"givenName": "Stephane",
"userName": "sorluc",
"accountStatus": "active",
"effectiveAssignments": []
}

This JSON is an overview of the managed user for which the consent has been added.

Revoke Cookie consent
To revoke a Cookie consent execute the following REST call:

curl --location --request PATCH 'http://<IDM_SERVER>:<IDM_PORT>/openidm/managed/user/<USER_ID>' \
--header 'X-OpenIDM-Username: <IDM_username>' \
--header 'X-OpenIDM-Password: <IDM_userpassword>'
--header 'Accept-API-Version: resource=1.0' \
--header 'Content-Type: application/json' \
--data-raw '[{
"operation":"remove",
"field":"/Cookies",
"value":{
"_ref": "managed/Cookie/<COOKIE_ID>",
"_refResourceCollection": "managed/Cookie",
"_refResourceId": "<COOKIE_ID>",
"_refProperties": {
"_id": "<REF_CONSENT>",
"_rev": "<REV_CONSENT>"
}
}
}]

where <IDM_SERVER>, <IDM_PORT>, <IDM_username> and<IDM_userpassword>, have the same meaning as for first example. <USER_ID> refers to the ID of the user for which we will revoke the consentedCookie and <COOKIE_ID> is the ID of the Cookie for which the user removing his consent consenting. And finally <REF_CONSENT> is the reference of the link (the consent) between the User and the cookie and <REV_CONSENT> is the version of the consent. Note: <REF_CONSENT> and <REV_CONSENT> are retrieved when you list user’s Cookie consents (see above how to do it).
The result of this call is the same as when you add a Cookie consent:

{
"_id": "ac42dc30-7d39-4fc8-825c-aa5818105626",
"_rev": "00000000ec962b70",
"preferences": {
"updates": false,
"marketing": false
},
"mail": "stephane.orluc@gmail.com",
"sn": "Orluc",
"givenName": "Stephane",
"userName": "sorluc",
"accountStatus": "active",
"effectiveAssignments": []
}

This JSON is an overview of the managed user for which the consent has been revoked.

Get Consent history
To get the consent history of a user execute the following REST call:
Note: in this post we are viewing the full the consent history with an administrator account.

curl --location --request GET 'http://<IDM_SERVER>:<IDM_PORT>/openidm/audit/activity?_queryFilter=eventName%20co%20%27relationship%27%20and%20userId%20eq%20%27<USERNAME>%27'' \
--header 'X-OpenIDM-Username: <IDM_username>' \
--header 'X-OpenIDM-Password: <IDM_userpassword>'

where <IDM_SERVER>, <IDM_PORT>, <IDM_username> and<IDM_userpassword>, have the same meaning as for first example. <USERNAME> refers to the Username of the user for which we want to get his consent activity.
The result of this call is:

{
"result": [{
"_id": "2190ab24-146c-4feb-b2ed-1bcd8b73157d-94386",
"timestamp": "2020-09-28T14:03:35.997Z",
"eventName": "relationship_deleted",
"transactionId": "2190ab24-146c-4feb-b2ed-1bcd8b73157d-94359",
"userId": "sorluc",
"runAs": "sorluc",
"objectId": "managed/Cookie/8df2eb7f-e4cc-410e-aeb4-27144e18b3a5/users/526fedd8-a2b7-4115-9e9a-efa274b6fa99",
"operation": "DELETE",
"changedFields": [],
"revision": "000000001627a10a",
"status": "SUCCESS",
"message": "Relationship originating from managed/Cookie/8df2eb7f-e4cc-410e-aeb4-27144e18b3a5 via the relationship field users and referencing managed/user/ac42dc30-7d39-4fc8-825c-aa5818105626 was deleted.",
"passwordChanged": false
}, .......
]}

This JSON contains a table with all the Cookie consent and revoke operation the user has done. In the example above, the user "userId": "sorluc" has successfully revoked a consent "operation": "DELETE" he granted to Cookie managed/Cookie/8df2eb7f-e4cc-410e-aeb4-27144e18b3a5.

Conclusion

We’ve seen how to design and configure the managed object and the access right management we need to manage cookie consent in ForgeRock Identity Management. We’ve also see how to use it with the ForgeRock REST API.
In another blog note, I may present how to use it with our End-user UI and how to use a javascript widget to integrate the cookie consent management in any website.

--

--

Stéphane Orluc
Stéphane Orluc

Written by Stéphane Orluc

Sales Engineer at Ping Identity (historic ForgeRock) www.linkedin.com/in/sorluc (posts are my own and do not necessarily reflect the views of my company)

No responses yet