This example shows how to sign a PutObject request by hand in Node.js — constructing the string to sign, computing the HMAC-SHA1 signature, and setting the Authorization header — without using the OSS SDK (software development kit).
Use the OSS SDK for production applications. Manual signing is useful when you cannot use the SDK or need to understand the underlying authentication mechanism.
Prerequisites
Before you begin, ensure that you have:
Node.js v12.10.0 or later installed
An OSS bucket
An AccessKey ID and AccessKey secret with write access to the bucket
The following npm packages installed:
npm install crypto-js request
How signing works
OSS authenticates each request using a signature in the Authorization header. The signature is computed from a string to sign that encodes the request method, content type, date, and resource path.
String-to-sign formula:
StringToSign = HTTP-Verb + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedResourceAuthorization header format:
Authorization: OSS <AccessKeyId>:<Signature>
Signature = Base64(HMAC-SHA1(AccessKeySecret, StringToSign))Field reference:
| Field | Required | Description |
|---|---|---|
HTTP-Verb | Yes | The HTTP method in uppercase, for example, PUT |
Content-MD5 | No | MD5 hash of the request body. Use an empty string if omitted. |
Content-Type | No | MIME type of the request body. Use an empty string if omitted. |
Date | Yes | Request time in GMT format, for example, Mon, 02 Mar 2026 08:00:00 GMT |
CanonicalizedResource | Yes | Slash-prefixed bucket name and object key, for example, /mybucket/mytest/nodejs.txt |
Example: how a PutObject request maps to the string to sign
Request StringToSign
PUT /mytest/nodejs.txt HTTP/1.1 PUT\n
Content-Type: application/json \n
Date: Mon, 02 Mar 2026 08:00:00 GMT application/json\n
Host: mybucket.oss-cn-hangzhou... Mon, 02 Mar 2026 08:00:00 GMT\n
/mybucket/mytest/nodejs.txtNote that Content-MD5 is absent from the request, so it becomes an empty string in the string to sign.
Sign and upload an object
The following Node.js code signs a PutObject request using HMAC-SHA1 and uploads an object to OSS.
var HmacSha1 = require('crypto-js/hmac-sha1');
var Base64 = require('crypto-js/enc-base64');
var request = require('request');
// Configuration — replace placeholders with your actual values
var endpoint = 'http://oss-cn-hangzhou.aliyuncs.com'; // <region-endpoint>
var bucketName = 'xxx'; // <your-bucket-name>
var objectName = 'mytest/nodejs.txt'; // <your-object-name>
var accesskey = 'xxxx'; // <your-accesskey-id>
var accesskeysecret = 'xxx'; // <your-accesskey-secret>
// Build the string to sign
var gmtDate = (new Date()).toGMTString();
var contenttype = 'application/json';
var strtosign = 'PUT\n\n' + contenttype + '\n' + gmtDate + '\n' + '/' + bucketName + '/' + objectName;
// Compute the signature
var sign = Base64.stringify(HmacSha1(strtosign, accesskeysecret));
// Send the PUT request
var options = {
url: 'http://' + bucketName + '.oss-cn-hangzhou.aliyuncs.com/' + objectName,
headers: {
'Content-Type': contenttype,
'Date': gmtDate,
'Authorization': 'OSS ' + accesskey + ':' + sign
},
body: '{test:test}'
};
request.put(options, function(error, response, body) {
console.info('response: ' + JSON.stringify(response));
console.info('statusCode: ' + response.statusCode);
console.info('body: ' + body);
});Replace the following placeholders with your actual values:
| Placeholder | Description | Example |
|---|---|---|
<region-endpoint> | OSS endpoint for your region | http://oss-cn-hangzhou.aliyuncs.com |
<your-bucket-name> | Your bucket name | my-bucket |
<your-object-name> | Target object path in the bucket | mytest/nodejs.txt |
<your-accesskey-id> | Your AccessKey ID | LTAI5tXxx |
<your-accesskey-secret> | Your AccessKey secret | xXxXxXx |
Troubleshooting
`SignatureDoesNotMatch`
This error means the signature OSS computed from your request does not match the one you sent. Check the following:
The
Dateheader is in valid GMT format and matches the value used in the string to sign.The
Content-Typein the string to sign exactly matches theContent-Typeheader, including case.CanonicalizedResourcestarts with/followed by the bucket name and object key:/bucketName/objectName.If
Content-MD5orContent-Typeis absent from the request, use an empty string ("") in that position of the string to sign.The AccessKey secret used to compute the signature is correct and has not been rotated.
`403 Access Denied`
Verify that the AccessKey ID and AccessKey secret are valid and that the associated account has oss:PutObject permission on the target bucket.
What's next
Include signatures in the Authorization header — full specification for OSS request signing