# 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`](https://docs.api7.ai/hub/hmac-auth.md) 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`](https://docs.api7.ai/hub/hmac-auth.md).

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

* An API7 Enterprise instance is running.
* A Gateway Group is created and a Gateway instance is running.
* A [token from the Dashboard](https://docs.api7.ai/api7-gateway/reference/obtain-dashboard-token.md).

## Configure HMAC Authentication[​](#configure-hmac-authentication "Direct link to Configure HMAC Authentication")

Setting up HMAC authentication involves three steps:

1. Create a service with a valid upstream.
2. Create a route that enables `hmac-auth`.
3. Create a consumer and attach an HMAC credential.

### Step 1: Create a Service with an Upstream[​](#step-1-create-a-service-with-an-upstream "Direct link to 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

        }

      ]

    }

  }'
```

adc.yaml

```
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`[​](#step-2-create-a-route-and-enable-hmac-auth "Direct link to 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[​](#step-3-create-a-consumer-and-credential "Direct link to 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[​](#validate-the-configuration "Direct link to 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:

hmac-request.py

```
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[​](#next-steps "Direct link to Next Steps")

* [Configure JWT Authentication](https://docs.api7.ai/api7-gateway/how-to-guides/api-security/jwt-auth.md) - use JSON Web Tokens for stateless authentication.
* [Configure Key Authentication](https://docs.api7.ai/api7-gateway/how-to-guides/api-security/key-auth.md) - use simple API keys for quick security.
* [Learn about Consumers and Credentials](https://docs.api7.ai/api7-gateway/key-concepts/consumers-and-credentials.md) - understand how API7 Gateway manages identities.
