A mobile app can use an STS token of a RAM role to securely access Alibaba Cloud resources without embedding long-term credentials.
Background information
A company develops a mobile app that uses Object Storage Service (OSS). The app must directly connect to OSS to upload or download data, but it runs on end-user mobile devices that the company does not control.
The company has the following requirements:
-
Direct data transfer: The company wants the app to connect directly to OSS for uploads and downloads, rather than proxying data through its backend application server.
-
Secure credential management: The company must avoid embedding long-term credentials, such as an AccessKey, in the mobile app. End-user devices are untrusted runtime environments.
-
Risk control: To follow the principle of least privilege, each app must have minimal permissions and a short-lived session when connecting to OSS.
Solution
When the mobile app needs to upload or download data from OSS, it requests credentials from an application server. The application server, as a RAM user, assumes a RAM role by calling the STS AssumeRole operation and passes the returned STS token to the app, which uses it to access OSS.

-
The app requests credentials from the application server.
-
Create a RAM role and grant it the required permissions.
For more information, see Create a RAM role and grant permissions .
-
Create a RAM user for the application server and allow the RAM user to assume the RAM role.
For more information, see Create a RAM user and allow the user to assume a RAM role .
-
The application server calls the STS AssumeRole operation to obtain an STS token for the RAM role.
For more information, see Obtaining an STS token on the application server .
-
The application server can further restrict the permissions of the STS token for finer-grained control over each app client.
For more information, see Limit the permissions of an STS token .
-
When the app needs to directly upload or download data, it uses the STS token to access OSS.
For more information, see Use an STS token to access OSS from the app .
Create a RAM role and grant permissions
Assume that the ID of your Alibaba Cloud account is 123456789012****.
-
Use your Alibaba Cloud account to create a RAM role named
oss-objectmanagerand select Cloud Account as the principal type.NoteWhen you create the RAM role, select Current Account as the trusted principal. This allows only RAM users that belong to the same Alibaba Cloud account to assume this RAM role.
For more information, see Create a RAM role for an Alibaba Cloud account.
After the RAM role is created, you can view its ARN and trust policy on the role details page.
-
The ARN of the RAM role is
acs:ram::123456789012****:role/oss-objectmanager. -
The trust policy of the RAM role is as follows.
NoteThe following trust policy allows any authenticated principal within Alibaba Cloud account
123456789012****to assume the role.{ "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "RAM": [ "acs:ram::123456789012****:root" ] } } ], "Version": "1" }
-
-
Attach the
AliyunOSSFullAccesssystem policy to theoss-objectmanagerRAM role.For more information, see Grant permissions to a RAM role.
Create a RAM user and allow role assumption
-
Create a RAM user named
appserverfor the application server.For more information, see Create a RAM user.
-
Grant the
AliyunSTSAssumeRoleAccesspermission to theappserverRAM user to allow the user to assume roles.For more information, see Grant permissions to a RAM user.
Obtain an STS token
-
The application server uses the RAM user's AccessKey to call the STS AssumeRole operation.
Note-
Before you use Alibaba Cloud Command Line Interface (CLI), you must install it on your application server and configure it with the RAM user's credentials. For more information, see STS CLI reference.
-
In this example, the
Policyparameter is not specified. Therefore, the returned STS token inherits all permissions from theoss-objectmanagerRAM role. To further restrict the permissions of the STS token, see Limit the permissions of an STS token.
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' -
-
STS returns an STS token to the application server. The STS token includes an
AccessKeyId, anAccessKeySecret, and aSecurityToken.The following code provides a 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" }NoteThe
SecurityTokenhas a short expiration time. If a longer session is required, the application server must re-issue the STS token periodically, for example, every 1800 seconds.
Limit STS token permissions
You can use the Policy parameter in the AssumeRole call to restrict the permissions of an STS token based on the user or device, reducing the risk of privilege escalation.
The following example grants permission to download objects that match the sample-bucket/2015/01/01/*.jpg path.
-
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"}]}'NoteThe default expiration time for an STS token is 3,600 seconds. You can set a different expiration time by using the
DurationSecondsparameter. 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 an STS token to access OSS
-
The application server passes the STS token to the mobile app.
-
The mobile app uses the STS token to access OSS.
The following example uses the OSS Android SDK to download a file from OSS with an STS token.
// Replace yourEndpoint with the endpoint of the region where your bucket is located. For example, for the China (Hangzhou) region, the endpoint is https://oss-cn-hangzhou.aliyuncs.com. String endpoint = "yourEndpoint"; // Replace yourRegion with the ID of the region where your bucket is located. For example, for the China (Hangzhou) region, the region ID is cn-hangzhou. String region = "yourRegion"; // The temporary AccessKey ID and AccessKey Secret obtained from 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 an OSSClient instance. OSSClient oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider); oss.setRegion(region); // Construct a download request. GetObjectRequest get = new GetObjectRequest("sample-bucket", "2015/01/01/grass.jpg"); OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() { @Override // On success, the GetObject request returns a GetObjectResult containing an input stream. You must process the stream. public void onSuccess(GetObjectRequest request, GetObjectResult result) { // The request is 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) { // Process the data. } } catch (IOException e) { e.printStackTrace(); } } @Override // The onFailure callback is triggered if the request fails. Handle the exception. public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) { if (clientExcepion != null) { // Handle client-side exceptions, such as network errors. clientExcepion.printStackTrace(); } if (serviceException != null) { // Handle service-side exceptions. Log.e("ErrorCode", serviceException.getErrorCode()); Log.e("RequestId", serviceException.getRequestId()); Log.e("HostId", serviceException.getHostId()); Log.e("RawMessage", serviceException.getRawMessage()); } } }); // Cancel the task. // task.cancel(); // Wait for the task to complete. // task.waitUntilFinished();