All Products
Search
Document Center

API Gateway:Hmac-auth

Last Updated:Sep 09, 2026

The hmac-auth plug-in generates unforgeable signatures for HTTP requests based on the HMAC algorithm and uses the signatures for identity authentication.

Plug-in type

Authentication and authorization.

Fields

Authentication configuration

Field

Data type

Required

Default value

Description

consumers

array of object

Yes

-

The callers of the service, used to authenticate requests.

date_offset

number

No

-

The maximum allowed client time offset, in seconds. The system parses the client UTC time from the Date request header to prevent replay attacks. If not configured, the system does not verify the client UTC time.

global_auth

array of string

No (Required only for instance-level configurations)

-

Instance-level only. When set to true, authentication takes effect globally. When set to false, authentication applies only to configured domain names and routes. When not configured, authentication takes effect globally only if no domain names or routes are configured.

Fields in consumers:

Field

Data type

Required

Default value

Description

key

string

Yes

-

The consumer access key.

secret

string

Yes

-

The secret used to generate the signature.

name

string

Yes

-

The name of the consumer.

(Optional) Authorization configuration

Field

Data type

Required

Default value

Description

allow

array of string

No (Required for non-instance-level configurations)

-

Configurable only at the route or domain name level. Specifies which consumers are allowed to access matching requests for fine-grained permission control.

Important
  • Authorization and authentication configurations cannot coexist in the same rule.

  • For authenticated requests, the X-Mse-Consumer header is added to identify the caller.

Examples

Globally configure authentication and configure authorization for routes

The following example enables hmac-auth authentication for specific routes or domains. The key field must be unique.

Apply the following plug-in configurations at the instance level:

global_auth: false
consumers: 
- key: appKey-example-1
  secret: appSecret-example-1
  name: consumer-1
- key: appKey-example-2
  secret: appSecret-example-2
  name: consumer-2

Apply the following plug-in configuration to the route-a and route-b routes:

allow:
- consumer1

Apply the following plug-in configuration to the *.example.com and test.com domain names:

allow:
- consumer2
Note
  • In this example, the route-a and route-b routes are those specified when the gateway routes are created. If a client request matches one of the routes, the caller whose name is consumer1 is allowed to access the gateway. Other callers are not allowed to access the gateway.

  • In this example, the *.example.com and test.com domain names are used to match domain names in requests. If a client request matches one of the domain names, the caller whose name is consumer2 is allowed to access the gateway. Other callers are not allowed to access the gateway.

Enable the traffic-tag plug-in for gateways

global_auth: true
consumers: 
- key: appKey-example-1
  secret: appSecret-example-1
  name: consumer-1
- key: appKey-example-2
  secret: appSecret-example-2
  name: consumer-2

Signature mechanism

Configuration preparations

Configure the following credentials for generating and validating signatures:

  • key: used in the request header x-ca-key.

  • secret: used to generate the request signature.

Generate a signature on the client

Process

The client generates a signature by performing these steps:

  1. Extract key data from the original request to generate a signature string.

  2. Encrypt the signature string with the configured secret to produce the signature.

  3. Add all signature-related headers to the original HTTP request.

Extract a signature string

The client extracts key data from the HTTP request and combines it into a signature string in the following format:

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

These fields are separated by \n. If the Headers field is empty, \n is not required. For other empty fields, \n must be retained. The signature is case-sensitive.

