Problem/Motivation

A fully compliant solution for GDPR requires not only getting user consent but also creating a provable record of it on both the client and server sides. The current implementation of the Klaro module stores user consent on the browser (client-side) within a cookie or local storage, but this record is insufficient for demonstrating compliance.

As stated in the official text of the GDPR, Article 7 (https://gdpr-info.eu/art-7-gdpr/), paragraph 1:

"Where processing is based on consent, the controller shall be able to demonstrate that the data subject has consented to processing of his or her personal data."

To meet this requirement, the solution must create a record that includes:

The date and time of consent.

The user's choices (which categories they accepted).

The state of the cookie banner at the time of consent (e.g., the version of the banner or services).

The existing client-side cookie set by the Klaro module (e.g., named klaro) lacks this essential logging information. It only contains a list of accepted services. Without a detailed client-side cookie and a corresponding server-side log, site administrators cannot provide proof of consent, which puts them at risk of non-compliance.

Steps to reproduce

Install and configure the Klaro module on a Drupal site.

Enable the cookie banner and configure at least one service.

As a user, visit the site for the first time.

Click "Accept" or make choices and save them on the cookie banner.

Observe that a cookie named klaro is set in the user's browser. This cookie stores a list of the services the user accepted.

Note that this client-side cookie does not contain a timestamp or a version number of the consent dialog.

Furthermore, note that there is no corresponding log or entry in the Drupal database to track this consent.

Proposed resolution

Introduce a versioning system for the klaro-configuration and an UI listing the different versions. I would suggest to just store the complete config json as it appears in `drupalSettings.klaro.config` and assign a UUID to it that can be referrenced within the serverlog-entry. This also adds new feature-possibilities like import/exporting config and/or going back and forth to specific versions.

Implement both a client-side logging cookie and a server-side logging mechanism to record user consent. This would involve:

Client-Side: Updating the Klaro module's behavior to set a dedicated cookie (or add to the existing one) with detailed logging information, including a timestamp and a version of the consent dialog. (While client-side logging seems not to be legally required for compliance though.)

Server-Side:

Creating a new database table to store consent records.

The website's Klaro configuration should be updated to send an asynchronous request to the server from the client-side JavaScript when the user makes their choice.

This request should send key information for each consent event, such as a unique, non-personally identifiable identifier for the user (e.g., a session ID or a unique token), the timestamp, the accepted categories, and the state of the cookie banner (version, etc.).

Remaining tasks

Discuss the best approach for implementing the logging on both the client and server sides.

Determine the necessary data points to store for a complete consent record.

Introduce a versioning system for the klaro-configuration and potencially an UI listing the different versions.

Introduce a user-UUID that will be assigned on initial pageload if not set yet and store within klaro cookie/localstorage and serverlog

Develop the actual logging as well as an UI to browse and search the entries.

Write tests to ensure the new functionality works correctly.

Issue fork klaro-3549264

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

rafaellapinho created an issue. See original summary.

rafaellapinho’s picture

Issue summary: View changes
dunx’s picture

I've been discussing this with Rafa elsewhere and she's correct that to be totally GDPR compliant you need to be able to log how approval was requested and how it was obtained. The tricky bit is working out what you can store in this log to ensure you remain GDPR compliant!

Klaro's paid for versions include managed consent records and ChatGPT tells me the following:

Klaro supports a mechanism for recording users’ consent decisions so that the site owner can demonstrate when, how, and for what consent was given (or declined) — an important requirement under GDPR (“accountability” principle).

Depending on how Klaro is configured (client-side storage, backend logging, or a hybrid), the consent records can include:

  1. Consent decisions for individual services E.g. { "google-analytics": true, "openstreetmap": false, … }
  2. Klaro config ID The identifier of the particular Klaro configuration (or version) used when the user made the decision
  3. Type of consent decision action E.g. "accept", "decline", "save", etc.
  4. Hostname / domain The site domain (or hostname) where the consent was collected
  5. URL path / pathname The specific page path where the user made the consent decision
  6. Client / user agent / version Some anonymous info about the client (browser or Klaro client version)
  7. Cookie or localStorage storage The record is stored in a cookie or localStorage (by default, Klaro stores the consent decision in the browser)
  8. Timestamp / digital signature / hash To ensure integrity and prove the record wasn’t tampered with, Klaro can cryptographically sign consent records with a timestamp and authenticated hash.

That list might be a good place to start.

scott_euser’s picture

Has anyone tried the paid versions to support the consent tracking? https://klaro.org/pricing
Does it just work or do we need to do something here in the Drupal module to start supporting that?

sascha_meissner’s picture

@scott_euser For that take a look at: https://www.drupal.org/project/klaro/issues/3529599 still needs review

sascha_meissner’s picture

sascha_meissner’s picture

Issue summary: View changes

Thanks for creating and working on this issue.
I´m looking forward to implement this.
Updated the remaining tasks

sascha_meissner’s picture

Issue summary: View changes
dunx’s picture

That seems quite specific to a paid for kiprotect integration.

I may be naive here, but shouldn't it be easy to log something in a Drupal table? We just need some config for housekeeping activity and a View to list records. Let's be honest here, this has not been tested in court to my understanding, so initial requirements can be minimal to show we're doing what the legislation requests. It doesn't have to be a massive piece of functionality.

sascha_meissner’s picture

@dunx Oh maybe you got it wrong, the whole "paid kiprotect stuff" is a seperate issue that has nothing to do with this one (besides that it also provides consentlogging).
I´ll be working on this issue and implement this feature here step by step. See the remaining tasks

scott_euser’s picture

Worth considering views integration and permissions here too. And per GDPR should have right to be forgotten somehow. Not sure what else needs to be considered here.

We could avoid reinventing the wheel if there is somewhere else to copy from (copy in terms of functionality not code I mean)

jurgenhaas’s picture

The right to be forgotten and related stuff gets handled in the PII module as part of the privacy working group, see also #drupal-cms-privacy channel on Drupal Slack.

sascha_meissner’s picture

AFAIS In the case of the consent log, the right to be Forgotten is generally overridden by your legal obligation and legitimate interest to maintain accountability under the GDPR. (Article 5(2))

For the same reason you would not have to collect a consent to log the consent-states. (which also wouldnt be possible, because how to store a "reject event" when i reject to do so ^^?! ) its sole purpose is compliance assurance. + they dont have to contain any personal data anyways. But the question that arises is how long to store (Article 5(1)(e)) "no longer than is necessary", this might be an adjustable configuration setting. But yeah there is definitely more to consider ;) For example IMHO clientside logging is not necessary, it should be sufficient to additionally store a uuid within the already existing cookie for the linkage to the serverside logging ( which is broken anyway when a user deletes their cookies)

