Skip to main content
Version: Next

Consent before login

v4 Changelog

  • Update components overview diagram to reflect data flow
  • Add section regarding responsibility isolation and fault tolerance
  • Specify ordering of synchronizations (anon to user, multi-devices, user to anon)
  • Add info regarding "get missing agreements" algorithm at post-login
  • Update table diagrams, move link with hash table to installation_agreement, remove "sync_enabled" flag
  • Improve multi-device synchronization to handle all possible logout cases
  • Add installation_hash and user_hash

Glossary

Consent : Description of data collection and usage by a specific feature in the app. A consent typically has a title, a content. A consent can be plugin specific.

Agreement, Agreement : The approval or denial decided by the user regarding a specific consent.

Installation id : Previously named installation ID. Instance within the app is ready to handle one specific user on a specific device. This time includes before effective login. When a new user is logged into the app and actively resets the device, the installation identifier must be reset.

Context

NAVIDA should comply with mandatory regulations regarding data collection and tracking consent. While these topics are already handled when logged in, AOK also needs to collect consent before login.

The approach described here would merge consent before and after login into one unified solution to record agreements from the user, or from a device.

  • Consent given before login is anonymous and should be recorded. At some point, when the user actually logged in, reconciliation should be performed between pre-login and post-login consents.
  • The most recent consent overtake previous ones. Even if the consent has actually been declined.
  • AOKs need to prove when the consent has been proposed, when it has been accepted and also what has been accepted.
  • A consent can not, in no possible ways, be deleted. Soft deletion should be a rule of thumb and considered as a consent revocation.

More details regarding requirements can be found here (German) : https://confluence-extern.plus.aok.de/display/PLATT/Requirements+Tracking+and+Consent+before+login

About installation identifier

Previous documentation mentionned an INSTALLATION_ID. In practice, this ID is closer to a installation identifier, since it might be reset while keeping the app installed (when another user try to login after a preceding one on the same device, for instance)

Components overview

Domain model and global diagrams

Entity relation model

Important: AGREEMENT and INSTALLATION_AGREEMENTS must have specific read/write permissions :

  • DELETE is impossible. The only exception is when the consent expires. This should be handled in an isolated service/database user.
  • UPDATE is impossible
  • Only INSERT is possible

For non-anon databases

For anon database

Requirements

Core

  • Users can accept or reject a consent. Such process is called agreement.
  • The CMT must give the support employee the same options for creating and processing the consent texts before login as the current Navida consent texts.
  • The agreement must be stored in a logged, timestamped, audit-proof and unchangeable manner.
  • The agreement must have a signature that prooves it has been signed from a specific content, and prooves if this consent has been changed subsequently.
  • The signature (or hash) must be as unchangeable as the agreement itself.

Anonymous consents / consents before login

  1. Consents made before login should be stored in a dedicated database schema.
  2. They should follow the same access restrictions as consents after login.
  3. These consents must be linked to an installation/installation identifier.
  4. They must not be linked directly with a User ID.
  5. The installation ID is kept until a new user tries to log inside the app. When this happen, the app data should be reset and the installation id renewed.

Login

  1. Consents provided before login (in anonymous mode) should be copied to user consents.

Multi-device

  1. For the same user, consent should be synced with all logged in devices.
  2. Multi-device works only when user is linked with the app, which means the user is authed inside the app, with successful biometrics.
  3. If user is unable to authenticate/validate its biometrics, user should be considered as anon and device should be excluded from synchronization.

Logout

  1. When logging out, the installation id is preseved.
  2. At logout, the device should have the latest consents provided by the user.
  3. Once logged out, the device is no longer in sync with user consents.
  4. When logging back again, the device is re-synced with all device from users.

Support agents

  1. Support agents can view user agreements.
  2. They can reject consent on behalf of a user. However, it does not mean they can delete a previous agreement. --> They can only create a new reject agreement on behalf of a user.
  3. They can also view agreements for a specific installation ID
  4. They can create a rejection agreement for a given installation ID. They can not create acception agreements
  1. User can view approved/rejected consents inside App > Settings > Consents
  2. User can give a new agreement on consents in Consents settings (i.e. : provide a new agreement, not updating the previous one)

Data transparency

  1. If user agreed on tracking, User can view Adobe Analytics tracking ID in Consents settings
  2. User can view Installation ID in the same screen.
  3. User can view User ID in the same screen.

