Case Study Bloom Credit: Multi-Provider API Security with KrakenD

You are viewing a previous version of KrakenD Enterprise Edition (v2.3), go to the latest version

Document updated on Oct 18, 2021

Revoking valid tokens with a Bloom filter

The API Gateway authorizes users that provide valid tokens according to your criteria, but at some point, you might want to change your mind and decide to revoke JWT tokens that are still valid.

Revoke tokens via API
The Enterprise version offers a Revoke Server that coordinates token revokes in a cluster using a REST API.

When are you going to need this? Examples of situations where you might need to revoke perfectly legit tokens:

  • A user wants to log out from all my devices.
  • An administrator wants to kick out someone from the platform.
  • A software release needs all sessions renegotiated again, or users of a specific app (Android, iOS, Web app, etc.) have to be invalidated.

Storing blocked tokens using the bloom filter

KrakenD integrates the bloom filter component that allows you to store in an optimized way tokens to revoke on subsequent requests.

When you enable the bloom filter, it inspects the payload of incoming JWT tokens to check if any configured fields in token_keys contain a blocked value. And if a block is found, access is not permitted.

The bloom filter component brings the following functionalities:

  • Hold blocked tokens in memory
  • Propagate blocked elements through an RPC interface
  • Check tokens and discard access on positives

Bloom filter client

The communication with the bloom filter is RPC-based. The component exposes a listening port of your choice to receive updates of the bloom filter (single or batch), but a client is needed to communicate with the component.

When using the open-source edition, you have to build your client. Look at the bloom filter library, which includes a client. In addition, the KrakenD Playground project consists of a sample web page with a form and an RPC client that sends commands to the bloom filter and updates it.

Note that this low-level bloom filter client requires elements added to the bloom filter to conform to a special format: a key, representing a field in the token, separated by a hypen (-); and the value of that field that will be used to revoke requests. In the example below, you could expire the token for an individual user by adding jti-mnb23vcsrt756yuiomnbvcx98ertyuiop to the bloom filter. This can also be seen in the sample web page with a form and an RPC client in the KrakenD Playground project.

When using the Enterprise edition the Revoke Server connects to all KrakenD instances as a client, and there’s nothing you need to build to make it work.

Bloom filter performance

The Bloom filter is ideal for supporting a massive rejection of tokens with very little memory consumption. For instance, 100 million tokens of any size consume around 0.5GB RAM (with a rate of false positives of 1 in 999,925,224 tokens), and lookups resolve in constant time (k-number of hashes). These numbers are impossible to get with a key value or a relational database.

The tokens are in-memory and directly in the rejecter interface, so the system quickly resolves the match.

Configuration

The bloom filter lives at the extra_config in the root level of the configuration, using the namespace auth/revoker:

{
    "version": "2",
    "name": "My lovely gateway",
    "extra_config":{
      "auth/revoker": {
        "N": 10000000,
        "P": 0.0000001,
        "hash_name": "optimal",
        "TTL": 1500,
        "port": 1234,
        "token_keys": ["jti"]
      }
    }
}

All the configuration fields are mandatory and are explained below:

Fields of "auth/revoker"
* required fields

N * integer
The maximum Number of elements you want to keep in the bloom filter. Tens of millions work fine on machines with low resources.
Example: 10000000
P * number
The Probability of returning a false positive. E.g.,1e-7 for one false positive every 10 million different tokens. The values N and P determine the size of the resulting bloom filter to fulfill your expectations. E.g: 0.0000001
Example: 1e-7
TTL * integer
The lifespan of the JWT you are generating in seconds. The value must match the expiration you are setting in the identity provider when creating the tokens.
hash_name *
Either optimal (recommended) or default. The optimal consumes less CPU but has less entropy when generating the hash, although the loss is negligible.
Possible values are: "optimal" , "default"
port * integer
The port number exposed on each KrakenD instance for the RPC service to interact with the bloomfilter. This port is allocated only to the clients (running KrakenDs).
token_keys * array
The list with all the claims in your JWT payload that need watching. These fields establish the criteria to revoke accesses in the future. The Revoker does not use this value, only the clients.
Example: "jti"

If you use the bloom filter together with the Revoken Server Enterprise , see its configuration.

Hygiene habits
Keep the life of your tokens short (e.g., 30 minutes).

Applied example

Our sample JWT payload has the following characteristics:

{
    "aud": "https://www.krakend.io",
    "iss": "https://api.krakend.io",
    "sub": "[email protected]",
    "jti": "mnb23vcsrt756yuiomnbvcx98ertyuiop",
    "roles": ["user", "premium"],
    "did": "Android 8.0.0",
    "exp": 1735689600
}

The following list shows the possible functionalities with an example"token_keys": ["jti","sub","did","aud"]:

  • jti to revoke a single user session and device
  • sub to revoke all sessions of the same subject.
  • did to revoke all sessions using the same device ID (e.g., a new release in the Play Store)
  • aud to revoke all our users of this audience or application.

Options are endless; these are some random examples, but it’s up to you to decide which JWT elements you want to watch and apply revocations. If, for instance, you only want to revoke access to a particular user or session, you only need to look at the jti (the unique identifier of a user) and sub.

Expiring tokens in a cluster

All KrakenD nodes are stateless and act individually; they don’t synchronize. Every node must receive the RPC notification about any tokens that need insertion in every local bloom filter.

The bloom filter gets updated while the service is running, but the level of synchronization between the nodes depends on your push strategy to the different cluster members. KrakenD uses conflict-free replicated data types (CRDT), so you can replicate the data across multiple computers in a network without coordination between the replicas, and where it is always mathematically possible to resolve inconsistencies that might result.

The resulting system is eventually consistent.

The bloom filter management is brought to you by the component, and for the administration part, the client offers the necessary tools to adapt the gateway to your scenario. The implementation very much depends on what you want to achieve.

Additional resources

If you want to learn bloomfilters by example or additional information on token revocation, have a look at the following resources:

Scarf

Unresolved issues?

The documentation is only a piece of the help you can get! Whether you are looking for Open Source or Enterprise support, see more support channels that can help you.

See all support channels