All Products
Search
Document Center

Resource Access Management:Use STS tokens to grant mobile apps access to Alibaba Cloud resources

Last Updated:Jan 08, 2026

This topic describes a common security pattern where a mobile app uses Security Token Service (STS) tokens to directly access Alibaba Cloud resources.

Background information

In this scenario, an enterprise develops a mobile app that must upload and download data directly to and from Object Storage Service (OSS). The app runs on end-user mobile devices, which are considered untrusted client environments.

The solution must meet the following requirements:

  • Direct access to OSS: To reduce latency and server load, the app must communicate directly with OSS instead of proxying traffic through a backend app server.

  • Secure credential management: To mitigate security risks, long-term credentials (AccessKey pairs) must not be embedded in the mobile app.

  • Least-privilege access: To minimize the potential impact of a security breach, each app client must be granted only the permissions necessary to perform its tasks, and only for a limited time.

Solution

This solution uses the token vending machine (TVM) pattern. The mobile app requests STS tokens from a trusted backend app server. The server, acting as a RAM user, calls the AssumeRole API operation of STS to assume a pre-defined RAM role. STS returns an STS token, which the server passes to the mobile app. The app then uses the STS token to sign and send requests directly to OSS.

移动设备应用访问阿里云

  1. The mobile app authenticates with the app server and requests an STS token.

  2. Create a RAM role and attach a policy that grants the required permissions (such as, access to a specific OSS bucket).

  3. Create a RAM user for the app server and grant it permission to assume the RAM role.

  4. The app server calls the AssumeRole operation of STS to obtain an STS token.

  5. (Optional) The app server can pass a session policy in the AssumeRole call to further scope down the permissions of the STS tokens. This allows for fine-grained access control tailored to each user or device.

  6. The mobile app uses the received STS tokens to sign and send requests directly to OSS. For more information, see Use a STS token to access OSS.

Create a RAM role and grant permissions

This section assumes the Alibaba Cloud account ID is 123456789012****.

  1. Create a RAM role named oss-objectmanager. For the principal type, choose Cloud Account.

    Note

    When you create the RAM role, select Current Account as the trusted account. This configures the role's trust policy to allow only principals from within the same Alibaba Cloud account to assume it.

    For more information, see Create a RAM role for a trusted Alibaba Cloud account.

    After the RAM role is created, you can view the following information on its details page:

    • The ARN of the RAM role: acs:ram::123456789012****:role/oss-objectmanager.

    • The trust policy for the RAM role:

      Note

      The Principal in the trust policy specifies which identities are allowed to assume the role. In this case, "acs:ram::123456789012****:root" means any authenticated identity within account 123456789012**** can assume the RAM role, subject to their own RAM policies.

      {
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
              "RAM": [
                "acs:ram::123456789012****:root"
              ]
            }
          }
        ],
        "Version": "1"
      }
  2. Create a policy for the RAM role. For this example, attach the AliyunOSSFullAccess system policy to the oss-objectmanager RAM role.

Create a RAM user and grant it permission to assume a RAM role

  1. Create a RAM user named appserver, which will represent your app server.

  2. Attach the AliyunSTSAssumeRoleAccess system policy to the appserver user to allow it to call the AssumeRole API operation. For more information, see Grant permissions to a RAM user.

Obtain STS tokens

  1. The app server uses the AccessKey pair of the appserver RAM user to call the AssumeRole API operation of STS.

    Note
    • Before using the Alibaba Cloud CLI, you must install and configure it on your app server with the AccessKey pair of the appserver RAM user. For more information, see STS CLI reference.

    • In this example, the Policy parameter is not included in the call. Therefore, the returned STS token has the same permissions that are granted by the oss-objectmanager role's RAM policy. To return STS tokens with more restrictive permissions, see the next section.

    The following example shows how to use Alibaba Cloud CLI to call the AssumeRole operation:

    aliyun sts AssumeRole --RoleArn 'acs:ram::123456789012****:role/oss-objectmanager' --RoleSessionName 'client-001'
  2. STS returns a STS token, which include a temporary AccessKeyId, a AccessKeySecret, and a SecurityToken.

    Sample response:

    {
         "AssumedRoleUser": {
             "AssumedRoleId": "391578752573****:client-001",
             "Arn": "acs:ram::123456789012****:role/oss-objectmanager/client-001"
         }, 
         "Credentials": {
             "AccessKeySecret": "yourAccessKeySecret",
             "SecurityToken": "yourSecurityToken",
             "Expiration": "2016-01-13T15:02:37Z",
             "AccessKeyId": "yourAccessKeyId"
         }, 
         "RequestId": "E1779AAB-E7AF-47D6-A9A4-53128708B6CE"
     }
    Note

    The SecurityToken expires after a specified duration. If the mobile app requires access for longer than the token's lifetime, your application must implement logic to refresh the STS token by requesting a new one from the app server before the old one expires.

