Application-Enabled Authentication

Last updated: 2021-06-25 11:31:32

    If a published API uses the application-enabled authentication method (ApiAppKey and ApiAppSecret), when a client calls the API, it needs to use the signature key to perform signature calculation on the request content and transfer the signature to the server for signature verification. This document describes how to implement the signature calculation process on the client.

    Note:

    For application-enabled authentication signature demos for common programming languages, please see Development Guide - Application-Enabled Authentication Signature Generation in Multiple Programming Languages.

    Overview

    API Gateway provides a frontend signature calculation and verification feature, which can:

    • Verify the validity of a client request and confirm that the request carries the signature generated by the authorized ApiAppKey.
    • Prevent the request data from being tampered with during network transfer.

    The owner of an API can generate an application on the application management page in the API Gateway console. Each application carries a signature key pair (ApiAppKey and ApiAppSecret). After the API owner authorizes the API to the specified application (which can be issued by the API owner or owned by an API caller), the API caller can use the application's signature key to call the API.

    When the client calls the API, it needs to use the authorized signature key to perform encrypted signature calculation on the critical request content, put the ApiAppKey and the encrypted signature string in the header of the request, and transfer it to API Gateway. API Gateway will read the header information of the ApiAppKey in the request, query the value of the ApiAppSecret corresponding to the value of the ApiAppKey, use the ApiAppSecret to perform signature calculation on the critical data in the received request, and compare the generated signature with the signature sent by the client to verify the correctness of the signature. Only if the request passes the signature verification will it be sent to the backend service; otherwise, API Gateway will deem the request invalid and directly return an error.

    Signature Generation and Verification Process

    Prerequisites

    • The API caller needs to get the signature key pair (ApiAppKey and ApiAppSecret) authorized to an API before calling the API.
    • The security authentication type of the called API is "Application-Enabled Authentication".

    Signature generation on client

    1. Extract the critical data from the original request and get a string for signing.
    2. Use the encryption algorithm plus ApiAppSecret to encrypt the critical data signature string to get a signature.
    3. Add all headers related to the signature to the original HTTP request to get the final HTTP request.

    Signature verification on server

    1. Extract the critical data from the received request and get a string for signing.
    2. Read the ApiAppKey from the received request and query the corresponding ApiAppSecret through the ApiAppKey.
    3. Use the encryption algorithm plus ApiAppSecret to encrypt the critical data signature string to get a signature.
    4. Read the client signature from the received request and check whether the server signature and the client signature are the same.

    Signature Generation and Transfer

    Signature string extraction

    The client needs to extract the critical data from the HTTP request and splice it into a signature string in the following format:

    Headers
    HTTPMethod
    Accept
    Content-Type
    Content-MD5
    PathAndParameters
    

    The above 6 fields constitute the entire signature string. They need to be separated with \n. Headers must contain X-Date. There is no need to add \n after PathAndParameters. Even if other fields are empty, \n should still be retained. The signature is case sensitive. The extraction rules for each field are as follows:

    • Headers: you can select specified headers to participate in the signature calculation. The keys of the selected headers are sorted in lexicographical order and then spliced as follows:
      HeaderKey1 + ": " + HeaderValue1 + "\n"\+
      HeaderKey2 + ": " + HeaderValue2 + "\n"\+
      ...
      HeaderKeyN + ": " + HeaderValueN + "\n"
      
      The headers in Authorization are the ones involved in signature calculation. We recommend you convert them to the lowercase and separate them by ASCII spaces. For example, if the headers involved in the calculation are date and source, the format should be headers="date source"; if only the x-date header participates in the calculation, the format should be headers="x-date".
    • HTTPMethod: HTTP method. The value should be in all caps (such as POST).
    • Accept: value of the Accept header in the request, which can be empty. We recommend you explicitly set the Accept header. If it is empty, some HTTP clients will set the default value of / for it, causing signature verification to fail.
    • Content-Type: value of the Content-Type header in the request, which can be empty.
    • Content-MD5: value of the Content-MD5 header in the request, which can be empty. The Content-MD5 header is calculated only when the request has a Body in a non-Form format. The calculation method of the Content-MD5 value in Java is as follows:
      String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
      
    • PathAndParameters: it contains all the parameters in Path, Query, and Form in the following format:
      • The keys of the Query and Form parameter pair are sorted in lexicographical order and then spliced in the above-mentioned method.
      • If Query and Form parameters are empty, use Path directly without adding ?.
      • If the value of a parameter is empty, only the key is kept to participate in the signature calculation, and the equal sign does not need to be added in the signature.
      • If there are array parameters in Query and Form (i.e., parameters with the same key but different values), the values need to be sorted in lexicographical order and then spliced in the above-mentioned method.

    Take a general HTTP request as an example:

    POST / HTTP/1.1
    host:service-3rmwxxxx-1255968888.cq.apigw.tencentcs.com
    accept:application/json
    content-type:application/x-www-form-urlencoded
    source:apigw test
    x-date:Thu, 11 Mar 2021 08:29:58 GMT
    content-length:8
    p=test
    

    The generated correct signature string is as follows:

    source: apigw test
    x-date: Thu, 11 Mar 2021 08:29:58 GMT
    POST
    application/json
    application/x-www-form-urlencoded
    
    /?p=test
    

    Signature calculation

    After the client extracts the critical data from the HTTP request and splices it into a signature string, it needs to encrypt and encode the signature string to form the final signature in the following steps:

    1. Use UTF-8 to decode the signature string (signing_str signing information) to get a byte array.
    2. Use the encryption algorithm to encrypt the byte array.
    3. Base64-encode the encrypted byte array to form the final signature.

    Signature transfer

    The client needs to put the Authorization in the HTTP request and transfer it to API Gateway for signature verification.
    The format of the Authorization header is as follows:

    Authorization: hmac id="secret_id", algorithm="hmac-sha1", headers="date source", signature="Base64(HMAC-SHA1(signing_str, secret_key))"
    

    The parameters in Authorization are described as follows:

    Parameter Description
    hmac Fixed and used to indicate the calculation method
    ID Value of the secret_id in the key
    algorithm Encryption algorithm. HMAC-SHA1 and HMAC-SHA256 are supported currently
    headers Headers involved in the signature calculation
    signature Signature obtained after signature calculation is completed, with signing_str as its content

    Below is an example of an HTTP request with a signature:

    POST / HTTP/1.1
    host:service-3rmwxxxx-1255968888.cq.apigw.tencentcs.com
    accept:application/json
    content-type:application/x-www-form-urlencoded
    source:apigw test
    x-date:Thu, 11 Mar 2021 08:29:58 GMT
    Authorization:hmac id="xxxxxxx", algorithm="hmac-sha1", headers="source x-date", signature="xyxyxyxyxyxy"
    content-length:8
    p=test
    

    Signature Troubleshooting

    Error description:
    If the API Gateway signature verification fails, the server's signature string (StringToSign) will be put in the HTTP response header and returned to the client with an error code of 401.

    Solution:

    1. Check whether the locally calculated signature string (StringToSign) is the same as that returned by the server.
    2. Check whether the ApiAppSecret used for signature calculation is correct.
      Since line breaks cannot be expressed in HTTP headers, line breaks in StringToSign are replaced with #.
      "message":"HMAC signature does not match, Server StringToSign:source: apigw test#x-date: Thu, 11 Mar 2021 08:49:30 GMT#POST#application\/json#application\/x-www-form-urlencoded##\/?p=test"
      
      This means that the server signature is:
      source: apigw test
      x-date: Thu, 11 Mar 2021 08:29:58 GMT
      POST
      application/json
      application/x-www-form-urlencoded

      /?p=test