This topic describes how to authorize third-party users to download an object by providing them a signed URL or a temporary access credential without exposing the AccessKey pair of the object owner.

Use a temporary access credential to authorize third-party users

You can use Alibaba Cloud STS to authorize temporary access to OSS. STS is a web service that provides temporary access tokens for users. You can use STS to grant a set of temporary access credentials that have a custom validity period and custom permissions to a third-party application or a RAM user managed by you. For more information about STS, see What is STS?.

STS provides the following benefits:

  • You need only to generate an access token and send the access token to a third-party application, instead of exposing your AccessKey pair to the third-party application. You can define the access permissions and validity period of this token.
  • The token automatically expires after the validity period. Therefore, you do not need to manually revoke the access permissions of a token.
Note You can call the AssumeRole operation or use Security Token Service (STS) SDKs for various programming languages to obtain a temporary access credential. For more information, see STS SDK overview. The temporary access credential contains a security token and a temporary AccessKey pair. The AccessKey pair consists of an AccessKey ID and an AccessKey secret. The minimum validity period of a temporary access credential is 900 seconds. The maximum validity period of a temporary access credential is the maximum session duration specified for the current role. For more information, see Specify the maximum session duration for a RAM role.

Use OSS SDKs

The following code provides examples on how to use Object Storage Service (OSS) SDKs for common programming languages to authorize third-party users to download objects by providing a temporary access credential from STS. For more information about how to use OSS SDKs for other programming languages to authorize third-party users to download objects by providing a temporary access credential from STS, see Overview.

// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
String endpoint = "yourEndpoint";
// Specify the temporary AccessKey pair obtained from STS. 
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// Specify the security token obtained from STS. 
String securityToken = "yourSecurityToken";
// Specify the bucket name. Example: examplebucket. 
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. The full path cannot contain the bucket name. 
String objectName = "exampleobject.txt";

// After you obtain a temporary access credential from STS, you can use the security token and temporary AccessKey pair that are contained in the credential to create an OSSClient instance. 
// Create an OSSClient instance. 
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);

// Use the STS temporary access credential to download the object and store the object as a local file. If the specified local file already exists, the file is replaced by the downloaded object. If the specified local file does not exist, the local file is created. 
// If the path is not specified, the downloaded object is saved to the path of the project to which the sample program belongs. 
ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File("D:\\localpath\\examplefile.txt"));

// Shut down the OSSClient instance. 
ossClient.shutdown();
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// Specify the temporary AccessKey pair obtained from STS. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Specify the security token obtained from STS. 
$securityToken = "yourSecurityToken";
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Specify the bucket name. Example: examplebucket. 
$bucket = "examplebucket";
// Specify the full path of the object. The full path cannot contain the bucket name. 
$object = "exampledir/exampleobject.txt";

try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);
    // Use the STS temporary access credential to download the object. 
    $content = $ossClient->getObject($bucket, $object);
    var_dump($content);
} catch (OssException $e) {
    print $e->getMessage();
}
# -*- coding: utf-8 -*-

from aliyunsdkcore import client
from aliyunsdksts.request.v20150401 import AssumeRoleRequest
import json
import oss2

# Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
endpoint = 'yourEndpoint'
# Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and management. To create a RAM user, log on to the RAM console. 
access_key_id = 'yourAccessKeyId'
access_key_secret = 'yourAccessKeySecret'
# Specify the name of the bucket. Example: examplebucket. 
bucket_name = 'examplebucket'
# Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain the bucket name. 
object_name = 'exampledir/exampleobject.txt'
# To obtain the Alibaba Cloud Resource Name (ARN) information of the RAM role, log on to the RAM console. In the left-side navigation pane, choose Identities > Roles. On the Roles page, search for and click the created RAM role. In the Basic Information section of the role details page, you can view and copy the ARN information. 
# Specify the ARN information of the RAM role. Format: acs:ram::$accountID:role/$roleName. 
# $accountID specifies the Alibaba Cloud account ID. To view the Alibaba Cloud account ID, perform the following steps: Log on to the OSS console, and move the pointer over the profile picture in the upper-right corner to view and copy the account ID, or click Basic Information to view the account ID. 
# $roleName specifies the name of the RAM role. To view the RAM role name, perform the following steps: Log on to the RAM console. In the left-side navigation pane, click Roles. On the Roles page, view the name in the Role Name column. 
role_arn = 'acs:ram::17464958********:role/ossststest'

