Use OpenAPI to obtain a token when an SDK is unavailable for the programming language or when dependencies need to be managed directly. This topic describes the request parameters, signature mechanism, and response format, and provides Java and Python examples.
Prepare credentials
The API requires an AccessKey ID and AccessKey secret. Set the ALIYUN_AK_ID and ALIYUN_AK_SECRET environment variables in the runtime environment. The examples read credentials from these variables.
AccessKey secrets and tokens are sensitive information. Do not include them in public code or logs. The following examples print the response, which contains a token. Protect this information when integrating the code into an application.
Code examples
The following examples obtain a token by sending an HTTPS GET request. In the response, Token.Id is the token value and Token.ExpireTime is its expiration timestamp in seconds.
Java
Use JDK 8 or later and add the following Maven dependency.
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Map;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class CreateToken {
private static String encode(String value) throws Exception {
return URLEncoder.encode(value, "UTF-8")
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
}
public static void main(String[] args) throws Exception {
String accessKeyId = System.getenv("ALIYUN_AK_ID");
String accessKeySecret = System.getenv("ALIYUN_AK_SECRET");
if (accessKeyId == null || accessKeyId.isEmpty()
|| accessKeySecret == null || accessKeySecret.isEmpty()) {
throw new IllegalArgumentException("Set ALIYUN_AK_ID and ALIYUN_AK_SECRET.");
}
String endpoint = "https://nlsmeta.ap-southeast-1.aliyuncs.com/";
Map<String, String> parameters = new TreeMap<>();
parameters.put("AccessKeyId", accessKeyId);
parameters.put("Action", "CreateToken");
parameters.put("Version", "2019-07-17");
parameters.put("RegionId", "ap-southeast-1");
parameters.put("Format", "JSON");
parameters.put("SignatureMethod", "HMAC-SHA1");
parameters.put("SignatureVersion", "1.0");
parameters.put("SignatureNonce", UUID.randomUUID().toString());
parameters.put("Timestamp", Instant.now().truncatedTo(ChronoUnit.SECONDS).toString());
StringJoiner query = new StringJoiner("&");
for (Map.Entry<String, String> entry : parameters.entrySet()) {
query.add(encode(entry.getKey()) + "=" + encode(entry.getValue()));
}
String canonicalQuery = query.toString();
String stringToSign = "GET&" + encode("/") + "&" + encode(canonicalQuery);
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec((accessKeySecret + "&").getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String signature = Base64.getEncoder().encodeToString(
mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));
Request request = new Request.Builder()
.url(endpoint + "?" + canonicalQuery + "&Signature=" + encode(signature))
.get().build();
OkHttpClient client = new OkHttpClient();
try (Response response = client.newCall(request).execute()) {
String body = response.body() == null ? "" : response.body().string();
if (!response.isSuccessful()) {
throw new IllegalStateException("HTTP " + response.code() + ": " + body);
}
System.out.println(body);
}
}
}
Python
Use Python 3.4 or later and install Requests. The example uses Python 3.14.7.
pip install requests
import base64
import hashlib
import hmac
import os
import uuid
from datetime import datetime, timezone
from urllib.parse import quote
import requests
def encode(value):
return quote(value, safe="-_.~")
def create_token():
access_key_id = os.environ["ALIYUN_AK_ID"]
access_key_secret = os.environ["ALIYUN_AK_SECRET"]
endpoint = "https://nlsmeta.ap-southeast-1.aliyuncs.com/"
parameters = {
"AccessKeyId": access_key_id,
"Action": "CreateToken",
"Version": "2019-07-17",
"RegionId": "ap-southeast-1",
"Format": "JSON",
"SignatureMethod": "HMAC-SHA1",
"SignatureVersion": "1.0",
"SignatureNonce": str(uuid.uuid4()),
"Timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
}
canonical_query = "&".join(
encode(key) + "=" + encode(value)
for key, value in sorted(parameters.items())
)
string_to_sign = "GET&" + encode("/") + "&" + encode(canonical_query)
signature = base64.b64encode(hmac.new(
(access_key_secret + "&").encode("utf-8"),
string_to_sign.encode("utf-8"), hashlib.sha1
).digest()).decode("ascii")
response = requests.get(
endpoint + "?" + canonical_query + "&Signature=" + encode(signature),
timeout=20,
)
if response.status_code != 200:
raise RuntimeError("HTTP {}: {}".format(response.status_code, response.text))
return response.text
if __name__ == "__main__":
print(create_token())
Request details
The API supports GET and POST and uses Alibaba Cloud POP request signing. HTTP and HTTPS requests use the same parameters. HTTPS is recommended.
Endpoint
Endpoint: https://nlsmeta.ap-southeast-1.aliyuncs.com/. RegionId: ap-southeast-1. API version: 2019-07-17.
Request parameters
|
Name |
Type |
Required |
Description |
|
AccessKeyId |
String |
Yes |
The AccessKey ID. |
|
Action |
String |
Yes |
The operation name. Set this parameter to |
|
Version |
String |
Yes |
The API version. Set this parameter to |
|
Format |
String |
No |
The response format. Set this parameter to |
|
RegionId |
String |
Yes |
The region ID. Set this parameter to |
|
Timestamp |
String |
Yes |
The request timestamp in UTC, in the |
|
SignatureMethod |
String |
Yes |
The signature algorithm. Set this parameter to |
|
SignatureVersion |
String |
Yes |
The signature algorithm version. Set this parameter to |
|
SignatureNonce |
String |
Yes |
A unique random string to prevent replay attacks. Use a different value for each request. A UUID such as |
|
Signature |
String |
Yes |
The signature calculated from all request parameters except Signature. See the signature mechanism below. |
Headers and parameter placement
For GET, place the parameters in the URL query string. For POST, place them in the request body.
|
Header |
Required |
Description |
|
Host |
No |
The service hostname. The HTTP client typically sets this header based on the endpoint. |
|
Accept |
No |
Set this header to |
|
Content-Type |
Required for POST |
Set this header to |
The following templates show the request format. <encoded-parameters> represents the URL-encoded parameter string, including Signature. When signing a POST request, use POST as the HTTP method. A GET signature cannot be reused for POST.
GET
GET /?<encoded-parameters> HTTP/1.1
Host: <endpoint-host>
Accept: application/json
POST
POST / HTTP/1.1
Host: <endpoint-host>
Accept: application/json
Content-Type: application/x-www-form-urlencoded
<encoded-parameters>
Signature mechanism
Every request must include a signature. The client uses the AccessKey secret to calculate an HMAC-SHA1 message authentication code. The server retrieves the corresponding secret based on the AccessKey ID and verifies the signature to authenticate the caller and check request integrity.
Construct the canonicalized query string
Exclude the Signature parameter and sort the remaining parameters by name in case-sensitive lexicographical order.
URL-encode each parameter name and value using UTF-8:
Do not encode
A-Z,a-z,0-9,-,_,., or~.Encode other characters as
%XYfor each UTF-8 byte. For example, encode a double quotation mark as%22.Encode spaces as
%20, not as a plus sign (+).
Join each encoded name and value with
=, and join the resulting pairs with&. Do not place&before the first parameter.
percentEncode(name1)=percentEncode(value1)&percentEncode(name2)=percentEncode(value2)
Java's URLEncoder uses form encoding. In its output, replace + with %20, * with %2A, and %7E with ~.
Construct the string to sign
Join the uppercase HTTP method, the encoded request path (/), and the encoded canonicalized query string with &.
StringToSign = HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)
Calculate and add the signature
Append
&to the AccessKey secret to form the HMAC-SHA1 key.Encode the key and string to sign in UTF-8, calculate the HMAC-SHA1 value, and Base64-encode the result.
URL-encode the Base64 result and add it to the request parameters as
Signature=<encoded-signature>.
Signature = Base64(HMAC-SHA1(AccessKeySecret + "&", StringToSign))
Signature verification example
Use the following fixed parameters to check a signing implementation offline. The AccessKey pair is fictitious and the timestamp has expired, so these values cannot be used to obtain a token.
AccessKeyId: my_access_key_id
AccessKeySecret: my_access_key_secret
Action: CreateToken
Format: JSON
SignatureMethod: HMAC-SHA1
SignatureVersion: 1.0
SignatureNonce: b924c8c3-6d03-4c5d-ad36-d984d3116788
Timestamp: 2019-04-18T08:32:31Z
HTTPMethod: GET
Canonicalized query string:
AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-07-17
String to sign:
GET&%2F&AccessKeyId%3Dmy_access_key_id%26Action%3DCreateToken%26Format%3DJSON%26RegionId%3Dap-southeast-1%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Db924c8c3-6d03-4c5d-ad36-d984d3116788%26SignatureVersion%3D1.0%26Timestamp%3D2019-04-18T08%253A32%253A31Z%26Version%3D2019-07-17
Base64 signature:
4TdrOuLHXJU+5C6s927Wkq2h+wc=
URL-encoded signature parameter:
Signature=4TdrOuLHXJU%2B5C6s927Wkq2h%2Bwc%3D
Response details
The following descriptions apply when Format=JSON. GET and POST requests use the same response format.
Successful response
The HTTP status code is 200. The main fields are as follows.
|
Field |
Type |
Description |
|
Token |
Object |
Contains the token value and expiration time. |
|
Token.Id |
String |
The token value. |
|
Token.ExpireTime |
Long |
The expiration time as a Unix timestamp in seconds, not a validity duration. For example, 1553825814 corresponds to 2019-03-29 02:16:54 UTC. The token is valid before this time. |
The following example shows the Token field in a response.
{
"Token": {
"Id": "<token>",
"ExpireTime": 1553825814
}
}
Error response
The HTTP status code is not 200. Check the request parameters based on Code and Message.
|
Field |
Type |
Description |
|
RequestId |
String |
The request ID, which can be used for troubleshooting. |
|
Code |
String |
The error code. |
|
Message |
String |
The error message. |
For example, if the AccessKey ID does not exist, the API returns HTTP 404 with the following fields.
{
"RequestId": "<request-id>",
"Code": "InvalidAccessKeyId.NotFound",
"Message": "Specified access key is not found."
}
Related topics
For temporary debugging, obtain a token in the console.
To use an SDK to handle request signing and transmission, see Obtain a token using an SDK.