All Products
Search
Document Center

Object Storage Service:Authorize access by using OSS SDK for iOS

Last Updated:Jun 13, 2024

Object Storage Service (OSS) SDK for iOS provides the Security Token Service (STS) authentication mode, self-signed mode, and signed URLs to ensure data security of mobile devices.

Usage notes

When you use the STS authentication mode or self-signed mode, make sure that the callback function that you use can return the security token and signature. If you must obtain the token and signature from the app server by sending a request in the callback function, we recommend that you call the synchronous API operations included in the network library. The callback function runs in the child thread of the request generated by the SDK and does not block the main thread.

STS authentication mode

To access OSS by using temporary access credentials provided by STS, perform the following operations:

  1. Obtain temporary access credentials.

    Temporary access credentials include a security token and a temporary AccessKey pair. The temporary AccessKey pair consists of an AccessKey ID and an AccessKey secret. The validity period of temporary access credentials is in seconds. The minimum validity period of temporary access credentials is 900 seconds. The maximum validity period of temporary access credentials is the maximum session duration specified for the current role. For more information, see Specify the maximum session duration for a RAM role.

    You can use one of the following methods to obtain temporary access credentials:

    • Method 1:

      Call the AssumeRole operation to obtain temporary access credentials.

    • Method 2

      Use STS SDKs to obtain temporary access credentials. For more information, see STS SDK overview.

  2. Use temporary access credentials to initialize OSS SDK for iOS.

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

    To use OSSAuthCredentialProvider to initialize OSS SDK for iOS, see Initialization.

    When you initialize the SDK by using temporary access credentials, take note of the validity period of the security token. The following sample code provides an example on how to determine the validity period of an security token:

    NSDateFormatter * fm = [NSDateFormatter new];
    fm.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    [fm setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
    NSDate *expirationDate = [fm dateFromString:@"<StsToken.Expiration>"];
    NSTimeInterval interval = [expirationDate timeIntervalSinceDate:[NSDate date]];
    // The security token is about to expire within less than five minutes. 
    if (interval < 5 * 60) {
        id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:@"<StsToken.AccessKeyId>" secretKeyId:@"<StsToken.SecretKeyId>" securityToken:@"<StsToken.SecurityToken>"];
        client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];
    }
    • Manually update the security token

      When the security token is about to expire, you can create a new OSSClient instance or update CredentialProvider by using the following method:

      id<OSSCredentialProvider> credential = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:@"<StsToken.AccessKeyId>" secretKeyId:@"<StsToken.SecretKeyId>" securityToken:@"<StsToken.SecurityToken>"];
      client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];
    • Automatically update the security token

      If you want the SDK to automatically update the security token, you must configure a callback function in your app. The callback fuction obtains a federation token (security token) and returns the token to the SDK. The SDK uses the security token to generate signatures. When the security token needs to be updated, the SDK calls the callback function to obtain a new token.

      id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
          // Obtain a federation token and return it in an OSSFederationToken object. 
          // If the federation token is not obtained, nil is returned. 
            OSSFederationToken * token;
          // Obtain a federation token from your server. 
          ...
          return token;
      }];
      client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];
      Note

      If you obtain all fields that are required to generate an security token by using other methods, you can directly return the token in the callback. In this case, you must manually update the token, and then reconfigure OSSCredentialProvider of the OSSClient instance.

      If the URL of the server from which you request a token is http://localhost:8080/distribute-token.json, the following data is returned:

      {
          "StatusCode": 200,
          "AccessKeyId":"STS.iA645eTOXEqP3cg3****",
          "AccessKeySecret":"rV3VQrpFQ4BsyHSAvi5NVLpPIVffDJv4LojU****",
          "Expiration":"2015-11-03T09:52:59Z",
          "SecurityToken":"CAES7QIIARKAAZPlqaN9ILiQZPS+JDkS/GSZN45RLx4YS/p3OgaUC+oJl3XSlbJ7StKpQ****"
      }                           

      The following sample code provides an example on how to implement OSSFederationCredentialProvider:

      id<OSSCredentialProvider> credential2 = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
          // Create a request to access your service server. 
          NSURL * url = [NSURL URLWithString:@"http://localhost:8080/distribute-token.json"];
          // Use a request to set the parameters required by your server. 
          NSURLRequest * request = [NSURLRequest requestWithURL:url];
          OSSTaskCompletionSource * tcs = [OSSTaskCompletionSource taskCompletionSource];
          NSURLSession * session = [NSURLSession sharedSession];
          // Send the request. 
          NSURLSessionTask * sessionTask = [session dataTaskWithRequest:request
                                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                          if (error) {
                                                              [tcs setError:error];
                                                              return;
                                                          }
                                                          [tcs setResult:data];
                                                      }];
          [sessionTask resume];
          // Wait until the response to the request is returned. 
          [tcs.task waitUntilFinished];
          // Parse the returned results. 
          if (tcs.task.error) {
              NSLog(@"get token error: %@", tcs.task.error);
              return nil;
          } else {
              // The returned data is in the JSON format. Parse the data to obtain the values of the fields of the token. 
              NSDictionary * object = [NSJSONSerialization JSONObjectWithData:tcs.task.result
                                                                      options:kNilOptions
                                                                        error:nil];
              OSSFederationToken * token = [OSSFederationToken new];
              token.tAccessKey = [object objectForKey:@"AccessKeyId"];
              token.tSecretKey = [object objectForKey:@"AccessKeySecret"];
              token.tToken = [object objectForKey:@"SecurityToken"];
              token.expirationTimeInGMTFormat = [object objectForKey:@"Expiration"];
              NSLog(@"get token: %@", token);
              return token;
          }
      }];