Extraction rules for each field:

  • HTTPMethod: the HTTP method, such as POST. Must be uppercase.

  • Accept: the value of the Accept request header. Can be empty. We recommend that you explicitly set the Accept header, because some HTTP clients default to */*, which causes signature verification to fail.

  • Content-MD5: the value of the Content-MD5 header. Can be empty. Calculated only when the request contains a non-form body. Java example:

    String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
  • Content-Type: the value of the Content-Type header. Can be empty.

  • Date: the value of the Date header, used for time offset verification. Can be empty if date_offset is not configured.

  • Headers: the headers included in the signature. Concatenation rules:

    • Sort header keys alphabetically and concatenate them as follows:

      HeaderKey1 + ":" + HeaderValue1 + "\n"\+
      HeaderKey2 + ":" + HeaderValue2 + "\n"\+
      ...
      HeaderKeyN + ":" + HeaderValueN + "\n"
    • If a header value is empty, use HeaderKey + ":" + "\n" for the signature. The key and colon (:) must be retained.

    • The header keys used for the signature are separated by commas (,) and placed in the X-Ca-Signature-Headers header.

    • The following headers cannot be used in signature calculation: X-Ca-Signature, X-Ca-Signature-Headers, Accept, Content-MD5, Content-Type, and Date.

  • PathAndParameters: contains the path, query, and form parameters.

    Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
Note
  • Query and form parameter keys are sorted alphabetically and then concatenated as described above.

  • If query and form parameters are empty, use the path alone without adding signature information.

  • For array parameters with the same key but different values, only the first value is used for signature calculation.

Example of extracting a signature string

Initial HTTP request:

POST /http2test/test?param1=test HTTP/1.1
host:api.alibabacloud.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
content-length:33
username=xiaoming&password=123456789

Generated signature string:

POST
application/json; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Wed, 09 May 2018 13:30:29 GMT+00:00
x-ca-key:203753385
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-signature-method:HmacSHA256
x-ca-timestamp:1525872629832
/http2test/test?param1=test&password=123456789&username=xiaoming

Calculate a signature

After generating the signature string, the client encrypts and encodes it to produce the final signature.

In this code, stringToSign is the extracted signature string, secret is from the plug-in configuration, and sign is the final signature.

Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.encodeBase64String(result);

The stringToSign is decoded into a UTF-8 byte array, encrypted with the HMAC algorithm, and then Base64-encoded to produce the signature.

Add a signature

Include the following headers in requests sent to Cloud-native API Gateway for signature verification:

  • x-ca-key: the AppKey. Required.

  • x-ca-signature-method: the signature algorithm. Optional. Valid values: HmacSHA256 and HmacSHA1. Default value: HmacSHA256.

  • x-ca-signature-headers: all signature header keys, separated by commas (,). Optional.

  • x-ca-signature: the signature. Required.

Example HTTP request with a signature:

POST /http2test/test?param1=test HTTP/1.1
host:api.alibabacloud.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-key:203753385
x-ca-signature-method:HmacSHA256
x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
content-length:33
username=xiaoming&password=123456789

Verify the signature at the server side

Process

The server verifies the client signature by performing these steps:

  1. Extract key data from the request to obtain a signature string.

  2. Read the key from the request and look up the corresponding secret.

  3. Encrypt the signature string with the secret to produce a signature.

  4. Compare the server-side signature with the client-side signature from the request.

Troubleshoot signature errors

When signature verification fails, the server returns the server-side StringToSign in the X-Ca-Error-Message response header. Compare it with the client-side StringToSign to identify the discrepancy.

If the two values match, verify the AppSecret used for signature calculation.

HTTP headers do not support line breaks, so line breaks in StringToSign are replaced with #.

X-Ca-Error-Message:  Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`

Error codes

HTTP status code

Error message

Reason

400

Invalid Signature.

The signature in x-ca-signature does not match the server-calculated signature.

400

Invalid Content-MD5.

The Content-MD5 request header is invalid.

400

Invalid Date.

The time offset from the Date request header exceeds the configured date_offset.

401

Invalid Key.

The x-ca-key request header is missing or invalid.

401

Empty Signature.

The x-ca-signature request header is empty.

403

Unauthorized Consumer.

The request caller does not have access permissions.

413

Request Body Too Large.

The request body exceeds 32 MB.

413

Payload Too Large.

The request body exceeds the DownstreamConnectionBufferLimits configured for the gateway. You can increase DownstreamConnectionBufferLimits on the parameter configuration page.

Note

Increasing DownstreamConnectionBufferLimits significantly increases gateway memory usage. Exercise caution.