Configure HMAC Authentication
HMAC authentication requires clients to sign their requests using a shared secret. The signature covers the configured request target and signed headers. With a signed timestamp, clock_skew limits the age of an accepted request, but does not prevent replay of the same valid request within that window.
The hmac-auth plugin in API7 Gateway verifies the incoming signature against the configured consumer credential.
Use this guide for the common signing workflow. For the full plugin field reference and advanced options such as signed headers and request body validation, see hmac-auth.
Prerequisites
- An API7 Enterprise instance is running.
- A Gateway Group is created and a Gateway instance is running.
- A token from the Dashboard.
Configure HMAC Authentication
Setting up HMAC authentication involves three steps:
- Create a service with a valid upstream.
- Create a route that enables
hmac-auth. - Create a consumer and attach an HMAC credential.
Step 1: Create a Service with an Upstream
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/services/hmac-auth-httpbin-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "hmac-auth-httpbin-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'
services:
- name: hmac-auth-httpbin-service
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- name: hmac-auth-route
uris:
- /anything/hmac-auth
methods:
- GET
plugins:
hmac-auth:
clock_skew: 300
allowed_algorithms:
- hmac-sha256
labels:
docs-example: hmac-auth-httpbin-service
consumers:
- username: hmac-auth-consumer
credentials:
- name: hmac-auth-consumer-cred
type: hmac-auth
config:
key_id: client-1
secret_key: my-hmac-secret
labels:
docs-example: hmac-auth-httpbin-service
Preview the changes owned by this example and confirm that the diff contains no unintended updates or deletions:
adc diff -f adc.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=hmac-auth-httpbin-service
Synchronize the reviewed configuration:
adc sync -f adc.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=hmac-auth-httpbin-service
Step 2: Create a Route and Enable hmac-auth
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/routes/hmac-auth-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "hmac-auth-route",
"paths": ["/anything/hmac-auth"],
"methods": ["GET"],
"service_id": "hmac-auth-httpbin-service",
"plugins": {
"hmac-auth": {
"clock_skew": 300,
"allowed_algorithms": ["hmac-sha256"]
}
}
}'
The route is already included in the previous adc.yaml example.
Step 3: Create a Consumer and Credential
- Admin API
- ADC
# 1. Create the consumer
curl -k "https://localhost:7443/apisix/admin/consumers/hmac-auth-consumer?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "hmac-auth-consumer"
}'
# 2. Create the hmac-auth credential
curl -k "https://localhost:7443/apisix/admin/consumers/hmac-auth-consumer/credentials/hmac-auth-consumer-cred?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "hmac-auth-consumer-cred",
"plugins": {
"hmac-auth": {
"key_id": "client-1",
"secret_key": "my-hmac-secret"
}
}
}'
The consumer and credential are already included in the previous adc.yaml example.
Validate the Configuration
First, send a request without the HMAC headers. The gateway should reject it with 401 Unauthorized:
curl -i "http://127.0.0.1:9080/anything/hmac-auth"
Then generate and send a signed request with Python:
import base64
import hashlib
import hmac
import urllib.request
from email.utils import formatdate
key_id = "client-1"
secret_key = b"my-hmac-secret"
request_path = "/anything/hmac-auth"
date_header = formatdate(timeval=None, localtime=False, usegmt=True)
signing_string = f"{key_id}\nGET {request_path}\ndate: {date_header}\n"
signature = base64.b64encode(
hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest()
).decode()
request = urllib.request.Request(
"http://127.0.0.1:9080/anything/hmac-auth",
headers={
"Date": date_header,
"Authorization": (
f'Signature keyId="{key_id}",algorithm="hmac-sha256",'
f'headers="@request-target date",signature="{signature}"'
),
},
)
with urllib.request.urlopen(request, timeout=20) as response:
print(response.status)
print(response.read().decode())
Run the script:
python3 hmac-request.py
You should receive 200 OK, and the upstream response should include headers similar to the following:
{
"headers": {
"Authorization": "Signature keyId=\"client-1\",algorithm=\"hmac-sha256\",headers=\"@request-target date\",signature=\"<signature>\"",
"Date": "Tue, 21 Apr 2026 09:06:44 GMT",
"X-Consumer-Username": "hmac-auth-consumer",
"X-Credential-Identifier": "hmac-auth-consumer-cred"
}
}
If the authenticated request still returns 401, or the route returns 404, immediately after you apply the configuration, wait a few seconds for the latest configuration to reach the gateway and retry.
Next Steps
- Configure JWT Authentication - use JSON Web Tokens for stateless authentication.
- Configure Key Authentication - use simple API keys for quick security.
- Learn about Consumers and Credentials - understand how API7 Gateway manages identities.