Agreement revocation

  1. Revocation does not mean delete consent. It does mean we create a new rejected agreement.
  1. When the content of a consent is updated, its version should be incremented.
  2. When a new version of a consent is available, a new agreement should be asked to the user if and only if they haven't rejected the previous version.
  3. You can check following use case : Get missing consents

Installation identifier

  1. The installation identifier should be a unique identifier (UUID-v7)
  2. This installation id must be persisted on device.
  3. Installation id must be first set on first app launch.
  4. The installation id must be renewed when another user tries to log inside an app already linked to a previous user (Deduced from The CMT/App must ensure that only a new user who has freshly installed NAVIDA for the app installation first lands on the Navida generic onboarding screen and then on the consent before login page. Users who have already viewed the Navida Intro Page in the past and/or have been logged in will not see the consent in front of the login screen)

Safety

  • Any public endpoints must be secured in ways to prevent attacks and data tampering.

Data hosting

  1. Anonymous-only agreements (so agreements proceeded before login) should be stored on AOK PLUS side, inside a specific schema common for all AOKs.
  2. Agreements after login are stored depending on the user region : BaWü has its own database, PLUS has its own.
  3. Link between user ids and installation ids should be stored on the user region's database.

Responsibility isolation and fault tolerance

Anonymous consents should always be handled by the anonymous consent microservice, while user consents are handled by the user consent microservice.

When synchronization occurs between anon and user agreements, the two microservices are able to provide to each other the information. To do so, they should use a dedicated Kafka consumer group.

This use of Kafka preserves isolation between anonland and userland. But it also improves fault tolerance and horizontal scaling by acting as a queue.

Kafka messaging diagram

Use cases

Handling installation id

  • Generated on client side.
  • Should be a UUIDv7
  • Stored on device, in keychain
  • First generation on app boot. Then regenerated when a new user logs in and uses the reset feature.

The idea is simple : after login, we register the user id associated with the current installation id. It should also calculate the latest agreements for all consents, and reference them in all installations of the user.

The endpoint proposing this linking should absolutely be private.

To do so, we should trigger a post-login request to the consent microservice, which will store this link in a dedicated database.

Notice: Our proposal process does not add a user id on the existing agreements. It only provides a way to re-link anonymous agreements with the user after they have logged in.

It could also be thinkable to update agreement and set user id. However, since integrity of this agreement is valuable, we prefer to keep agreement unchanged and have this link made in another table. This process would be compatible with insert-only permissions on agreements table.

Example with BaWü user :

Agreements synchronization

Agreements can divided according :

  1. The login status of the user (Anon/User).
  2. The device the agreement has been provided on, for the same user (Multi-device).

These two criterias have direct consequences on data storage :

  1. When user is anonymous, agreement is handled by AOK PLUS. When logged-in, agreement is handled by the user's Krankenkasse.
  2. Consents that applies on anonymous also applies when logged-in, and vice versa: Agreements should be copied from anonymous namespace to the appropriate region, depending on user region.
  3. Once logged in, the user shares the same agreements over all their devices.

To solve these multi-DB, multi-device solution, we propose three different types of synchronization, trigerred on two specific events :

On login :

  1. Link device with user
  2. Import anon agreements to user database (anon ➡️ user)
  3. Synchronize device agreements
  4. Push device agreements to anon database (user ➡️ anon)

On providing new agreement :

  1. Push device agreements to anon database (user ➡️ anon)

Ordering of synchronizations on login

The order defined above should be respected to stay up-to-date with the latest agreements provided, especially when :

A device is no longer logged-in (including failure in providing biometrics).

In this case, the device should be considered anon again, and still have the latest agreements on anon consents.

User logs in with a brand new device.

This device will create new agreements on consents required before login. Therefore, these consents should be imported as the latest agreements of the user while logging in.

In such scenario, device B should import agreement from device A, then push this agreement in the anonymous database to make sure the device still has the agreement when the user logs out (volontarily or not).

Anon ↔️ User sync

Login status can change on two occasions : while logging in or while user is providing new consent agreements. For both events we should synchronize agreements between anon and non-anon databases.

This synchronization is based on the installation ID of the device and not the user ID, since this concept does not exists on anon database.

Important : Agreements are copied but all their attributes should be kept unchanged. Even the author type, even the timestamp. Data should still be capable of generating the agreement hash.

Anon ➡️ User (used only on login)

User ➡️ Anon

Multi-device sync

As you may have guessed, providing consent before login makes the agreements "device-centric". However, agreements should still be user-centric.

