Implement Key Authentication
Key authentication is a lightweight and effective method for controlling access to APIs. By issuing unique API keys to consumers, APISIX can identify and authenticate requests without requiring complex token exchanges or user credentials. This method is ideal for use cases where simplicity is a priority, such as protecting internal APIs, enabling access for trusted partners, or logging usage per consumer. However, it should generally be avoided for highly sensitive or public-facing APIs where stronger authentication methods, like OAuth, are more suitable.
In this guide, you will implement a scenario where there are two consumers using key authentication to authenticate with APISIX, each with a different rate limiting quota. Once implemented, consumers should have access to the upstream service and forward consumer IDs to the upstream service, opening up options for additional business logics.
Prerequisite(s)
- Install Docker.
- Install cURL to send requests to the services for validation.
- Follow the Getting Started tutorial to start a new APISIX instance in Docker.
Create Consumers
A consumer is an application or a developer who consumes the API. You should always create consumers when using APISIX built-in authentication methods.
- Admin API
- Ingress Controller
Create a consumer johndoe
with an optional custom ID and a rate limiting quota of one request in a 30-second window:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "johndoe",
"labels": {
"custom_id": "john-doe-junior"
},
"plugins": {
"limit-count": {
"count": 1,
"time_window": 30,
"rejected_code": 429
}
}
}'
The custom ID will be forwarded to the upstream service, should you wish to implement additional business logics.
Create another consumer janedoe
with an optional custom ID and a rate limiting quota of two requests in a 30-second window:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "janedoe",
"labels": {
"custom_id": "jane-doe-senior"
},
"plugins": {
"limit-count": {
"count": 2,
"time_window": 30,
"rejected_code": 429
}
}
}'
Ingress Controller currently does not support configuring consumer labels.
- Gateway API
- APISIX CRD
Create a Kubernetes manifest file for a consumer johndoe
with a rate limiting quota of one request in a 30-second window:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
name: johndoe
spec:
gatewayRef:
name: apisix
plugins:
- name: limit-count
config:
count: 1
time_window: 30
rejected_code: 429
Create another Kubernetes manifest file for a consumer janedoe
with a rate limiting quota of two requests in a 30-second window:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
name: janedoe
spec:
gatewayRef:
name: apisix
plugins:
- name: limit-count
config:
count: 2
time_window: 30
rejected_code: 429
Apply the configuration to your cluster:
kubectl apply -f consumer-rate-limit-john.yaml -f consumer-rate-limit-jane.yaml
The ApisixConsumer CRD currently does not support configuring plugins on consumers for the scenario in this guide. To configure a consumer with key-auth
without rate limiting, see Configure Consumer and Credentials.
Create Consumer Credentials
Credentials are used to configure authentication credentials associated with consumers.
- Admin API
- Ingress Controller
Create key-auth
credential for johndoe
:
curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
Create key-auth
credential for janedoe
:
curl "http://127.0.0.1:9180/apisix/admin/consumers/janedoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jane-key-auth",
"plugins": {
"key-auth": {
"key": "jane-key"
}
}
}'
- Gateway API
- APISIX CRD
Update the Kubernetes manifest files with credentials:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
name: johndoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cred-john-key-auth
config:
key: john-key
plugins:
- name: limit-count
config:
count: 1
time_window: 30
rejected_code: 429
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
name: janedoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cred-jane-key-auth
config:
key: jane-key
plugins:
- name: limit-count
config:
count: 2
time_window: 30
rejected_code: 429
Apply the configuration to your cluster:
kubectl apply -f consumer-rate-limit-john.yaml -f consumer-rate-limit-jane.yaml
The ApisixConsumer CRD currently does not support configuring plugins on consumers for the scenario in this guide. To configure a consumer with key-auth
without rate limiting, see Configure Consumer and Credentials.
Create a Route
Create a route and enable key-auth
:
- Admin API
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "key-auth-route",
"uri": "/anything",
"plugins": {
"key-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
name: auth-plugin-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: key-auth-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: auth-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
name: httpbin-external-domain
spec:
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: key-auth-route
spec:
ingressClassName: apisix
http:
- name: key-auth-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
authentication:
enable: true
type: keyAuth
Apply the configuration to your cluster:
kubectl apply -f httpbin-route.yaml
Verify
Send a request to the route with john
's key:
curl "http://127.0.0.1:9080/anything" -H 'apikey: john-key'
You should see an HTTP/1.1 200 OK
response similar to the following:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
...
"X-Consumer-Username": "johndoe",
"X-Credential-Identifier": "cred-john-key-auth",
"X-Consumer-Custom-Id": "john-doe-junior",
"X-Forwarded-Host": "127.0.0.1"
},
...
}
Generate three requests to the route with john
's key:
resp=$(seq 3 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: john-key' -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that out of the 3 requests, 1 request was successful while the others were rejected:
200: 1, 429: 2
Generate three requests to the route with jane
's key:
resp=$(seq 3 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: jane-key' -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that out of the 3 requests, 2 requests were successful while the other was rejected:
200: 2, 429: 1
Finally, send a request with an invalid key:
curl -i "http://127.0.0.1:9080/anything" -H 'apikey: wrong-key'
You should see an HTTP/1.1 401 Unauthorized
response with the following message:
{"message":"Invalid API key in request"}
Next Steps
You have now learned how to implement key authentication. APISIX supports other built-in authentication methods, such as basic authentication, JWT authentication, and HMAC authentication.