To call a published API that uses the digest authentication method (AppKey and AppSecret), clients must use a signature key pair to calculate the signature for the requested content, and then send the signature to the server side for verification. API Gateway SDKs come with the signature mechanism. After you configure the signature key pair in the SDKs, you can initiate a request that contains the correct signature. This topic describes how to calculate signatures on clients.
1. Overview
API Gateway provides the signature generation and signature verification features. The features are used in the following scenarios:
Check the validity of requests that are received from clients to ensure that the requests contain the correct signature that is generated based on the authorized AppKey.
Prevent requests from being tampered with during transmission.
The API provider can create an application on the Apps page of the API Gateway console. Each application has a signature key pair that consists of an AppKey and an AppSecret. After the API provider authorizes the application to call the API, API callers can use the application and the signature key pair to call the API. Take note that the application can be issued by the API provider or owned by the API caller.
When a client calls the API, the client must use the authorized signature key pair to encrypt and sign the request, add the AppKey and the signature string to the header of the request, and then send the request to API Gateway. After API Gateway receives the request, API Gateway reads the AppKey from the request header and obtains the AppSecret that corresponds to the AppKey. Then, API Gateway uses the AppSecret to calculate the signature of the key data in the request, and compares the calculated signature with the signature from the client to verify the signature. Only requests that pass signature verification are sent to backend services. If API Gateway determines that a request is invalid, API Gateway returns an error.
API Gateway verifies signatures in requests only for APIs whose Security Authentication value is Alibaba Cloud App.
2. API calls by using SDKs
For more information about how to calculate signatures, see the SDKs that are provided by API Gateway. You can download SDKs for Java, Android, and Objective-C that come with source code on the following pages in the API Gateway console:
Open API > SDKs
Call API > Authorized API SDK
For more information, see Use SDKs to call APIs.
3. Principles of digest authentication
3.1. Signature generation and verification
3.1.1. Prerequisites
The signature key pair that is assigned to the related API is obtained by the API caller before the API caller calls the API.
APP Key
APP Secret
The Security Authentication value of the called API is Alibaba Cloud App.
3.1.2. Signature generation on clients
To generate a signature, clients must perform the following steps:
Extract key data from the request to obtain a signature string.
Use an encryption algorithm and AppSecret to encrypt the signature string to obtain a signature.
Add all headers that are related to the signature to the original HTTP request to obtain the final HTTP request.
3.1.3. Signature verification on servers
To verify the signature from clients, servers must perform the following steps:
Extract key data from the received request to obtain a signature string.
Read the AppKey from the request and use the AppKey to obtain the AppSecret.
Use an encryption algorithm and the AppSecret to encrypt the signature string to obtain a signature.
Read the client-side signature from the request and compare the server-side signature with the client-side signature.
3.2. Signature generation and transfer
3.2.1. Extraction of a signature string
Clients must extract key data from an HTTP request and combine the data into a signature string. The signature string is in the following format:
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters
The preceding 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. Data extraction for each field follows the following rules:
HTTPMethod: the HTTP method that is 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 specify the Accept header in the request. If the Accept header is left empty, specific HTTP clients use the default value */* for Accept. In this case, 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 is used 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.
A Content-Type exception may occur because of underlying logic or when clients use a mini program to transfer files on WeChat. In this case, you can add X-Ca-Signed-Content-Type:multipart/form-data as a custom Content-Type header to your request. If clients use this header, API Gateway also uses this header.
Date: the value of the Date header in the request, which can be left empty.
Headers: You can specify the headers to calculate a signature. When you concatenate signature strings, the following rules apply:
Header keys are 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 and retain the header key and colon (:).
The header keys that are used for the signature are separated by commas (,) and placed in headers 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 parameters of the following types: Path, Query, and Form.
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
Keys of Query and Form parameters are sorted in alphabetical order, and then concatenated by using the preceding method.
If you leave the Query and Form parameters empty, you can use Path parameters without the need to add the question mark (?).
If parameters are left empty, only the key is used for signature.
If the Query and Form parameters have array parameters that have the same key but different values, the first value is used to calculate the signature.
The following example shows the parameters in a standard 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=123456789
The following signature string is generated for the preceding request:
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
3.2.2. Signature calculation
After clients combine key data that is extracted from the HTTP request into a signature string, the clients must encrypt and encode the signature string to generate a final signature. API Gateway supports the following encryption algorithms:
HmacSHA256
HmacSHA1
The following example shows the encryption method, where stringToSign is the extracted signature string and secret is the AppSecret.
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha256.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA256"));
byte[] md5Result = hmacSha256.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);
Mac hmacSha1 = Mac.getInstance("HmacSHA1");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha1.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA1"));
byte[] md5Result = hmacSha1.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);
A Byte array is obtained after StringToSign is decoded in UTF-8. Then, the Byte array is encrypted and encoded in Base64 to generate the final signature.
3.2.3. Signature transfer
Clients must include some or all of the following headers in the requests that are sent to API Gateway for signature verification:
x-ca-key: the AppKey. This parameter is required.
x-ca-signature-method: the signature method. This parameter is optional. Valid values: HmacSHA256 and HmacSHA1. Default value: HmacSHA256.
X-Ca-Signature-Headers: the keys of all signature headers. This parameter is optional. Separate multiple keys with commas (,).
X-Ca-Signature: the signature. This parameter is required.
The following example shows an HTTP request that has 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=123456789
3.3. Troubleshooting
If signature verification fails, API Gateway adds the server-side signature string (StringToSign) to the header of the HTTP response that is returned to the clients. 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 to calculate the signature.
HTTP headers do not support line breaks. Line breaks in the signature string (StringToSign) are replaced with number signs (#).
errorMessage: Invalid Signature, Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`
The following example shows a server-side signature string:
GET
application/json
application/json
X-Ca-Key:200000
X-Ca-Timestamp:1589458000000
/app/v1/config/keys?keys=TEST