Self-signed mode

You can perform the following operations to save the AccessKey ID and AccessKey secret to your own server and then sign the client information on your server:

  1. Obtain the string-to-sign from the client and send the string to your own server.

    1. Use the signContent method of OSSCustomSignerCredentialProvider provided by OSS SDK for iOS to obtain the string-to-sign when you create the request.

    2. Send the string-to-sign to your own server.

  2. Sign the string on your own server and return the signed string to the client.

    1. Use the specified signature algorithm to sign the string. For more information about the signature algorithm, see Include a V1 signature in the Authorization header.

      The V1 signature algorithm follows the signature = "OSS " + AccessKeyId + ":" + base64(hmac-sha1(AccessKeySecret, content)) format, in which content is the string that is created based on concatenation of request parameters. Sample code:

      id<OSSCredentialProvider> credential = [[OSSCustomSignerCredentialProvider alloc] initWithImplementedSigner:^NSString *(NSString *contentToSign, NSError *__autoreleasing *error) {
          // Use the specified signature algorithm to sign a string, concatenate your AccessKey ID to the signed string, and then return the final string. 
          // Send the signed string to your own server and return the signature. 
          // If the string fails to be signed, the server returns nil with an error message. 
      NSString *signature = [OSSUtil calBase64Sha1WithData:contentToSign withSecret:@"<your accessKeySecret>"]; // In this example, the string is signed on the client by using the tool provided by OSS SDK for iOS. We recommend that you sign the string on your business server. 
          if (signature != nil) {
              *error = nil;
          } else {
              *error = [NSError errorWithDomain:@"<your domain>" code:-1001 userInfo:@"<your error info>"];
              return nil;
          }
          return [NSString stringWithFormat:@"OSS %@:%@", @"<your accessKeyId>", signature];
      }];
      
      client = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credential];
                  
    2. Return the signed string to the client.

  3. Send the signed string on the client to the OSS server for authentication.

Signed URLs

