All Function Compute API requests must be signed, whether sent over HTTP or HTTPS. Function Compute verifies identity by validating the Authorization header of each request. A request is accepted only if the client uses the same signature algorithm as Function Compute.
If a function has an HTTP trigger configured for anonymous access, signature verification is skipped. For all other requests, a missing or invalid Authorization header causes Function Compute to return HTTP status code 403. Rejected requests are not charged. For details, see Billing overview.
Tip: Function Compute SDKs handle signing automatically. If you use an SDK, you do not need to implement this algorithm manually. See SDKs.
How signing works
The signature is computed using HMAC-SHA256 over a canonical string derived from the request, then Base64-encoded. The resulting Authorization header takes the following form:
Authorization = "FC " + accessKeyID + ":" + signatureThe signature is computed as:
signature = Base64(HMAC-SHA256(AccessKey secret, string-to-sign))Where string-to-sign is constructed by concatenating the following components, each separated by a newline (\n):
HTTP_METHOD + "\n"
+ CONTENT-MD5 + "\n"
+ CONTENT-TYPE + "\n"
+ DATE + "\n"
+ CanonicalizedFCHeaders
+ CanonicalizedResourceString-to-sign components
| Component | Description |
|---|---|
HTTP_METHOD | The HTTP method in uppercase: GET, PUT, POST, or DELETE. |
CONTENT-MD5 | The MD5 hash of the request body. Leave blank if the request has no Content-MD5 header. |
CONTENT-TYPE | The request body type. Function Compute requires application/json. |
DATE | The request timestamp in RFC 1123 GMT format. Cannot be blank. Example: Mon, 02 Jan 2006 15:04:05 GMT. |
CanonicalizedFCHeaders | A canonicalized string of all x-fc- prefixed request headers. See CanonicalizedFCHeaders. |
CanonicalizedResource | The canonical request URL path. See CanonicalizedResource. |
The clock skew between when you generate the signature and when Function Compute receives the request must not exceed 15 minutes. Requests outside this window are rejected.
CanonicalizedFCHeaders
Build the CanonicalizedFCHeaders value in three steps:
Collect all HTTP header fields whose names start with
x-fc-. Convert each header name to lowercase.Format each header as
${key}:${value}\n. Sort the formatted strings alphabetically by header name.Concatenate the sorted strings.
Example: The header X-Fc-Invocation-Type:Sync becomes x-fc-invocation-type:Sync\n.
The following pseudocode (JavaScript) implements this logic:
// prefix = 'x-fc-'
function buildCanonicalHeaders(headers, prefix) {
var list = [];
var keys = Object.keys(headers);
var fcHeaders = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var lowerKey = key.toLowerCase().trim();
if (lowerKey.startsWith(prefix)) {
list.push(lowerKey);
fcHeaders[lowerKey] = headers[key];
}
}
list.sort();
var canonical = '';
for (var _i = 0; _i < list.length; _i++) {
var _key = list[_i];
canonical += `${_key}:${fcHeaders[_key]}\n`;
}
return canonical;
}CanonicalizedResource
The CanonicalizedResource is derived from the request URL path. The URL path uses the format $api-version/api-path, where:
api-version: the API version, currently2016-08-15.api-path: the operation-specific path. For example, the CreateService operation uses/services. See List of operations by function.
Function Compute processes CanonicalizedResource differently depending on the request type.
Common requests (all requests except those for HTTP-trigger functions requiring authentication):
URL-decode the path and discard the query string. Use only the content before ?.
Requests for HTTP-trigger functions with authentication required:
URL-decode the full path. If the request has query parameters, sort all key-value pairs alphabetically and separate them with \n, then append to the decoded path. If there are no query parameters, append \n to the end of the decoded path.
When a parameter key maps to multiple values, treat the key and all its values as a single unit when sorting.
Example — HTTP trigger with authentication:
// Original URL (URL-encoded):
/2016-08-15/proxy/service-name/func-name/path-with-%20-space/action?x=1&a=2&x=3&with%20space=foo%20bar
// After URL decoding:
/2016-08-15/proxy/service-name/func-name/path-with- -space/action?x=1&a=2&x=3&with space=foo bar
// CanonicalizedResource (params sorted alphabetically, separated by \n):
/2016-08-15/proxy/service-name/func-name/path-with- -space/action\na=2\nwith space=foo bar\nx=1\nx=3Example — Common request:
// CanonicalizedResource (query string discarded):
/2016-08-15/service-name/func-name/path-with- -space/actionPseudocode reference
The following pseudocode shows how to build the string-to-sign and compute the signature. Use your AccessKey secret as the signing key.
// Build the string-to-sign
function composeStringToSign(method, path, headers, queries) {
var contentMD5 = headers['content-md5'] || '';
var contentType = headers['content-type'] || '';
var date = headers['date'];
var signHeaders = buildCanonicalHeaders(headers, 'x-fc-');
var u = url.parse(path);
var pathUnescaped = decodeURIComponent(u.pathname);
var str = `${method}\n${contentMD5}\n${contentType}\n${date}\n${signHeaders}${pathUnescaped}`;
if (queries) {
var params = [];
Object.keys(queries).forEach(function (key) {
var values = queries[key];
var type = typeof values;
if (type === 'string') {
params.push(`${key}=${values}`);
return;
}
if (type === 'object' && values instanceof Array) {
queries[key].forEach(function (value) {
params.push(`${key}=${value}`);
});
}
});
params.sort();
str += '\n' + params.join('\n');
}
return str;
}
// Compute the signature using HMAC-SHA256 and Base64-encode the result
function signString(source, secret) {
const buff = crypto.createHmac('sha256', secret)
.update(source, 'utf8')
.digest();
return new Buffer(buff, 'binary').toString('base64');
}After computing the signature, construct the Authorization header:
Authorization = "FC " + accessKeyID + ":" + signatureExample `Authorization` header value:
FC <your-access-key-id>:<computed-signature>Replace <your-access-key-id> with your AccessKey ID and <computed-signature> with the Base64-encoded HMAC-SHA256 output.