I´m gonna start with something that needs to be done anyways and that is the versioning of the klaro config, e.g everytime you update the configuration a new version entry will be dumped. So that a consent-log-entry can refer to a specific configuration of apps/texts/setting ("what did the user see at the moment of the event")

scott_euser’s picture

What I don't get is how its meant to be useful; its not like John Doe can say 'Tell me when I consented' because an anonymous visitor granting cookie consent has no PII to go along with their consent. Their Klaro consent UUID would be stored in a cookie, do we need to them let them see that somehow?

scott_euser’s picture

This page has screenshots for how Iubenda deals with consent records: https://www.iubenda.com/en/help/6469-consent-solution-getting-started if its helpful

scott_euser’s picture

StatusFileSize
new99.54 KB
new144.08 KB

Here is specifically what Iubenda stores:

Overview of all consents:

Screenshot of overview

Details of an individual consent when clicking view icon from the overview:

Screenshot of details

sascha_meissner’s picture

well, its compliance vs reality :D ... However, the GDPR's Accountability Principle (Article 5(2)) focuses not on identifying John Doe, but on demonstrating that you, the Controller, followed the law. Which should be veeery useful in case of an investigation ;)

dunx’s picture

Agree the usefulness of the requirement is limited, but that's legislation for you. You have to record that 'anybody' had engaged with the cookie banner (uuid, datetime, Klaro config settings), but not record any personally identifying information about them (such as their IP address, which is stored in server logs but nobody seems to care about that even for PII). There shouldn't be any PII in the cookie log to forget.

If 'somebody' were to instigate an investigation you would just look back to the correct time period to show what you were doing generally. Or even just look back over any time period to show you are recording something. What that's useful for is beyond me. That's my practical view point anyway.

As for duration; I've seen both 7 years and 'as long as your longest cookie lifetime' - there really is no rule and it hasn't been tested in court yet. I don't know what duration Iubenda, CookieBot, Klaro, etc. use but we could follow their approach (or just make it configurable).

Config versioning is a good start for sure. It wouldn't easily be able to store what the banner looked like though - the vast majority of cookie banners have different colours for Accept and Deny, which is against the legislation. Nor could it store whether users could retrospectively change their cookie settings. I suspect we're limited to 'whatever is stored within the Klaro config' here, but a good start.

sascha_meissner’s picture

Assigned: Unassigned » sascha_meissner