# Create a RAM policy. 
# The policy specifies that GetObject operations can be performed on resources only in the bucket named examplebucket. 
policy_text = '{"Version": "1", "Statement": [{"Action": ["oss:GetObject"], "Effect": "Allow", "Resource": ["acs:oss:*:*:examplebucket/*"]}]}'

clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hangzhou')
req = AssumeRoleRequest.AssumeRoleRequest()

# Set the format of the returned value to JSON. 
req.set_accept_format('json')
req.set_RoleArn(role_arn)
# Specify a custom role session name to distinguish different tokens. Example: session-test. 
req.set_RoleSessionName('session-test')
req.set_Policy(policy_text)
body = clt.do_action_with_exception(req)

# Use the AccessKey pair of the RAM user to apply for a temporary access credential from STS. 
token = json.loads(oss2.to_unicode(body))

# Initialize the StsAuth instance based on the authentication information in the temporary access credential. 
auth = oss2.StsAuth(token['Credentials']['AccessKeyId'],
                    token['Credentials']['AccessKeySecret'],
                    token['Credentials']['SecurityToken'])

# Initialize a bucket based on the StsAuth instance. 
bucket = oss2.Bucket(auth, endpoint, bucket_name)

# Download the object from the bucket. 
read_obj = bucket.get_object(object_name)
print(read_obj.read())            
package main

import (
    "fmt"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "os"
)

func main() {
    // Specify the security token obtained from STS. 
    securitytoken := "yourSecurityToken"
    // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
    // Specify the temporary AccessKey pair obtained from STS. 
    // After you obtain a temporary access credential from STS, you can use the security token and temporary AccessKey pair that are contained in the credential to create an OSSClient instance. 
    // Create an OSSClient instance. 
    client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "yourAccessKeyId", "yourAccessKeySecret", oss.SecurityToken(securitytoken))
    if err != nil {
        fmt.Println("Error:", err)
    os.Exit(-1)

    }
    // Specify the bucket name. Example: examplebucket. 
    bucketName := "examplebucket"
    // Specify the full path of the object. The full path cannot contain the bucket name. Example: exampledir/exampleobject.txt. 
    objectName := "exampledir/exampleobject.txt"
    // Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. 
    filepath := "D:\\localpath\\examplefile.txt"
    // Use the STS temporary access credential to download the object. 
    err = bucket.GetObjectToFile(objectName,filepath)
    fmt.Println(err)
}

Use a signed URL to authorize third-party users

Notice A validity period must be set for an STS temporary access credential and a signed URL. When you use an STS temporary account credential to generate a signed URL that is used to perform operations such as object upload and download, the minimum validity period takes precedence. For example, you can set the validity period of your STS temporary access credential to 1,200 seconds and the validity period of your signed URL generated by using this credential to 3,600 seconds. In this case, the signed URL cannot be used to upload objects after the STS temporary access credential expires, even if the signed URL is within its validity period.

You can generate a signed URL and provide the URL to a visitor for temporary access. When you generate a signed URL, you can specify the validity period of the URL to limit the period of access from visitors. By default, the validity period of a signed URL is 3,600 seconds. The maximum validity period of a signed URL is 32,400 seconds.

You can add signature information to a URL and provide the URL to a third-party user for authorized access. For more information, see Add signatures to URLs.

Notice If you use the following code to generate a signed URL that contains the plus sign (+), you may fail to access OSS by using the URL. In this case, you need to replace + in the URL with %2B.

Use OSS SDKs

The following code provides examples on how to use OSS SDKs for common programming languages to authorize third-party users to download objects by proving a temporary access credential from STS. For more information about how to use OSS SDKs for other programming languages to authorize third-party users to download objects by proving a temporary access credential from STS, see Overview.

// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
String endpoint = "yourEndpoint";
// Specify the temporary AccessKey pair obtained from STS. 
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// Specify the security token obtained from STS. 
String securityToken = "yourSecurityToken";
// Specify the name of the bucket. Example: examplebucket. 
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. The path cannot contain the bucket name. 
String objectName = "exampleobject.txt";

// Create an OSSClient instance. 
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);

// Specify the expiration time of the signed URL. 
Date expiration = null;
try {
    expiration = DateUtil.parseRfc822Date("Wed, 18 Mar 2022 14:20:00 GMT");
} catch (ParseException e) {
    e.printStackTrace();
}
// Create a request to generate the signed URL. 
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
// Specify the expiration time of the request. 
request.setExpiration(expiration);
// Generate the signed URL that allows HTTP GET requests. 
URL signedUrl = ossClient .generatePresignedUrl(request);
System.out.println("signed url for getObject: " + signedUrl);

// Use the signed URL to send a request. 
Map<String, String> customHeaders = new HashMap<String, String>();
// Add headers to the GetObject request. 
customHeaders.put("Range", "bytes=100-1000");
OSSObject object = ossClient.getObject(signedUrl,customHeaders);

// Shut down the OSSClient instance. 
ossClient.shutdown();                           
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;

// Specify the temporary AccessKey ID and AccessKey secret that are obtained from STS. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Specify the security token that is obtained from STS. 
$securityToken = "yourSecurityToken";
// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if your bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
$endpoint = "yourEndpoint";
// Specify the bucket name. 
$bucket= "examplebucket";
// Specify the full path of the object. The full path does not contain the bucket name. 
$object = "exampleobject.txt";
// Set the validity period of the URL to 3,600 seconds. 
$timeout = 3600;
try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);

    // Generate the signed URL for the GetObject request. 
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": signedUrl: " . $signedUrl . "\n");

// You can run code to access the signed URL, or enter the URL in the address bar of a browser to access the signed URL. 
$request = new RequestCore($signedUrl);
// Set the default method to access the signed URL to GET. 
$request->set_method('GET');
$request->add_header('Content-Type', '');
$request->send_request();
$res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code());
if ($res->isOK()) {
    print(__FUNCTION__ . ": OK" . "\n");
} else {
    print(__FUNCTION__ . ": FAILED" . "\n");
};                    
# -*- coding: utf-8 -*-
import oss2
# Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and management. To create a RAM user, log on to the RAM console. 
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
# Specify the name of the bucket. Example: examplebucket. 
bucket = oss2.Bucket(auth, 'yourEndpoint', 'examplebucket')
# Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain the bucket name. 
object_name = 'exampledir/exampleobject.txt'

# Generate a signed URL that is used to download the object. The validity period of the URL is 60 seconds. 
# By default, OSS identifies the forward slashes (/) in the full path of an object as escape characters when the signed URL is generated. Therefore, you cannot directly use the signed URL. 
# Set the slash_safe parameter to True. This way, OSS does not identify the forward slashes (/) in the full path of the object as escape characters. Then, you can directly use the generated signed URL. 
url = bucket.sign_url('GET', object_name, 60, slash_safe=True)     
print('the address of the signed URL:', url)

# Use the signed URL to download the object to the local path. 
# Specify the full path of the local file that is downloaded from OSS. Example: D:\\localpath\\examplefile.txt. 
# By default, if you set this parameter to the name of a local file such as examplefile.txt without specifying the local path, the downloaded object is saved to the local path of the project to which the sample program belongs. 
result = bucket.get_object_with_url_to_file(url, 'D:\\localpath\\examplefile.txt')
print(result.read())
package main

