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.
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"
N
* integer- The maximum
N
umber 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
P
robability of returning a false positive. E.g.,1e-7
for one false positive every 10 million different tokens. The valuesN
andP
determine the size of the resulting bloom filter to fulfill your expectations. E.g: 0.0000001Example: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) ordefault
. Theoptimal
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.
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 devicesub
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: