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 |
|
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. |
-
Authorization and authentication configurations cannot coexist in the same rule.
-
For authenticated requests, the
X-Mse-Consumerheader 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
-
In this example, the
route-aandroute-broutes are those specified when the gateway routes are created. If a client request matches one of the routes, the caller whosenameisconsumer1is allowed to access the gateway. Other callers are not allowed to access the gateway. -
In this example, the
*.example.comandtest.comdomain names are used to match domain names in requests. If a client request matches one of the domain names, the caller whosenameisconsumer2is 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:
-
Extract key data from the original request to generate a signature string.
-
Encrypt the signature string with the configured
secretto produce the signature. -
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_offsetis 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-Headersheader. -
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
-
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:
-
Extract key data from the request to obtain a signature string.
-
Read the
keyfrom the request and look up the correspondingsecret. -
Encrypt the signature string with the
secretto produce a signature. -
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. |
Increasing DownstreamConnectionBufferLimits significantly increases gateway memory usage. Exercise caution.