2016-12-27 22 views
1

我已经使用AWS API Gateway部署了一个API,并试图通过iOS设备访问它。有些终端支持未经授权的用户,我无法访问它们,但其他终端则不支持查询它们。我使用新的Cognito用户池功能进行身份验证,在使用Web应用程序(或邮递员)时可以正常工作。首先,即使一些端点受到保护(如下面的控制台图片所示),当我部署API并为iOS生成SDK(Objective-C)时,我可以在README文件中读取: “所有端点都不需要授权。”API网关为授权用户生成的iOS iOS(Objective-C)SDK with Cognito用户池

enter image description here

然后,当我运行从AWS文档下面的验证码,似乎一切就好了工作:

AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionEUWest1 credentialsProvider:nil]; 
AWSCognitoIdentityUserPoolConfiguration *userPoolConfiguration = [[AWSCognitoIdentityUserPoolConfiguration alloc] initWithClientId:ClientId clientSecret:nil poolId:UserPoolId]; 
[AWSCognitoIdentityUserPool registerCognitoIdentityUserPoolWithConfiguration:serviceConfiguration userPoolConfiguration:userPoolConfiguration forKey:@"UserPool"]; 
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:@"UserPool"]; 

AWSCognitoIdentityUser *user = [pool getUser]; 
[[user getSession:username password:password validationData:nil] continueWithBlock:^id(AWSTask<AWSCognitoIdentityUserSession *> *task) { 
    if (task.error) { 
     NSLog(@"Could not get user session. Error: %@", task.error); 
    } else if (task.exception) { 
     NSLog(@"Could not get user session. Exception: %@", task.exception); 
    } else { 
     NSLog(@"Successfully retrieved user session data"); 
     AWSCognitoIdentityUserSession *session = (AWSCognitoIdentityUserSession *) task.result; 

     NSMutableString *poolId = [[NSMutableString alloc] initWithString:@"cognito-idp.eu-west-1.amazonaws.com/"]; 
     [poolId appendString:UserPoolId]; 
     NSString *tokenStr = [session.idToken tokenString]; 
     NSDictionary *tokens = [[NSDictionary alloc] initWithObjectsAndKeys:tokenStr, poolId, nil]; 



     CognitoPoolIdentityProvider *idProvider = [[CognitoPoolIdentityProvider alloc] init]; 
     [idProvider addTokens:tokens]; 

     AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionEUWest1 identityPoolId:IdentityPoolId identityProviderManager:idProvider]; 

     [credentialsProvider clearKeychain]; 
     [credentialsProvider clearCredentials]; 

     AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionEUWest1 
                              credentialsProvider:credentialsProvider]; 

     [[credentialsProvider getIdentityId] continueWithBlock:^id _Nullable(AWSTask<NSString *> * _Nonnull task) { 
      if (task.error) { 
       NSLog(@"Could not get identity id: %@", task.error); 
      } else if (task.exception) { 
       NSLog(@"Could not get identity id: %@", task.exception); 
      } else { 
       NSLog(@"Identity id: %@", task.result); 
      } 

      return nil; 
     }]; 
    } 

    return nil; 
}]; 

我实现CognitoPoolIdentityProvider为this post规定。

@interface CognitoPoolIdentityProvider() 
@property (strong, nonatomic) NSDictionary *tokens; 
@end 

@implementation CognitoPoolIdentityProvider 

    - (AWSTask<NSDictionary *> *)logins { 
     return [AWSTask taskWithResult:self.tokens]; 
    } 

    - (void)addTokens:(NSDictionary *)tokens { 
     self.tokens = tokens; 
    } 

@end 

我设法得到一个正确的令牌(测试使用邮递员)和用户ID:

2016-12-27 12:43:35.760 AskHub[26625:10037234] AWSiOSSDK v2.4.11 [Debug] AWSURLResponseSerialization.m line:63 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: {"IdentityId":"eu-west-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"} 2016-12-27 12:43:35.766 AskHub[26625:10037234] Identity id: eu-west-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

然而,当我运行下面的代码打一个受保护的端点,CloudFront的认为,我未认证。

APIHealthClient *apiClient = [APIHealthClient defaultClient]; 
APIAskHubRequest *initReq = [[APIAskHubRequest alloc] init]; 
initReq.message = @"FIN"; 

