Access control

Last Updated: Sep 30, 2017

A mobile terminal is an untrusted environment. There is a high risk if you store the AccessKeyId and AccessKeySecret in a local mobile terminal for signing requests. The SDK provides the STS authentication mode and self-signed mode.

STS authentication mode

Introduction

OSS can temporarily grant authorization for access through the Alibaba Cloud STS service. Alibaba Cloud STS (Security Token Service) is a web service that provides a temporary access token to a cloud computing user.

Through the STS, you can assign a third-party application or federated user (you can manage the user ID) an access credential with a custom validity period and permissions. The access credential is called FederationToken on the app side.

Third-party applications or federated users can use these access credentials to directly call the Alibaba Cloud product APIs or use the SDKs provided by Alibaba Cloud products to access the cloud product APIs.

  • You do not need to expose your long-term key (AccessKey) to a third-party application. You only need to generate an access token and send the access token to the third-party application. You can customize the access permission and validity of this token.
  • You do not need to worry about permission revocation issues. The access token automatically becomes invalid when it expires.

Taking an app as an example, the interaction process is shown in the following figure:

The solution is detailed as follows:

  1. Log on as the app user. App user IDs are managed by the customer. The customer can customize the ID management system or use an external web account or OpenID. For each valid app user, the AppServer can precisely define the minimum access permission.
  2. The AppServer requests a security token (SecurityToken) from the STS. Before calling STS, the AppServer needs to determine the minimum access permission (described in policy syntax) of the app user and the expiration time of the authorization.Then you can obtain the security token by calling the STS’ AssumeRole interface. For details about role management and usage, see Role Management in the RAM User Guide.
  3. The STS returns a valid access credential (called FederationToken on the app side) to the AppServer. The access credential contains a security token, a temporary pair of access keys (an AccessKeyID and an AccessKeySecret), and the expiration time.
  4. The AppServer returns the FederationToken to the ClientApp. The ClientApp can cache this credential. When the credential becomes invalid, the ClientApp needs to request a new valid access credential from the AppServer. For example, if the access credential is valid for one hour, the ClientApp can request the AppServer to update the access credential every 30 minutes.
  5. The ClientApp uses the locally cached FederationToken to request Alibaba Cloud Service APIs. The cloud service perceives the STS access credential, relies on STS to verify the credential, and responds to the user request correctly.

For details about STS security tokens, see Role Management in the RAM User Guide. The key is to call the STS interface AssumeRole to obtain valid access credential. You can also directly use STS SDK to call this method. Click to view details.

To use this authentication mode, you need to first activate Alibaba Cloud RAM service.

STS user manual: Click to view

OSS authentication policy configuration: Click to view

Practical guide: Click to view

Set StsToken directly

You can get a pair of StsToken in the app via a method (such as from your business server through network requests) and then use it to initialize the SDK. If this method is adopted, you must pay particular attention to the expiration time of the StsToken. When the StsToken is about to expire, you need to take initiative to update the new StsToken to the SDK.

The initial code is:

  1. id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:@"<StsToken.AccessKeyId>" secretKeyId:@"<StsToken.SecretKeyId>" securityToken:@"<StsToken.SecurityToken>"];
  2. client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];

When you see that the Token is about to expire, you can rebuild a new OSSClient, or update the CredentialProvider via the following method:

  1. client.credentialProvider = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:@"<StsToken.AccessKeyId>" secretKeyId:@"<StsToken.SecretKeyId>" securityToken:@"<StsToken.SecurityToken>"];

Implement the callback to get the StsToken

If you want the SDK to automatically help you manage Token updates, you should tell the SDK how to get the token. In the SDK’s app, you need to implement a callback which gets a FederationToken (that is, StsToken) and returns the token. The SDK will use the Token for signing. When the token needs to be updated, the SDK will call the callback to get the token, as shown in the figure:

  1. id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
  2. // Here you need to implement a method to get a FederationToken and construct it into the OSSFederationToken object to return it
  3. // If the token fails to be obtained, "nil" is returned directly
  4. OSSFederationToken * token;
  5. // The following code obtains the token, from your server for example
  6. ...
  7. return token;
  8. }];
  9. client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];