import (
    "fmt"
    "os"
    "io/ioutil"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func HandleError(err error) {
    fmt.Println("Error:", err)
    os.Exit(-1)
}

func main() {
    // After you obtain a temporary STS credential, you can use the security token and temporary AccessKey pair (AccessKey ID and AccessKey secret) that are contained in the credential to create an OSSClient. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret", oss.SecurityToken("yourSecurityToken"))
    if err != nil {
        HandleError(err)
    }

    // Specify the name of the bucket in which the object you want to download is stored. 
    bucketName := "examplebucket"
    // Specify the full path of the object that you want to download. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    objectName := "exampledir/exampleobject.txt"
    // Download the object to the local directory and store the object as a local file. If the specified local file exists, it is overwritten by the downloaded object. Otherwise, the local file is created. 
    // If the path of the local file is not specified, the downloaded object is saved to the path of the project to which the sample program belongs. 
    localDownloadedFilename := "D:\\localpath\\examplefile.txt"

    // Obtain the bucket. 
    bucket, err := client.Bucket(bucketName)
    if err != nil {
        HandleError(err)
    }

    // Generate a signed URL to download the object to a stream. 
    signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 60)
    if err != nil {
        HandleError(err)
    }

    body, err := bucket.GetObjectWithURL(signedURL)
    if err != nil {
        HandleError(err)
    }
    // Read the object content from the stream. 
    data, err := ioutil.ReadAll(body)
    body.Close()
    data = data // Use the downloaded data. 

    // Generate a signed URL to download the object and store the object as a local file. 
    err = bucket.GetObjectToFileWithURL(signedURL, localDownloadedFilename)
    if err != nil {
        HandleError(err)
    }
}
                    
using Aliyun.OSS;
using Aliyun.OSS.Common;
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the bucket name. Example: examplebucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. The full path cannot contain the bucket name. Example: exampledir/exampleobject.txt. 
var objectName = "exampledir/exampleobject.txt";
// Specify the full path of the local file to which you want to download the object. Example: D:\\localpath\\examplefile.txt. If the specified local file exists, the object to download replaces the file. If the specified local file does not exist, a file is created. 
var downloadFilename = "D:\\localpath\\examplefile.txt";
// Create an OssClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    var metadata = client.GetObjectMetadata(bucketName, objectName);
    var etag = metadata.ETag;
    // Generate a signed URL. 
    var req = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Get)
      {
        // Specify the validity period of the signed URL. Default value: 3600. Unit: seconds. 
        Expiration = DateTime.Now.AddHours(1),
    };
    var uri = client.GeneratePresignedUri(req);
    // Use the signed URL to download the object. 
    OssObject ossObject = client.GetObject(uri);
    using (var file = File.Open(downloadFilename, FileMode.OpenOrCreate))
    {
        using (Stream stream = ossObject.Content)
        {
            int length = 4 * 1024;
            var buf = new byte[length];
            do
            {
                length = stream.Read(buf, 0, length);
                file.Write(buf, 0, length);
            } while (length != 0);
        }
    }
    Console.WriteLine("Get object by signatrue succeeded. {0} ", uri.ToString());
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}", 
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize the information about the account that is used to access OSS. */
    /* Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
    std::string Endpoint = "yourEndpoint";
    /* Specify the bucket name. Example: examplebucket. */
    std::string BucketName = "examplebucket";
    /* Specify the full path of the object. The full path cannot contain the bucket name. Example: exampledir/exampleobject.txt. */ 
    std::string GetobjectUrlName = "exampledir/exampleobject.txt";

    /* Initialize resources such as networks. */
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    /* Specify the validity period of a signed URL. */
    std::time_t t = std::time(nullptr) + 1200;
    /* Generate a signed URL. */
    auto genOutcome = client.GeneratePresignedUrl(BucketName, GetobjectUrlName, t, Http::Get);
    if (genOutcome.isSuccess()) {
        std::cout << "GeneratePresignedUrl success, Gen url:" << genOutcome.result().c_str() << std::endl;
    }
    else {
        /* Handle exceptions. */
        std::cout << "GeneratePresignedUrl fail" <<
        ",code:" << genOutcome.error().Code() <<
        ",message:" << genOutcome.error().Message() <<
        ",requestId:" << genOutcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /* Use the signed URL to download the object. */
    auto outcome = client.GetObjectByUrl(genOutcome.result());

    if (!outcome.isSuccess()) {
        /* Handle exceptions. */
        std::cout << "GetObjectByUrl fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /* Release resources such as networks. */
    ShutdownSdk();
    return 0;
}