NSLog(@"Sending initial request"); 
[[apiClient webhooksAskhubPost:initReq] continueWithBlock:^id(AWSTask *task) { 
    if (task.error) { 
     NSLog(@"Could not send initial request: %@", task.error); 
    } else if (task.exception) { 
     NSLog(@"Could not send initial request: %@", task.exception); 
    } else { 
     NSLog(@"Successfully sent initial request"); 
    } 

    return nil; 
}]; 

的回复:

2016-12-27 12:56:25.247 AskHub[26784:10046562] Could not send initial request: Error Domain=com.amazonaws.AWSAPIGatewayErrorDomain Code=1 "(null)" UserInfo={HTTPBody={ message = Unauthorized; }, HTTPHeaderFields={type = immutable dict, count = 9, entries => 3 : Via = {contents = "X.X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.cloudfront.net (CloudFront)"} 4 : x-amzn-ErrorType = {contents = "UnauthorizedException"} 5 : Content-Type = {contents = "application/json"} 6 : Content-Length = {contents = "27"} 7 : Connection = {contents = "keep-alive"} 8 : x-amzn-RequestId = {contents = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"} 9 : Date = {contents = "Tue, 27 Dec 2016 11:56:25 GMT"} 10 : X-Cache = {contents = "Error from cloudfront"} 11 : X-Amz-Cf-Id = {contents = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"} } }

我在这里失去了一些东西?自动生成的SDK是否支持用户池身份验证?

+0

我有同样的问题,你有...我有一个通过我的cognito用户池授权的api。当我通过邮递员调用这个api并在用户池中传入一个来自用户的有效的id令牌的“Authorization”头时,它就可以工作。但是,当我尝试通过生成的api ios sdk通过ios调用相同的api时,我得到相同的错误。我的猜测是,ios中还有一件事尚未安装?如果我找到它,我会继续沿着它回到这里。 –

回答

1

我发现在两种身份验证模式之间存在混淆:使用凭证提供程序或仅将JWT标记添加到“授权”标头参数中(或者您创建自定义参数名称授权人)。

第一种方法对我不起作用,即使它是我在文档中找到的唯一一个涉及到使用iOS SDK的方法。第二种方法工作得很好,但为了能够在不侵入SDK的情况下使用它,不要忘记在API网关中指定API时添加“授权”标头。

1

根据我看到的代码,您正在清除凭据,但从来没有获得凭据。快速审查它看起来像你正确设置服务配置和身份验证,但你永远不会调用凭据。

如果是这样,即使您的应用程序将进行身份验证,凭据提供程序也永远不会获取登录字典。

(您可以在AWS控制台中验证这一点,如果您查看要用来访问资源的identityId,可以查看“登录”计数。如果为0,则表示您未登录)

为了进行身份验证,您需要让凭证提供程序调用您的identityProviderManager“登录”方法。

当您执行SDK中“凭据”的“getCredentialsForIdentity”时会发生此调用。

通常,序列是GetID,然后是GetCredentialsForId。在IOS SDK中,GetId发生在“getSession”(所以你应该拥有它),并且GetCredentials与“凭据”发生

(请注意,每个SDK中有不同的命名(Mobile Hub vs IOS SDK例如),但重要的是您的凭证提供程序会获取登录字典。使用详细日志记录您应该实际看到记录的“登录”字典,这将向您证明登录字典正在提供给凭证提供程序)。

+0

感谢您精确的事情。我试图调用“凭据”,它似乎工作,因为我能够记录AccessKey,SecretKey和SessionKey。然而,当我设置defaultServiceConfiguration后(使用新的credentialsProvider),然后我调用API,我仍然得到一个UnauthorizedException ... –

+0

你在日志文件中获得登录字典吗?像这样:“X-Amz-Target”=“AWSCognitoIdentityService.GetCredentialsForIdentity”; } 2016-12-27 17:09:30.736 KeyCode [3004:122424] AWSiOSSDK v2.4.14 [Debug] AWSURLSessionManager.m line:555 | - [AWSURLSessionManager printHTTPHeadersAndBodyForRequest:] |请求正文: {“Logins”:{“cognito-idp.us-east-1.amazonaws.com \/us-east-1_xxxxxxxxx”:“eyJraWQixxxxxxxxxx long long coded tokenxxxxxj3f2QzWX5o8AVdtDPA”},“IdentityId”:“us-east -1:“} – Bruce0

+0

您是否在aws控制台中为有问题的identityId获得大于0的登录? – Bruce0

相关问题