Limit the permissions of STS tokens

When you call AssumeRole, you can include the Policy parameter to pass a session policy. This policy scopes down the permissions of the returned STS tokens. The resulting permissions are the intersection of the role's RAM policy and the session policy.

In this example, the session policy grants permission to download the sample-bucket/2015/01/01/*.jpgobject.

  • Sample request

    aliyun sts AssumeRole --RoleArn 'acs:ram::123456789012****:role/oss-objectmanager' --RoleSessionName 'client-002' --Policy '{"Version":"1", "Statement": [{"Effect":"Allow", "Action":"oss:GetObject", "Resource":"acs:oss:*:*:sample-bucket/2015/01/01/*.jpg"}]}'
    Note

    By default, STS tokens are valid for 3,600 seconds (1 hour). You can use the DurationSeconds parameter to specify a shorter or longer duration, up to the maximum session duration configured for the role. For more information, see AssumeRole.

  • Sample response

    {
       "AssumedRoleUser": {
           "AssumedRoleId": "391578752573****:client-002",
           "Arn": "acs:ram::123456789012****:role/oss-objectmanager/client-002"
       },
       "Credentials": {
           "AccessKeySecret": "yourAccessKeySecret",
           "SecurityToken": "yourSecurityToken",
           "Expiration": "2016-01-13T15:03:39Z",
           "AccessKeyId": "yourAccessKeyId"
       }, 
       "RequestId": "98835D9B-86E5-4BB5-A6DF-9D3156ABA567"
    }

Use the STS tokens to access OSS

  1. The app server returns the STS tokens (AccessKey ID, AccessKey secret, and security token) to the mobile app.

  2. The mobile app uses the STS tokens to configure the OSS SDK and make authenticated requests to OSS.

    This example demonstrates how to integrate the OSS Android SDK into an Android app and use an STS token to download an object from OSS to a local device. Sample code:

    // Set the endpoint for the region where your OSS bucket is located. For example, for China (Hangzhou), use https://oss-cn-hangzhou.aliyuncs.com. 
    String endpoint = "yourEndpoint";
    // Set the region where your bucket is located. For example, for China (Hangzhou), use "cn-hangzhou". 
    String region = "yourRegion";
    
    // The AccessKey ID and AccessKey secret obtained from your STS. 
    String accessKeyId = "yourAccessKeyId";
    String accessKeySecret = "yourAccessKeySecret";
    // The security token obtained from STS. 
    String securityToken = "yourSecurityToken";
    
    OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(accessKeyId, accessKeySecret, securityToken);
    ClientConfiguration config = new ClientConfiguration();
    config.setSignVersion(SignVersion.V4);
    // Create the OSSClient instance.
    OSSClient oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider);
    oss.setRegion(region);
    // Initiate the asynchronous object download. 
    GetObjectRequest get = new GetObjectRequest("sample-bucket", "2015/01/01/grass.jpg");
    
    OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
      @Override
      public void onSuccess(GetObjectRequest request, GetObjectResult result) {
        // The request was successful.
        Log.d("asyncGetObject", "DownloadSuccess");
        Log.d("Content-Length", "" + result.getContentLength());
            
        try (InputStream inputStream = result.getObjectContent()) {
          byte[] buffer = new byte[2048];
          int len;
          while ((len = inputStream.read(buffer)) != -1) {
            // Get the input stream from the result and process the downloaded data.
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
      @Override
      // The onFailure callback is triggered when the request fails. 
      public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
        // Handle the request failure. 
        if (clientExcepion != null) {
          // Handle client-side exceptions, such as network errors. 
          clientExcepion.printStackTrace();
        }
        if (serviceException != null) {
          // Handle service-side exceptions from OSS. 
          Log.e("ErrorCode", serviceException.getErrorCode());
          Log.e("RequestId", serviceException.getRequestId());
          Log.e("HostId", serviceException.getHostId());
          Log.e("RawMessage", serviceException.getRawMessage());
        }
      }
    });
    // To cancel the download task, call task.cancel(). 
    // task.cancel(); 
    // To block until the download is finished, call task.waitUntilFinished().
    // task.waitUntilFinished();