That means, if users have multiple devices, they expect the agreements to be mutualized across devices. If a user is no longer authenticated on a device, mutualization should stop right away.

Also, agreements are be immutable. That means you should not copy them from a device to another, you should not update them either. Otherwise, we might lose our ability to proove their origin/authenticity.

To fit these constraints, we decided to create a many-to-many relationship between devices/installations and agreements. That means an agreement can be referenced by one or multiple devices, which belongs to a user (or not, yet).

When the user logs inside the app on a specific device (A) (including providing biometrics or refreshing the access token), the agreements from all other devices should be imported. If there is a device (B) with later agreements, these agreements should be linked to the device (A) when user logs in device (A).

Also, and first of all : a synchronization request can only come from an authenticated device. The id of this device should be provided, in order to re-enable sync to this device if it has been disabled before (because of a logout for instance).

Register an agreement

NB: AOK should keep an integrity proof of this consent.

Agreements are the most sensitive information in this concept. To make them as immutable as possible, we must clearly distinguish :

  1. The author of an agreement, which could be anon, user or support. Author type and identifier is part of the agreement itself and must be stored.
  2. The devices referencing an agreement. These devices will rely on the agreements while not necessarily be the one on which the decision has been made.

When we talk about registering an agreement, we are refering to topic no. 2.

The endpoint registering agreement should be a semi-public endpoint. That means auth is optinal and will provide additional info on user. If not, we fallback to an anonymous user..

  • If the user is authenticated and consent cannot be anonymous, author type will be USER.
  • If not, author type will be ANON.

In both cases, agreement will be saved and referenced by at least one device : the one we just used. If user is connected, agreements synchronization should occur just after.

Sequence diagram

Please note this sequence diagram could occur before or after login. The process would be the same. The differences would rely in data :

  1. Consent before login would not have any user ID provided.
  2. Consent after login would have both user and sesion ID.

Flowchart

Get list of latest agreements

For a user

As defined in the requirements, an agreement can be anonymous and should be :

  • persisted
  • cross-device, cross-platform
  • revocable
  • version-specific
  • rejected automatically if the previous version was rejected
  • if preceding a successful login, linked to the user

User's consents is the aggregation of all its device agreements.

In the following example, the latest agreements of User are :

  • ConsentX-2023
  • ConsentY-2024
  • ConsentZ-2024
  • ConsentW-2024

Consent-Y-2023 is ignored since a newest agreement is available.

Get user agreements

For a device

The same principles apply for a single device. Instead of using the user id, installation id is used to retrieve the agreements. Agreements synchronization at login / new consent will automatically push agreements given from other devices in our device scope.

Agreements have important legal constraints. In these constraints, data localization is crucial. The rules established by AOK PLUS and BaWü are the following :

  1. Consents after login must be stored in the database associated with user's AOK : BaWü users' agreements should be stored in BaWü database, and so on for PLUS and other AOKs.
  2. All consents provided before login should be stored in a specific schema, maintained by AOK PLUS.
  3. However, we should import consents provided before login to the user's region DB, since this region should have the autority to revoke the consents on demand.

Therefore, agreements of a user should always be stored in a region-specific database (after login). Agreements of a device that can be anonymous should always have a copy in the anon database (before login).

Get device agreements in anon-mode

Get missing agreements

Intro: Post-synchronization state

The above algorithms work in every case. But there is a state, just after user logs in, where agreements of the currently used device has all the agreements of the user. Post-login is also the moment where we look for missing consents.

These conditions dratically reduce the complexity of finding missing agreements : only current device agreements can be checked to get an overview of latest agreements given by user, on all their devices.

The following algorithm relies on this principle.

Algorithm

Finding out what consents are missing is actually really similar whether you are anonynous or not :

  • If anonymous, we should consider finding the missing consents for the current device
  • If connected, since agreements are referenced accros all devices at login/new consent, you can determine missing consents by only looking on the current device agreements.

We adopt security by design by not providing all the agreements the user has already done, but the ones that are actually missing. This prevent malicious users to find out what consents have changed from another device. When user is logged out, it keeps scope on the device only, by design.

Plugins should still be able to check if an agreement has been approved for a specific consent.

Once having this list of missing consents, the frontend app will only have to display them and ask for consent.

This case is important for plugins that need to check the consent has been explicity given and not revoked (opt-in).

This use case could be resolved by getting the list of all agreements, and check if the consent is in this list and is approved.

