The hmac-auth plug-in is used to generate unforgeable signatures for HTTP requests based on the Hash-based message authentication code (HMAC) algorithm. The signatures are used for identity authentication. This topic describes how to configure the hmac-auth plug-in.
Plug-in type
Authentication plug-in.
Fields
Authentication configuration
Name | Data type | Required | Default value | Description |
consumers | array of object | Yes | - | The callers of the service. This field is used to authenticate requests. |
date_offset | number | No | - | The maximum time offset of the client in seconds. The system uses this field to parse the Universal Time Coordinated (UTC) time of the client from the |
global_auth | array of string | No (Required only for instance-level configurations) | - | If global_auth is set to true, the authentication mechanism globally takes effect. If global_auth is set to false, the authentication mechanism takes effect only for the domain names and routes that you configure. If global_auth is not configured, the authentication mechanism globally takes effect only when no domain names and routes are configured. |
The following table describes the configuration items in the consumers field.
Name | Data type | Required | Default value | Description |
key | string | Yes | - | The access key of the consumer. |
secret | string | Yes | - | The secret that is used to generate the signature. |
name | string | Yes | - | The name of the consumer. |
Authorization configuration (optional)
Name | Data type | Required | Default value | Description |
allow | array of string | No (Required for non-instance-level configurations) | - | You can only configure this field at a fine granularity such as route or domain name. For requests that meet the matching conditions, you can configure consumers that are allowed for access. This implements fine-grained permission control. |
The authorization configuration and authentication configuration cannot coexist in a rule.
For authenticated requests, the
X-Mse-Consumerfield is added to the request header to identify the names of the callers.
Configuration examples
Globally configure authentication and configure authorization for routes
This section provides an example on how to enable authentication based on the hmac-auth plug-in for specific routes or domains of the gateway. 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-2Apply the following plug-in configuration to the route-a and route-b routes:
allow:
- consumer1Apply the following plug-in configuration to the *.example.com and test.com domain names:
allow:
- consumer2In 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 authentication 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-2Signature mechanism
Configuration preparations
You must configure the following credential settings that are required 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
Overview
To generate a signature, the client performs the following steps:
Extracts the key data from the original request and generates a signature string.
Uses the encryption algorithm and the configured
secretto encrypt the signature string and generates a signature.Adds all headers that are related to the signature to the original HTTP request to obtain the final HTTP request.
Extract a signature string
To generate a signature, the client needs to extract key data from the HTTP request and combine the key data into a signature string. The signature string is in the following format:
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParametersThe preceding seven fields constitute a signature string and are separated by \n. If you leave the Headers field empty, \n is not required. If you leave other fields empty, \n must be retained. The signature is case-sensitive.
Rules for extracting each field:
HTTPMethod: the HTTP method used to send a request, such as POST. The value of this field is in uppercase.
Accept: the value of the Accept header in the request. You can leave the Accept header empty. We recommend that you explicitly specify the Accept header in the request. If the Accept header is empty, some HTTP clients use the default value
*/*for Accept. As a result, the signature verification fails.Content-MD5: the value of the Content-MD5 header, which can be left empty. The value is calculated only when a request contains a body of a non-Form type. The following example shows how to calculate the value of the Content-MD5 header in the Java format:
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));Content-Type: the value of the Content-Type header, which can be left empty.
Date: the value of the Date header, which is used for time offset verification. You can leave this field empty if
date_offsetis not specified.Headers: You can specify the headers to calculate a signature. When you concatenate signature strings, the following rules apply:
Header keys are first sorted in alphabetical order and then concatenated based on the following rules:
HeaderKey1 + ":" + HeaderValue1 + "\n"\+ HeaderKey2 + ":" + HeaderValue2 + "\n"\+ ... HeaderKeyN + ":" + HeaderValueN + "\n"If the value of a header is empty, use HeaderKey + ":" + "\n" for the signature. You must retain the header key and colon (:).
The header keys that are used for the signature are separated by commas (,) and placed in the header whose key is
X-Ca-Signature-Headers.You cannot use the following headers to calculate a signature: X-Ca-Signature, X-Ca-Signature-Headers, Accept, Content-MD5, Content-Type, and Date.
The PathAndParameters field contains all the path, query, and form parameters.
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
Keys of query and form parameters are first sorted in alphabetical order and then concatenated by using the preceding method.
If the query and form parameters are left empty, you can use path parameters without the need to add signature information.
If some query and form parameters are array parameters with the same key but different values, 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.aliyun.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=123456789Generated 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=xiaomingCalculate a signature
After the client extracts the key data from the HTTP request and generates a signature string, the client needs to encrypt and encode the signature string to form the final signature.
In the encryption process, stringToSign specifies the extracted signature string, secret is specified in the plug-in configuration, and sign specifies 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);In summary, stringToSign is decoded into a byte array by using UTF-8. The byte array is encrypted by using an encryption algorithm and then encoded by using the Base64 algorithm to generate a signature.
Add a signature
The client must include the following headers in the requests sent to API Gateway for signature verification:
x-ca-key: the AppKey, which is required.
x-ca-signature-method: the signature algorithm, which is optional. Valid values: HmacSHA256 and HmacSHA1. Default value: HmacSHA256.
x-ca-signature-headers: the collection of keys for all signature headers, which is optional. The keys are separated by commas (,).
x-ca-signature: the signature, which is required.
The following example shows an HTTP request with a signature:
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.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=123456789Verify the signature at the server side
Procedure
To verify the signature received from the client, the server performs the following steps:
Extracts key data from the request to obtain a signature string.
Reads the
keyfrom the request and uses thekeyto obtain thesecret.Uses an encryption algorithm and the
secretto encrypt the signature string to obtain a signature.Reads the client-side signature from the request and compares the server-side signature with the client-side signature.
Troubleshoot signature errors
If signature verification fails, the system adds the server-side signature string (StringToSign) to the header of the HTTP response that is returned to the client. The key is X-Ca-Error-Message. You can identify errors when you compare the client-side signature string (StringToSign) with the server-side signature string.
If the two values are the same, check the AppSecret that is used for signature calculation.
HTTP headers do not support line breaks. Line breaks in the signature string (StringToSign) are replaced with number signs (#).
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`HTTP status codes
HTTP status code | Error message | Reason |
400 | Invalid Signature. | The x-ca-signature request header contains a signature that does not match the server-calculated signature. |
400 | Invalid Content-MD5. | The content-md5 request header is invalid. |
400 | Invalid Date. | The time offset calculated based on the date request header exceeds the configured date_offset. |
401 | Invalid Key. | The x-ca-key request header is not provided or is invalid. |
401 | Empty Signature. | The x-ca-signature request header does not contain a signature. |
403 | Unauthorized Consumer. | The caller of the request does not have access permissions. |
413 | Request Body Too Large. | The size of the request body exceeds 32 MB. |
413 | Payload Too Large. | The request body exceeds the value of DownstreamConnectionBufferLimits that is configured for the gateway. You can increase the value of DownstreamConnectionBufferLimits on the parameter configuration page. |
If you increase the value of DownstreamConnectionBufferLimits, the gateway memory usage significantly increases. Exercise caution when you perform this operation.