Pairwise Pseudonymous Identifiers

Pairwise Pseudonymous Identifiers


Increasing Privacy with Pairwise Pseudonymous Identifiers

The OpenID Connect standard defines a way of increasing the user's privacy using something called Pairwise Pseudonymous Identifiers or PPIDs. The combination of user and client creates a unique identifier which represents the user for that particular client. When using PPIDs, the client does not know about the user's actual identifier, which may be an email address, employee number, social security number, or other ID that contains Personally Identifiable Information (PII). Even when the user ID does not include sensitive information, PPIDs are helpful in increasing privacy by creating a unique ID for each client. As a consequence, different clients are not able to collude or share information about users. This is the case because each client knows the same user by different IDs. This concept is illustrated in the following figure:

Overview of pairing of user IDs per client

In this example, a user named Alice logs in using her email. Instead of sharing this ID, however, a pseudonymous user ID is provided to each client. If the two then shared usage and behavioral statics about Alice, each client's data would not be possible to correlate with the other's. Also, if either client was breached, the attacker would not obtain Alice's PII; instead, they would only gain a random, opaque ID. In these ways, PPIDs enhance Alice's privacy.

Sector Identifiers

There are times when multiple clients are working together in legitimate ways, however. This often comes up when two clients need to access or store user preferences, products, shopping carts, medical records, etc. In such cases, clients may be placed in the same group or "sector". This will allow clients within this sector to obtain the same PPID for a user. When this feature is used, the pairing is not client-based but rather sector-based. In such a situation, the above diagram would look more like this:

Pairing of user IDs per sector

In this diagram, client www_1 is not grouped together with any other clients, so it doesn't need to have a sector ID configured. cloud_app_1, however, has been grouped together with a mobile app with an ID of cloud_app_1_mobile_app. This grouping is designated by configuring both with the sector ID cloud_app. In so doing, www_1 continues to receive different pseudonymous user IDs for Alice, but both the cloud app and its mobile app receive the same PPID for Alice. This allows these two to work together and store data related to Alice. Her privacy is still protected, however, by restricting her actual user ID and limiting the sharing of the same PPID to a subset of clients. It also remains impossible for www_1 and all clients within the cloud_app sector to collude with each other. The configuration for these three clients is shown in the following listing:


This configuration can be done using Curity's admin UI of course. When doing so, these settings will be presented on each client in a manner similar to the following figure:

Configuring a client's sector ID in the admin UI

A sector ID only needs to be configured like this when:

  • The client has multiple redirect URIs configured and
  • The hosts of those redirect URIs are not the same.

So, if only one redirect URI is configured for a client, like www_1, then a sector ID need not be configured. Even if multiple redirect URIs are defined, a sector ID is still not needed if the host name of those redirects URIs are the same.

Dynamic Clients

When non-templatized Dynamic Client Registration (DCR) is enabled, an app may request the use of PPIDs when registering. It knows that this is supported by examining the OpenID Connect metadata and finding this value:


If an OAuth profile has been configured to require the use of PPID, then the public element of the list will not be present. In any case, the client will receive a PPID by registering as a non-templatized client using the subject_type client metadata with a value of pairwise. (Templatized, dynamic clients will use the PPID settings of the template and cannot influence this during registration.) When non-templatized, dynamic clients include multiple redirects URIs in the registration request and any of those have different host names, a sector_identifier_uri must also be included. Such a registration request will look similar to this:

    "redirect-uris":["https://localhost:8080/cb", ""],

Accepting such a request is potentially dangerous and could allow a rogue actor to join a sector of victim client(s). If such an attack is successful, the perpetrator could learn about Alice's true identity or at least her pseudonymous ID as known to the victim client(s). To avoid this, the dynamic client's sector ID is derived from a sector ID URL provided in the registration request. The eventual sector ID that is used will be the host portion of this URL but it must first be validated. This validation occurs by making an HTTPS request to the URL to obtain a JSON array. This array must contain all redirect URIs of the new dynamic client. This interaction is shown in the following figure:

Sector ID validation process

WARNING Serving the sector ID validation endpoint from a shared hosting provider, IaaS, PaaS, or SaaS platform that uses the same host name between tenants and/or users will expose the client to attack by rogue, dynamic clients wishing to learn the ID of users as known by those victim clients. A sector validation endpoint should never be served from a host that is not under complete control of the client.

Conclusion and More Info

Hopefully this short writeup taught you what a PPID is, how it can be used to enhance user privacy, and some of the concerns you need to have in mind when deploying it. PPID support is new in Curity 3.1.0, so you will need to upgrade from older versions before you can use this functionality. If you aren't yet running Curity, you can easily sign-up and download it. Also, more information about setting up and using PPIDs in Curity can be found in the Token Service administrator guide. If you have questions about this article, feel free to contact us.

Was this page helpful?