Document updated on Oct 25, 2022
The API key authentication enables a Role-Based Access Control (RBAC) and a rate-limiting mechanism based on an API key passed by the client. For the desired endpoints, KrakenD rejects requests from users that do not provide a valid key, are trying to access a resource with insufficient permissions for the user’s role, or are exceeding the defined quota.
The authentication is granular and works per-endpoint, meaning that you can combine public endpoints (no API Key needed) and private endpoints in the same configuration.
The API Key component requires you to declare at least two different blocks of configuration:
extra_config
middleware section.The first block of configuration declares how KrakenD retrieves keys, which ones are available, and the roles recognized by the system. The API keys configuration requires at least the keys
attribute with a list of objects declaring each client’s key
and roles
. The configuration is as follows:
{
"version": 3,
"extra_config": {
"auth/api-keys": {
"strategy": "header",
"identifier": "Authorization",
"keys": [
{
"key": "4d2c61e1-34c4-e96c-9456-15bd983c5019",
"roles": ["role1", "role2"],
"@description": "ACME Inc."
},
{
"key": "58427514-be32-0b52-b7c6-d01fada30497",
"roles": ["role1","role3"],
"@description": "Administrators Inc."
}
]
}
}
}
The configuration attributes are:
| The header name or the query string name that contains the API key. Defaults to key when using the query_string strategy and to Authorization when using header .Example: "Authorization" | ||||
| A list of objects defining each API Key.
Each item is an object with the following properties:
| ||||
| One of header or query_string. Specifies where to expect the user API key, whether inside a header or as part of the query string. Defaults to header. Possible values are: "header" , "query_string" |
It is also shown in the example a @description
attribute to help you identify who this key belongs to. This attribute is metadata and unneeded by KrakenD, but it easies the administration of keys. Use attributes starting with @
to place comments in the file.
Now that all users and roles are declared, it’s time to reference them in the endpoints. You must include the namespace auth/api-keys
in its extra_config
for all the endpoints needing API Key validation. Any endpoints not having the namespace are not API Key protected. For example, the endpoints could look like this:
{
"endpoint": "/admin",
"backend": [
{
"url_pattern": "/__debug/admin",
"host": [
"http://localhost:8080"
]
}
],
"extra_config": {
"auth/api-keys": {
"roles": [
"admin"
],
"client_max_rate": 5
}
}
}
The endpoint configuration accepts the following parameters:
| If you want to limit the endpoint usage to this specific user at a number of requests per second. Exceeding the number of requests per second will give the client a 429 Too Many Requests HTTP status code. |
| The list of roles allowed to access the endpoint. Values must match (case sensitive) definitions in the keys section at the service level of auth/api-keys . API Keys not having the right role, or unauthenticated requests, will receive a 401 Unauthorized . |
Here is a full example of two different API Keys that can access three different endpoints:
{
"version": 3,
"extra_config": {
"auth/api-keys": {
"keys": [
{
"@description": "ACME Inc.",
"key": "4d2c61e1-34c4-e96c-9456-15bd983c5019",
"roles": ["user", "whitelabel"]
},
{
"@description": "Administrators Inc.",
"key": "58427514-be32-0b52-b7c6-d01fada30497",
"roles": ["admin", "user"]
}
]
}
},
"endpoints": [
{
"endpoint": "/public",
"backend": [
{
"url_pattern": "/__debug/public",
"host": [
"http://localhost:8080"
]
}
]
},
{
"endpoint": "/admin",
"backend": [
{
"url_pattern": "/__debug/admin",
"host": [
"http://localhost:8080"
]
}
],
"extra_config": {
"auth/api-keys": {
"roles": [
"admin"
],
"client_max_rate": 5
}
}
},
{
"endpoint": "/user",
"backend": [
{
"url_pattern": "/__debug/user",
"host": [
"http://localhost:8080"
]
}
],
"extra_config": {
"auth/api-keys": {
"roles": [
"user"
]
}
}
}
]
}
When you don’t set any strategy
in the configuration clients, clients need to make requests to KrakenD adding the Authorization: Bearer
or Authorization: Basic
header. The value inside the header must strictly match the API key defined in the configuration.
Bearer
The format of the header is as follows:
Authorization: Bearer YOUR-KEY
For instance, having declared in the configuration a key 4d2c61e1-34c4-e96c-9456-15bd983c5019
that should be capable of seeing /foo
, you should make a call like this:
$curl -H'Authorization: Bearer 4d2c61e1-34c4-e96c-9456-15bd983c5019' http://localhost:8080/foo
{"message":"pong"}
Basic
authentication instead of Bearer
Another way of authenticating is using Basic
authentication. It does not present any benefit compared to Bearer
other than backward compatibility with legacy implementations.
The difference is that clients must pass the key in base64
:
Authorization: Basic base64(YOUR-KEY:)
Notice that the encoding of the key contains an ending :
. The final colon prevents your client from being asked for a password.
Basic
authentication exampleRepeating the previous Bearer
example, let’s connect using Basic
authentication now. The first step is to base64-encode:
$echo -n "4d2c61e1-34c4-e96c-9456-15bd983c5019:" | base64
NGQyYzYxZTEtMzRjNC1lOTZjLTk0NTYtMTViZDk4M2M1MDE5Ogo=
And then pass the header_
$curl -H"Authorization: Basic NGQyYzYxZTEtMzRjNC1lOTZjLTk0NTYtMTViZDk4M2M1MDE5Ogo=" http://localhost:8080/foo
{"message":"pong"}
You can also not do the base64 encoding if you use a client with regular basic auth implemented, which will encode automatically (again, notice the :
at the end of the key):
$curl -i --user 4d2c61e1-34c4-e96c-9456-15bd983c5019: http://localhost:8080/foo
{"message":"pong"}
In case you forget the colon :
you’ll be prompted for the password (when there isn’t):
$curl -i --user 4d2c61e1-34c4-e96c-9456-15bd983c5019 http://localhost:8080/user
Enter host password for user '4d2c61e1-34c4-e96c-9456-15bd983c5019':
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Krakend: Version
X-Krakend-Completed: true
Date: Tue, 10 Nov 2020 17:37:09 GMT
Content-Length: 18
{"message":"pong"}
Authorization
headerUsing the identifier
option, you can replace Authorization
with any other header. But in all cases, whatever header you choose, the Bearer
or the Basic
must be part of the header as described above.
For instance:
{
"auth/api-keys": {
"strategy": "header",
"identifier": "X-Key"
}
}
Clients will need to make calls like
$curl -H'X-Key: Bearer 4d2c61e1-34c4-e96c-9456-15bd983c5019' http://localhost:8080/foo
{"message":"pong"}
If you set the strategy
to query_string
, clients can directly pass the key on the URL using ’ ?key=xxxx`. For instance:
$curl http://localhost:8080/user?key=4d2c61e1-34c4-e96c-9456-15bd983c5019
{"message":"pong"}
You can set a different identifier
section instead of key
to something else. For instance, let’s use ?mycustomapikey=xxxx
:
{
"auth/api-keys": {
"strategy": "query_string",
"identifier": "mycustomapikey",
"keys": [{}]
}
}
A configuration like the above will require users to make calls like this:
$curl http://localhost:8080/user?mycustomapikey=4d2c61e1-34c4-e96c-9456-15bd983c5019
{"message":"pong"}
The following configuration snippet is fully functional. Run KrakenD with the debug flag (krakend run -d
) to test it locally, as it uses itself as a backend. Explanation below:
{
"version": 3,
"extra_config": {
"auth/api-keys": {
"keys": [
{
"@description": "ACME Inc.",
"key": "4d2c61e1-34c4-e96c-9456-15bd983c5019",
"roles": [
"user",
"whitelabel"
]
},
{
"@description": "Administrators Inc.",
"key": "58427514-be32-0b52-b7c6-d01fada30497",
"roles": [
"admin",
"user"
]
}
]
}
},
"endpoints": [
{
"endpoint": "/public",
"backend": [
{
"url_pattern": "/__debug/public",
"host": [
"http://localhost:8080"
]
}
]
},
{
"endpoint": "/admin",
"backend": [
{
"url_pattern": "/__debug/admin",
"host": [
"http://localhost:8080"
]
}
],
"extra_config": {
"auth/api-keys": {
"roles": [
"admin"
]
}
}
},
{
"endpoint": "/user",
"backend": [
{
"url_pattern": "/__debug/user",
"host": [
"http://localhost:8080"
]
}
],
"extra_config": {
"auth/api-keys": {
"roles": [
"user"
]
}
}
}
]
}
In this example, we have enabled two different API users. One with key 4d2c61e1-34c4-e96c-9456-15bd983c5019
(let’s say a customer of ACME Inc.) and another one with the key 58427514-be32-0b52-b7c6-d01fada30497
(an administrator of my company).
Both users share the role users
, and they can access all the protected endpoints as this role is included. Nevertheless, the /admin
endpoint is reachable by the administrator only, as the role “admin” is required.
The endpoint /public
is always accessible, with or without the Authorization
header, as it does not include the API key middleware configuration.
And now some sample interactions:
$curl -H'Authorization: Bearer 4d2c61e1-34c4-e96c-9456-15bd983c5019' http://localhost:8080/user
{"message":"pong"}
$curl -i --user 4d2c61e1-34c4-e96c-9456-15bd983c5019: http://localhost:8080/user
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Krakend: Version
X-Krakend-Completed: true
Date: Tue, 10 Nov 2020 17:07:46 GMT
Content-Length: 18
{"message":"pong"}
$curl -iG -H'Authorization: Bearer 4d2c61e1-34c4-e96c-9456-15bd983c5019' http://localhost:8080/admin
HTTP/1.1 401 Unauthorized
Date: Tue, 10 Nov 2020 17:01:03 GMT
Content-Length: 0
$curl -iG -H'Authorization: Bearer INVALID-API-KEY' http://localhost:8080/user
HTTP/1.1 401 Unauthorized
Date: Tue, 10 Nov 2020 16:59:35 GMT
Content-Length: 0
$curl http://localhost:8080/public
{"message":"pong"}
As the KrakenD configuration is static and does not change until you restart the process or you do a deployment, you might find it inconvenient to onboard new customers with new API keys, and you don’t want to be restarting the server every time. The following advice can be handy.
Instead of waiting for user registration in your system to insert a new API key, create a pool of available API keys. KrakenD has a constant performance, so it doesn’t change if you have 100 keys or 1 million.
An easy way to generate API keys could be as follows:
$uuidgen
If you want to generate several keys and write part of the configuration file, you could use something like:
$for i in $(seq 50)
do
key=$(uuidgen)
echo "{ \"key\": \"$key\", \"roles\": [\"silver-plan\"], \"@status\": \"free\" },"
done
Then you would use the output above to create a partial file api-keys.json
that would be used on KrakenD with Flexible Configuration.
Finally, your backend should have this list somewhere, and when a new user registers, you assign one of the free keys to the new user. You can deploy from time to time when you are running out of API keys in the pool or if you want to write the assignation in the configuration.
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.