Usage notes

  • When you use an OSS SDK to generate a signed URL, the OSS SDK uses a specific algorithm based on the key information stored in the local computer to calculate a signature and adds the signature to a URL to ensure the validity and security of the URL. The operations performed to calculate and construct the URL are completed on the client. You do not need to send requests to the server over the network. This way, you do not need to grant specific permissions to the caller when you generate the signed URL. However, to allow third-party users to perform relevant operations on the resources authorized by the signed URL, you must make sure that the principal that calls the API operations to generate the signed URL has the corresponding permissions.

    For example, if a principal wants to upload an object by using a signed URL, you must grant the oss:PutObject permission to the principal. If a principal wants to download or preview an object by using a signed URL, you must grant the oss:GetObject permission to the principal.

  • The signed URL generated by using the following sample code may contain a plus sign (+). In this case, replace the plus sign (+) in the URL with %2B. Otherwise, the signed URL may not be used to access the object as expected.

Use a signed URL to upload an object

  1. Generate a signed URL.

    // Specify the name of the bucket. 
    NSString *bucketName = @"examplebucket";
    // Specify the name of the object. 
    NSString *objectKey = @"exampleobject.txt";
    NSURL *file = [NSURL fileURLWithPath:@"<filePath>"];
    NSString *contentType = [OSSUtil detemineMimeTypeForFilePath:file.absoluteString uploadName:objectKey];
    __block NSString *urlString;
    // Generate a signed URL with a specified validity period for uploading the object. In this example, the validity period of the URL is 30 minutes. 
    OSSTask *task = [client presignConstrainURLWithBucketName:bucketName
                                                withObjectKey:objectKey
                                                   httpMethod:@"PUT"
                                       withExpirationInterval:30 * 60
                                               withParameters:@{}
                                                  contentType:contentType
                                                   contentMd5:nil];
    [task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
        if (task.error) {
            NSLog(@"presign error: %@", task.error);
        } else {
            urlString = task.result;
            NSLog(@"url: %@", urlString);
        }
        return nil;
    }];
  2. Use a signed URL to upload the object.

    // Upload the object by using a signed URL. 
    NSURL * url = [NSURL URLWithString:urlString];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"PUT";
    request.allHTTPHeaderFields = @{OSSHttpHeaderContentType: contentType};
    NSURLSession * session = [NSURLSession sharedSession];
    NSURLSessionTask * sessionTask = [session uploadTaskWithRequest:request
                                                           fromFile:file
                                                  completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"upload error: %@", error);
            return;
        } else if (((NSHTTPURLResponse*)response).statusCode == 203 ||
                   ((NSHTTPURLResponse*)response).statusCode >= 300) {
            NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"upload error: %@", body);
            return;
        }
        NSLog(@"upload success");
    }];
    [sessionTask resume];

Use a signed URL to download an object

  1. Generate a signed URL.

    // Specify the name of the bucket. 
    NSString *bucketName = @"examplebucket";
    // Specify the name of the object. 
    NSString *objectKey = @"exampleobject.txt";
    __block NSString *urlString;
    // Generate a signed URL with a specified validity period for downloading the object. In this example, the validity period of the URL is 30 minutes. 
    OSSTask *task = [client presignConstrainURLWithBucketName:bucketName
                                                withObjectKey:objectKey
                                                   httpMethod:@"GET"
                                       withExpirationInterval:30 * 60
                                               withParameters:@{}];
    [task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
        if (task.error) {
            NSLog(@"presign error: %@", task.error);
        } else {
            urlString = task.result;
            NSLog(@"url: %@", urlString);
        }
        return nil;
    }];
  2. Use the signed URL to download the object.

    // Use the signed URL to download the object. 
    NSURL * url = [NSURL URLWithString:urlString];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    NSURLSession * session = [NSURLSession sharedSession];
    NSURLSessionTask * sessionTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"download error: %@", error);
            return;
        } else if (((NSHTTPURLResponse*)response).statusCode == 203 ||
                   ((NSHTTPURLResponse*)response).statusCode >= 300) {
            NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"download error: %@", body);
            return;
        }
        NSLog(@"download success");
    }];
    [sessionTask resume];