Note: If you have obtained all the fields required by the token by other means, you can use the callback to directly return the token. In this case, you need to manually update the token and then re-set the OSSCredentialProvider of the OSSClient instance.

Example:

Suppose the URL of the server you set up is http://localhost:8080/distribute-token.json. The following data will be returned after the address is accessed:

  1. {"accessKeyId":"STS.iA645eTOXEqP3cg3VeHf",
  2. "accessKeySecret":"rV3VQrpFQ4BsyHSAvi5NVLpPIVffDJv4LojUBZCf",
  3. "expiration":"2015-11-03T09:52:59Z",
  4. "federatedUser":"335450541522398178:alice-001",
  5. "requestId":"C0E01B94-332E-4582-87F9-B857C807EE52",
  6. "securityToken":"CAES7QIIARKAAZPlqaN9ILiQZPS+JDkS/GSZN45RLx4YS/p3OgaUC+oJl3XSlbJ7StKpQ....“}

You can use the following code to implement the OSSFederationCredentialProvider instance:

  1. id<OSSCredentialProvider> credential2 = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
  2. // Construct a request to access your business server
  3. NSURL * url = [NSURL URLWithString:@"http://localhost:8080/distribute-token.json"];
  4. NSURLRequest * request = [NSURLRequest requestWithURL:url];
  5. OSSTaskCompletionSource * tcs = [OSSTaskCompletionSource taskCompletionSource];
  6. NSURLSession * session = [NSURLSession sharedSession];
  7. // Send the request
  8. NSURLSessionTask * sessionTask = [session dataTaskWithRequest:request
  9. completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  10. if (error) {
  11. [tcs setError:error];
  12. return;
  13. }
  14. [tcs setResult:data];
  15. }];
  16. [sessionTask resume];
  17. // You need to block other requests and wait for the response of the request
  18. [tcs.task waitUntilFinished];
  19. // Resolve the result
  20. if (tcs.task.error) {
  21. NSLog(@"get token error: %@", tcs.task.error);
  22. return nil;
  23. } else {
  24. // The returned data is in the JSON format and you need to resolve it to obtain all fields of the token
  25. NSDictionary * object = [NSJSONSerialization JSONObjectWithData:tcs.task.result
  26. options:kNilOptions
  27. error:nil];
  28. OSSFederationToken * token = [OSSFederationToken new];
  29. token.tAccessKey = [object objectForKey:@"accessKeyId"];
  30. token.tSecretKey = [object objectForKey:@"accessKeySecret"];
  31. token.tToken = [object objectForKey:@"securityToken"];
  32. token.expirationTimeInGMTFormat = [object objectForKey:@"expiration"];
  33. NSLog(@"get token: %@", token);
  34. return token;
  35. }
  36. }];

Self-signed mode

  1. id<OSSCredentialProvider> credential = [[OSSCustomSignerCredentialProvider alloc] initWithImplementedSigner:^NSString *(NSString *contentToSign, NSError *__autoreleasing *error) {
  2. // Here you need to sign a character string using the OSS-specified signature algorithm, merge the AccessKeyID with the signed string, and return the string
  3. // A typical implementation method is to post the character string to your business server and then return the signature
  4. // If the signing fails for some reason, "nil" will be returned after the error is described
  5. NSString *signature = [OSSUtil calBase64Sha1WithData:contentToSign withSecret:@"<your accessKeySecret>"]; // Use a utility function of the SDK for the local signing. It is recommended that you implement remote signing through the business server
  6. if (signature != nil) {
  7. *error = nil;
  8. } else {
  9. *error = [NSError errorWithDomain:@"<your domain>" code:-1001 userInfo:@"<your error info>"];
  10. return nil;
  11. }
  12. return [NSString stringWithFormat:@"OSS %@:%@", @"<your accessKeyId>", signature];
  13. }];
  14. client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];

Note: For STS authentication mode and self-signed mode, you should ensure that the results will be returned at the time that you call the implemented callback function. We recommend that you call the synchronous interface of the network library or perform asynchronous-to-synchronous conversion to send a network request to the business server in order to obtain the token and signature. In the SDK, callback is executed in the subthread of the specific request, which does not block the main thread.

Thank you! We've received your feedback.