iOS:AWSAPIGateWay-缺少身份验证问题

时间:2018-10-30 10:10:33

标签: ios amazon-web-services aws-sdk-ios

几个小时不活动后,该应用程序未成功调用API。

重现行为的步骤:

  1. 创建Amazon Cognito ID。
  2. API调用。
  3. 将应用程序置于后台。
  4. 8小时后刷新代码。 (以下提到的initializeAmazonCongnitoProviderWithCompletionBlock会在应用程序仅在8小时后才进入前台时首先调用) 缺少身份验证令牌将按照屏幕快照中的建议显示。 哪些AWS服务受到影响?

enter image description here

- (void)initializeAmazonCognitoProviderWithCompletionBlock:(void (^)(void))completion { 
    [[UIApplication sharedApplication].keyWindow setUserInteractionEnabled:FALSE];
    NSString* AWSCognitoPoolID = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"AWSCognitoID"];
    AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]  initWithRegionType:AMAZON_COGNITO_REGION identityPoolId:AWSCognitoPoolID];
    [credentialsProvider clearCredentials];
    AWSServiceConfiguration *configuration =[[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1  credentialsProvider:credentialsProvider];
    AWSServiceManager.defaultServiceManager.defaultServiceConfiguration =  configuration;

    [self getCognitoID:credentialsProvider CompletionBlock:^{
        [self expirationHandler:credentialsProvider CompletionBlock:^{
            dispatch_async(dispatch_get_main_queue(), ^{
              [[UIApplication sharedApplication].keyWindow setUserInteractionEnabled:TRUE];
            });
            completion();
        }];
    }]; 
}


- (void)expirationHandler:(AWSCognitoCredentialsProvider *)creds CompletionBlock: (void (^)(void))completion {
    [[creds credentials] continueWithBlock:^id(AWSTask *task) {
        if (task.error) {
            [self initializeAmazonCognitoProviderWithCompletionBlock:^{}];
        } else {
            AWSCredentials *cred = (AWSCredentials*) task.result;
            NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
            [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
            /* https://aws.amazon.com/premiumsupport/knowledge-center/security-token-expired/
             https://forums.aws.amazon.com/thread.jspa?threadID=166398
             We should fire timer before 5 minutes of expiration.
             NSString *expF = [dateFormat stringFromDate:cred.expiration];
             */
            [NSTimer scheduledTimerWithTimeInterval:cred.expiration.timeIntervalSinceNow -  300 target:self selector:@selector(initializeAmazonCognitoProviderWithCompletionBlock:) userInfo:nil repeats:NO];
            completion();
        }
        return nil;
    }];
}


- (void)getCognitoID:(AWSCognitoCredentialsProvider *)creds CompletionBlock: (void (^)(void))completion {
    [[creds getIdentityId] continueWithBlock:^id(AWSTask *task) {
        if (task.error) {
            NSLog(@"Error: %@", task.error);
            [self initializeAmazonCognitoProviderWithCompletionBlock:^{}];
        } else {
            NSString *cognitoId = task.result;
            NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
            if (![[standardDefaults valueForKey:@"UserCognitoID"] isEqualToString:cognitoId]) {
                [standardDefaults setObject:@"" forKey:BainPreferenceToken];
                [standardDefaults setInteger:0 forKey:@"registrationPostComplete"];
            }
            [standardDefaults setObject:cognitoId forKey:@"UserCognitoID"];
            [standardDefaults synchronize];
            completion();
        }
        return nil;
    }];
}

1 个答案:

答案 0 :(得分:0)

AWSCognitoCredentialsProvider是一个对象,该对象从Amazon Cognito检索凭证并提供凭证以将请求签名到AWS(例如,将文件上传到S3)。

SDK中的

AWSCognitoIdentityProvider对象为Amazon Cognito UserPools提供了抽象,并帮助您登录用户并检索证明该用户已通过身份验证的令牌。

当用户登录并且AWSCognitoIdentityProvider已从Amazon Cognito UserPools检索到令牌后,可以将令牌联合到AWSCognitoCredentialsProvider中,以便为该经过身份验证的用户检索AWSCredentials和Cognito身份ID 。为此,您需要在登录映射中提供令牌,并将登录映射传递到AWSCognitoCredentialsProvider

要实现此目的,您需要

1)创建一个确认AWSIdentityProviderManager协议的类,并实现logins方法,该方法返回{providerLoginKey-> token}的映射。

@interface AWSFederationManager : NSObject<AWSIdentityProviderManager>

@property (nonatomic, readonly, strong) AWSCognitoCredentialsProvider *credentialsProvider;

@end
@interface AWSFederationManager()

@property (nonatomic, readwrite, strong) AWSCognitoCredentialsProvider *credentialsProvider;

@end
@implementation AWSFederationManager

- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins {
        return [AWSTask taskWithResult:@{[<identityProviderName> : <token>}];
}

@end

2)将AWSCognitoCredentialsProvider对象的委托设置为在步骤(1)中创建的类。

@implementation AWSFederationManager

- (instancetype) initialize {
    [self.credentialsProvider setIdentityProviderManagerOnce:self];
}

@end

现在,联合身份验证成功后,您将能够检索AWSCredentials和Cognito身份ID。

您可以参考Source以获得参考实现。