You must sign all HTTP or HTTPS requests to ensure security. Alibaba Cloud uses the request signature to verify the identity of the API caller. Operation Orchestration Service (OOS) implements symmetric encryption with an AccessKey pair to verify the identity of the request sender.

An AccessKey pair is an identity credential issued to Alibaba Cloud accounts and Resource Access Management (RAM) users that is similar to the username and password used to log on to the OOS console. An AccessKey pair consists of an AccessKey ID and an AccessKey secret. The AccessKey ID is used to verify the identity of the user, while the AccessKey secret is used to encrypt and verify the signature string. You must keep your AccessKey secret strictly confidential.

Note Alibaba Cloud offers Alibaba Cloud service SDKs and third-party SDKs in multiple languages, helping you easily sign API requests. For more information, download SDKs.

Compose and encode a string-to-sign

  1. Create a canonicalized query string by arranging the request parameters (including all common and operation-specific parameters except Signature) in alphabetical order. For more information, see Common parameters. The canonicalized query string is only made up of the parameters and does not include "https://endpoint/?".
    Note When you use the GET method to send a request, the request parameters are those after the question mark (?) and separated with ampersands (&) in the request URL.
  2. Encode the canonicalized query string in UTF-8 based on RFC 3986. Encoding rules:
    • Uppercase letters, lowercase letters, digits, and some special characters such as ampersands (&), hyphens (-), underscores (_), periods (.), and tildes (~) do not need to be encoded.
    • Other characters must be percent encoded in %XY format. XY represents the ASCII code of the characters in hexadecimal notation. For example, double quotation marks (") are encoded as %22.
    • Extended UTF-8 characters are encoded in %XY%ZA... format.
    • Spaces must be encoded as %20. Do not encode spaces as plus signs (+). The preceding encoding method is similar to but slightly different from the application/x-www-form-urlencoded MIME-type encoding algorithm. If you use java.net.URLEncoder in the Java standard library, use percentEncode to encode request parameters and their values. In the encoded query string, replace the plus sign (+) with %20, the asterisk (*) with %2A, and %7E with a tilde (~). In this way, you can obtain an encoded string that matches the preceding encoding rules.
      private static final String ENCODING = "UTF-8";
      private static String percentEncode(String value) throws UnsupportedEncodingException {
      return value ! = null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
      }
  3. Connect the encoded parameter names and values with equal signs (=).
  4. Sort the parameter name and value pairs as described in the Compose and encode a string-to-sign section and connect the pairs with ampersands (&).

Now, you have obtained a canonicalized query string (CanonicalizedQueryString) that follows the request syntax.

Create a string-to-sign from the encoded canonicalized query string

  1. Create StringToSign. You can also use percentEncode to encode the canonicalized query string constructed in the previous step. The steps to create a string-to-sign are as follows:
    StringToSign=
    HTTPMethod + "&" + // HTTPMethod: HTTP method used to make the request, such as GET.
    percentEncode("/") + "&" + // percentEncode("/"): Encode the forward slash (/) in UTF-8 as %2F.
    percentEncode(CanonicalizedQueryString) // Encode the canonicalized query string created in Step 1.
  2. Calculate the hash-based message authentication code (HMAC) value of the string-to-sign, as defined in RFC 2104. Use the Secure Hash Algorithm 1 (SHA-1) algorithm to calculate the HMAC value. Encode the HMAC value in Base64 to obtain the signature string as follows.
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  3. Add the signature string encoded based on RFC3986 to the request as the Signature parameter. The parameters for the actual API request do not need to be in any particular order. The result is the signed API request.
Note The AccessKey secret appended with an ampersand (&) (ASCII: 38) is used as the key specified by RFC 2104 for the HMAC calculation.

Example 1: Concatenate parameters

The following example describes how to call the ListTemplates operation to query templates. In the case of AccessKeyID=testid and AccessKeySecret=testsecret, the signature process is as follows:

  1. Compose and encode a string-to-sign.
    AccessKeyId=testid&Action=ListTemplates&Format=json&SignatureMethod=HMAC-SHA1&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1&SignatureVersion=1.0&Timestamp=2019-05-27T06%3A35%3A22Z&Version=2019-06-01
  2. Create StringToSign as described in the Create a string-to-sign from the encoded canonicalized query string section.
    GET&%2F&AccessKeyId%3Dtestid&Action%3DListTemplates&Format%3Djson&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D9a3fdf30-8049-11e9-8875-6c96cfdd1fa1&SignatureVersion%3D1.0&Timestamp%3D2019-05-27T06%253A35%253A22Z&Version%3D2019-06-01
  3. Calculate the HMAC value of the string-to-sign. In the case of AccessKeySecret=testsecret, the key used for calculation is testsecret&. The calculated signature value is 1FcsD6/AvH2KugeowoCJSi8lBd8=. Encode the HMAC value in Base64 to obtain the signature string as follows.
    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  4. Add the signature string encoded based on RFC3986, which is Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D, to the request URL in Step 1.
    http://oos.cn-hangzhou.aliyuncs.com/?SignatureVersion=1.0&Format=json&Timestamp=2019-05-27T06%3A35%3A22Z&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Version=2019-06-01&Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D&Action=ListTemplates&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1

You can use a browser or tools such as cURL and Wget to initiate an HTTP request through the new URL. The HTTP request calls the ListTemplates operation to query templates.

Example 2: Use the standard library of the programming language

The following example describes how to call the ListTemplates operation to query templates. Assume that AccessKeyID is set to testid and AccessKeySecret is set to testsecret, and all request parameters are placed in a Java Map<String, String> object.

  1. Predefine the encoding method.
    private static final String ENCODING = "UTF-8";
    private static String percentEncode(String value) throws UnsupportedEncodingException {
    return value ! = null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
    }
  2. Predefine the time format for the Timestamp parameter. The value of the Timestamp parameter must be specified in the ISO 8601 standard. The time must be in UTC+0.
    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private static String formatIso8601Date(Date date) {
    SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
    df.setTimeZone(new SimpleTimeZone(0, "GMT"));
    return df.format(date);
    }
  3. Compose and encode a string-to-sign.
    final String HTTP_METHOD = "GET";
    Map parameters = new HashMap();
    // Specify request parameters.
    parameters.put("Action", "ListTemplates");
    parameters.put("Version", "2019-06-01");
    parameters.put("AccessKeyId", "testid");
    parameters.put("Timestamp", formatIso8601Date(new Date()));
    parameters.put("SignatureMethod", "HMAC-SHA1");
    parameters.put("SignatureVersion", "1.0");
    parameters.put("SignatureNonce", UUID.randomUUID().toString());
    parameters.put("Format", "JSON");
    // Arrange request parameters.
    String[] sortedKeys = parameters.keySet().toArray(new String[]{});
    Arrays.sort(sortedKeys);
    final String SEPARATOR = "&";
    // Create a string-to-sign.
    StringBuilder stringToSign = new StringBuilder();
    stringToSign.append(HTTP_METHOD).append(SEPARATOR);
    stringToSign.append(percentEncode("/")).append(SEPARATOR);
    StringBuilder canonicalizedQueryString = new StringBuilder();
    for(String key : sortedKeys) {
    // Encode the key and the value.
    canonicalizedQueryString.append("&")
    .append(percentEncode(key)).append("=")
    .append(percentEncode(parameters.get(key)));
    }
    // Encode the canonicalized query string.
    stringToSign.append(percentEncode(
    canonicalizedQueryString.toString().substring(1)));
  4. Calculate the HMAC value of the string-to-sign. In the case of AccessKeySecret=testsecret, the key used for calculation is testsecret&. The calculated signature value is 1FcsD6/AvH2KugeowoCJSi8lBd8=.
    // The following sample code shows how to calculate the signature string.
    final String ALGORITHM = "HmacSHA1";
    final String ENCODING = "UTF-8";
    key = "testsecret&";
    Mac mac = Mac.getInstance(ALGORITHM);
    mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
    byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
    String signature = new String(Base64.encodeBase64(signData));
  5. Encode the Signature parameter based on RFC 3986 and add the parameter to the URL. The new URL is as follows:
    http://oos.cn-hangzhou.aliyuncs.com/?SignatureVersion=1.0&Format=json&Timestamp=2019-05-27T06%3A35%3A22Z&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Version=2019-06-01&Signature=1FcsD6%2FAvH2KugeowoCJSi8lBd8%3D&Action=ListTemplates&SignatureNonce=9a3fdf30-8049-11e9-8875-6c96cfdd1fa1
    					
  6. Use a browser or tools such as cURL and Wget to initiate an HTTP request through the new URL.
    {
    "Templates": [
     {
       "Hash": "9ea05673ea6c7d03fe8707ddd3d347d74f9e47963538097d120583c0b5385edf",
       "Description": "",
       "TemplateName": "demo",
       "ShareType": "Private",
       "Tags": [],
       "TemplateFormat": "JSON",
       "CreatedBy": "1000008528360000",
       "CreatedDate": "2019-06-01T12:00:00Z",
       "TemplateVersion": "v1",
       "TotalExecutionCount": 1
     },...],
     "NextToken": "gAAAAABc5pnvl_meBuZkGEbZNmzTOA1RotEjFs4q8q2fICes_oGk4qenxGB5UeyXYWa5eF4TeZLQMpnVc6rmhr2BC0Kahyx1P5brt_fQvLFTLBEcXQzzqsWwxDS-Y1xL7pkhOOgU_K3Z0-dMQHOkIQwWhodp4qutzKNO7gQ-EPWQvM1ugrGkonFDe_bV3TckHyHqgJDTLwk8Swfm1NvnZTXg9AH8YLvhu0fTK8sgXI6nBkvqTkozedWFhq8jmH1SFbs1yVZoKoKpFaYV6-vuTFcUO9G9-5W0YVdfliTuEOf42QHtkWLZ8jj1Xhmk9rTBYjb7P4KmRm7b7UhQ6FamvpVv9vXlCQvWAafnPgT98ViFlr6z7ByNHrI=",
     "RequestId": "8B813042-7F00-45CE-AF8C-85CCEEFC6BA2",
     "MaxResults": 50
    }

The result data lists the queried templates.