Centralizing Identity Data

Centralizing Identity Data

usecases

How the claims infrastructure can be used to centralize the identity data.

Overview

This article describes a common use-case. An organization has many clients and APIs that all need some portion of identity data about a user. How can the claims infrastructure be used to accommodate all parts of the organization.


The Problem

An organization has a online store, lets call it Company, with the following setup:

  • A Shopping website (ShoppingWebClient)
  • An Admin website (AdminWebClient)
  • A Shopping mobile application (ShoppingMobileClient)
  • A Store API for selling items in the store
  • An Inventory API for managing and viewing items in the store

The Company

Each of these systems require some details (claims) about the user to be able to operate properly. The following image overlays the claims on each system.

The Claims

  • sub - the username, can be changed by the user.
  • customer_id - the customer id can be used to show discounts etc. Cannot be changed by the user.
  • address - to know where to deliver and to present to user where to deliver
  • region - all items for sale are not available to all countries. This claim tells us what region the user belongs to.
  • store_id - the company has more brands, so the store the client is acting against has an id.
  • admin_id - when and admin user is updating the store the admin_id is used instead of customer_id.

The Claims based approach

By defining these claims centrally in the Token Service, and then mapping them to the appropriate tokens and clients, we can make sure that each part of the system only gets the information it needs.

Firstly, we define a number of scopes that contains the claims we're interested in. The scope is a grouping of claims, think of it as "Scope of Access". This makes it more manageable from both the Clients and the sys-admins perspectives.

The Shopping website might know what claims it needs for the website itself but it probably doesn't know what claims the shopping API requires in order to be able to place orders. So requiring the client to request claims for the API is usually not a good idea. Instead we map the claims to scope, and then also map these claims to tokens, so that some claims end up in the tokens that the client can read, and some end up in the tokens that the API can read. For more details about these mappiings see claims explained.

With the requirements defined in the problem section we get the following mapping table:

ScopeClaims
order_placeaddress, customer_id
inventory_readregion, store_id
inventory_writestore_id, admin_id
addressaddress
openidsub

The address and openid scopes are standard scopes with standard claims mapped to them from the OpenID Connect Specification.

Then we also map the claims to tokens for the clients like this:

ScopeTokenClaim
order_placeaccess_tokenaddress, customer_id
order_placeid_token-
inventory_readaccess_tokenregion, store_id
inventory_readid_tokenregion
inventory_writeaccess_tokenstore_id, admin_id
inventory_writeid_tokenadmin_id
addressaccess_token-
addressid_tokenaddress
openidall tokenssub*

* - sub is actually always present in all tokens so the openid scope serves no purpose for claims mappings in this example. But it is still needed since the client wants an ID Token which is only issued when the openid scope is requested.

Now if ShoppingWebClient requests tokens it can simply as for the scopes order_place, inventory_read, address and openid and the tokens it receives will be mapped as expected for each recipient.

Why do we explicitly have the address scope when the order_place contains the same claim? This is for two reasons, firstly there is a standard mapping in OpenID Connect for the address, which is good to use. Secondly, it is a claim that the client may or may not be interested in, so if a third party client would operate against the store, it may not need the address since it will perhaps not be meaningful for that client. To avoid unnecessary data leak we let the client ask for the address when it needs it. The API will anyway receive it, since it's mapped in the access token.

Token Mappings

The mappings can be done differently for different clients by using different mappers.

Tokens and Clients

This can be confusing for newcomers to claims based systems and OpenID Connect, but the point here is that there are two types of tokens being issued. ID Tokens, which the client can read, and Access Tokens, which the client receives but cannot decode. So we can safely put claims in the access token and be sure that only the API is the reader of that data.

The access tokens is normally an opaque token, meaning it holds no data, only a reference to data. The API can look this up, but the client cannot.

JWTs and tokens

The ID Token is always a JWT which means the client can always read it.

The Access Token could be a JWT, but in the use-case presented it must not be, since that would leak data to the client when it's not desired to do so.


Conclusion

The claims infrastructure is a powerful tool to keep the identity data secure and maintain full control over what part of the system gets access to which information. This is critical in larger organizations and even more important when conforming to regulations such as GDPR.

Was this page helpful?