Document updated on Aug 17, 2023
Multiple Identity Providers in KrakenD API Gateway
The JWK aggregator plugin allows KrakenD to validate tokens issued by numerous Identity Providers or multiple realms of the same Identity Server.
The default behavior of KrakenD allows you to validate JWT tokens using a single Identity Provider or tenant per endpoint. However, there are times when tokens arriving at an endpoint originate in different providers or different tenants or realms. This is especially true in multi-tenant scenarios, where an ongoing migration or other systems converge into the gateway. The KrakenD jwk-aggregator
allows you to alleviate this issue.
The plugin generates a new JWK URL that is hosted locally, that recognizes all the tokens genereated in the different providers (the origins
). For instance under the URL http://localhost:9876
(you can choose the port).
All origins
are fetched in parallel. If the cache
is set to true
, the responses of the Identity Server are and cached in-memory individually for the time specified in their Cache-Control
header.
In addition to the aggregator cache, you can also enable shared caching for JWT validation.
Configuration
The configuration is straightforward. You only need to include the following lines, where origins
is the list of all possible public keys of your identity servers:
{
"version": 3,
"$schema": "https://www.krakend.io/schema/krakend.json",
"plugin": {
"pattern":".so",
"folder": "/opt/krakend/plugins/"
},
"extra_config": {
"plugin/http-server": {
"name": ["jwk-aggregator"],
"jwk-aggregator":{
"port": 9876,
"cache": true,
"origins":[
"https://provider1.tld/jwk.json",
"http://provider2/public_keys",
"https://keycloak/auth/realms/realm-first/protocol/openid-connect/certs",
"https://keycloak/auth/realms/realm-second/protocol/openid-connect/certs",
"https://provider1.tld/jwk.json",
"http://provider2/public_keys",
"https://keycloak/auth/realms/realm-first/protocol/openid-connect/certs",
"https://keycloak/auth/realms/realm-second/protocol/openid-connect/certs"
]
}
},
"auth/validator": {
"@comment": "Enable a JWK shared cache amongst all endpoints of 15 minutes",
"shared_cache_duration": 900
}
},
"endpoints":[
{
"endpoint": "/example",
"extra_config": {
"auth/validator": {
"alg": "RS256",
"jwk_url": "http://localhost:9876",
"disable_jwk_security": true,
"cache": true
}
},
"backend": [{
"url_pattern": "/example"
}]
}
]
}
Fields of JWK aggregator
cache
boolean- When
true
, it stores the response of the Identity provider for the time specified in itsCache-Control
header. origins
* array- The list of all JWK URLs recognized as valid Identity Providers by the gateway.
port
* integer- The port of the local server doing the aggregation. The port is only accessible within the gateway machine using localhost, and it’s never exposed to the external network. Choose any port that is free in the system.Example:
9876
Endpoint’s configuration
In addition to the configuration above, the endpoints must point to the new service instead of a particular JWK URL. To do that, you have to reference it in the jwk_url
as follows and set the disable_jwk_security
flag to true
(as the connection is internal and does not use TLS validation). You also need to enable cache
to true to avoid hammering the aggregator (and the aggregator the external identity providers) on each request:
{
"endpoint": "/protected/resource",
"extra_config": {
"auth/validator": {
"alg": "RS256",
"jwk_url": "http://localhost:9876",
"disable_jwk_security": true,
"cache": true
}
},
"backend": [
{
"url_pattern": "/"
}
]
}
And that’s all you need to support multiple identity providers’ origin! You can change the exposed port. There is no specific reason to keep the 9876
.
If you want even better caching, you can also enable the global shared JWK cache which is reused between endpoints.