Tracking before login

  • Get agreements by installation id

Integrity check

As AOK, we should be able to proove the user gave their consent to a specific consent. This means there should be a double integrity check for :

  1. What consent has been proposed to the user, including its title, the related plugin, description, consent version.
  2. When it has been accepted or rejected.

For both prooves, we would rely on SHA256 hashes and on double-sided hash generation. The user device should generate all hashes, then they will be regenerated on server side. Client-side and server-side hashes should match.

This system would prevent any race condition to succeed, especially if a consent is modified on AOK side, while a user has it displayed on its device.

Content hash

Agreement hash

Installation hash

User hash

Note: user hash should be null on anonymous database.

When an agreement expires, it should be deleted from the database. To do so, we propose to create a dedicated microservice / batch service with exclusive deletion rights on the database.

The validity period of a consent would be defined in the CMS, in years.

Defining expiration date of an agreement is the following formula :

expiry = agreement_timestamp + expiry_in_years

This value might be stored on save to improve batch performance. However, this would prevent any consent expiration to update.

Support tools : specificities

Users of NAVIDA can rely on a dedicated assistance in case of troubles, or if they decide to use their "right to be forgotten".

In that case, the operator should be able to view the history of consents for a specific user, OR for a specific installation id.

They can also revoke any previous agreed consent, on behalf of a user and if they have their approval.

They are only allowed to reject/revoke a consent on behalf of a user.

To handle these cases, we propose three specific endpoint :

  1. Get history of all agreements for a user (check get user agreements)
  2. Get history of all agreements for a device (check get device agreements) - in this case, history can only come from anonymous database.
  3. Create a new rejected agreement for a user/device.

Any agreement created by support should have attribute author_type to SUPPORT.

What installation identifier ?

When the support tool operates on behalf of a user, we might not have any device we can link to the agreement.

One way to solve this issue is to persist a dedicated installation identifier for support. Only one device of this kind should exist per user.

Edge cases

User logged in, and then logs off

The resulting state is an anonymous-ish status : the app is still linked to the same device. However, link with the user should be cut until a new successful login.

This is done by design : when the user logs out on device ABC, volontarily or not (biometrics failure), the device no longer import agreements from other devices.

Only latest agreements for this specific devices will remain. Any new agreement coming from another devices will be ignored.

After re-login on the same user, a synchronization request should be made. This request should always includes what installation id it comes from.

The device would be reset only after a new user tries to log in. In this case, the user must face a dialog asking to reset the app.

This reset will generate a new Installation id, that can be linked with this new user.

Impact on saving agreement

No real impact. As a reminder, the rules are the following :

  • if the user is authed, author type should be USER.
  • if not, agreement should embed author type ANON. It is also stored in the specific anon database.

This rule is set to keep an authentic and exact view of the app status when anon/user made their agreement. It also has an impact on hashing.

Impact on fetching latest user/device agreements

This has no impact on retrieving the latest agreements, for a device or either a user.

When looking for a device agreements, we always follow the logic defined in get device agreements.

Same user logged inside multiple devices

When the user uses multiple devices, we expect the app to automatically "sync" their agreements across all devices.

This is done by making the agreements device-centric, and having multiple devices reference the same agreements. A user has a list of devices, and therefore all the agreements are referenced on all devices. So looking on the current device should be enough.

However, if any issue create a incoherence between two sessions, it is still possible to get the agreements of a user by searching the agreements in all their devices.

User logs in, then logs out, and then explore the app without login

This use case should be really rare, and could be the source of many confusion. If the logged out user decides to explore the app without login, the installation ID is preserved.

From a technical perspective, nothing prevents this to happen. Once the user logged out, the synchronization with other user devices has been cut, so any further consent prompted will be set for the device only.

User logs in successfully. Later on, user tried to login, but failed biometrics/forgot password.

In this case, since no login tentative with another account has been made, we preserve the same installation id.

If the user ultimately logs with another account, the installation id should be immediately reset after login. Then, consents will be prompted to this new user.

FAQ

Why don't you just copy agreements between devices and change device id in agreements table ?

Agreements have a legal value. The whole system is designed to make them as immutable as possible.

Changing installation id on agreement would make their hashes no longer valid. We prefer to consider them as our unique source of truth, store the link between multiple installations in another table and then deduce what logic should be applied.

It also helps continuous improvement and adpatation to regulators, since no data would have to be altered. Only business logic would have to be changed.