0

總體問題: 我的前端(iOS)使用開發人員身份驗證身份時遇到問題。我知道我的後端生成正確的標記和身份標識,但我的刷新方法從未被調用。我也看了一下這個例子,但是我對所做的一切都有些困惑。 流程說明: 目前我有一個登錄屏幕,有一個登錄按鈕。用戶按下登錄按鈕,然後我的api類獲取憑證,加密密碼並將其存儲在鑰匙串中(現在註釋掉,因爲它在模擬器上不起作用)。我的DeveloperAuthenticatedIdentityProvider被稱爲我的應用程序BusytimeAuthenticated。我已經完成了所有的方法(我使用AWS lambda和DynamoDB對用戶進行身份驗證),我以未經身份驗證的訪問開始,這允許我只訪問兩種方法,即登錄和註冊。然後,我想假設我的身份驗證用戶允許我調用其他方法。從unauth切換到開發人員認證的認證用戶 - AWS iOS SDK

我API代碼:

[AWSLogger defaultLogger].logLevel = AWSLogLevelVerbose; 
id<AWSCognitoIdentityProvider> identityProvider = [[BusytimeAuthenticated alloc] initWithRegionType:AWSRegionUSEast1 
                              identityId:nil 
                       identityPoolId:@"SOMEIDENTITYPOOLID" 
                       logins:@{@"SOMEPROVIDERNAME": @"SOMEUSERNAME"} 
                         providerName:@"SOMEPROVIDERNAME" 
                              ]; 

credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 
                    identityProvider:identityProvider 
                     unauthRoleArn:nil 
                     authRoleArn:nil]; 

configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 
                    credentialsProvider:self.credentialsProvider]; 
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration; 
[[credentialsProvider refresh] continueWithBlock:^id(BFTask *task){ 
    [self testAuth]; 
    return nil; 
}]; 

我DeveloperAuthenticatedIdentityProvider代碼(BusytimeAuthenticated):

#import "BusytimeAuthenticated.h" 

@interface BusytimeAuthenticated() 
@property (strong, atomic) NSString *providerName; 
@property (strong, atomic) NSString *token; 
@end 

@implementation BusytimeAuthenticated 
@synthesize providerName=_providerName; 
@synthesize token=_token; 



- (instancetype)initWithRegionType:(AWSRegionType)regionType 
         identityId:(NSString *)identityId 
        identityPoolId:(NSString *)identityPoolId 
          logins:(NSDictionary *)logins 
         providerName:(NSString *)providerName{ 
    if (self = [super initWithRegionType:regionType identityId:identityId accountId:nil identityPoolId:identityPoolId logins:logins]) { 
     self.providerName = providerName; 
    } 
    return self; 
} 

// Return the developer provider name which you choose while setting up the 
// identity pool in the Amazon Cognito Console 

- (BOOL)authenticatedWithProvider { 
    return [self.logins objectForKey:self.providerName] != nil; 
} 


// If the app has a valid identityId return it, otherwise get a valid 
// identityId from your backend. 

- (BFTask *)getIdentityId { 
    // already cached the identity id, return it 
    if (self.identityId) { 
     return [BFTask taskWithResult:nil]; 
    } 
    // not authenticated with our developer provider 
    else if (![self authenticatedWithProvider]) { 
     return [super getIdentityId]; 

    } 
    // authenticated with our developer provider, use refresh logic to get id/token pair 
    else { 
     return [[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) { 
      if (!self.identityId) { 
       return [self refresh]; 
      } 
      return [BFTask taskWithResult:self.identityId]; 
     }]; 
    } 

} 


// Use the refresh method to communicate with your backend to get an 
// identityId and token. 

- (BFTask *)refresh { 
    if (![self authenticatedWithProvider]) { 
     return [super getIdentityId]; 
    }else{ 
//  KeychainWrapper *keychain = [[KeychainWrapper alloc]init]; 
     AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker]; 
     NSDictionary *parameters = @{@"username" : @"SOMEUSERNAME", 
            @"password":@"SOMEENCRYPTEDPASS", 
            @"isError" : @NO}; 
     NSLog(@"Here"); 
     [[lambdaInvoker invokeFunction:@"login" JSONObject:parameters] continueWithBlock:^id(BFTask* task) { 
      if (task.error) { 
       NSLog(@"Error: %@", task.error); 
      } 
      if (task.exception) { 
       NSLog(@"Exception: %@", task.exception); 
      } 
      if (task.result) { 
       self.identityId = [task.result objectForKey:@"IdentityId" ]; 
       self.token = [task.result objectForKey:@"Token" ]; 
//    [keychain mySetObject:[task.result objectForKey:@"Token" ] forKey:@"Token"]; 
//    [keychain mySetObject:[task.result objectForKey:@"IdentityId" ] forKey:@"IdentityId"]; 
       NSLog(@"Result: %@", task.result); 

      } 
      return [BFTask taskWithResult:self.identityId]; 
     }]; 



    } 
    return NULL; 
} 

@end 

總結問題: 不幸的是,當我測試我的新priveleges,我從錯誤中看到:「 Unauth_Role/CognitoIdentityCredentials未被授權執行:lambda:InvokeFunction「。很明顯,我沒有正確地切換。我在我的刷新方法中放置了一個斷點,以查看它是否被調用。不是。我不太瞭解我如何正確切換。任何幫助獲得這項工作非常感謝。

注意:我做的一個大改變是我拿出了「DeveloperAuthenticationClient」類,因爲我認爲我可以在沒有它的情況下做到這一點。

+0

我的問題已更新到此:http://stackoverflow.com/questions/33205271/unauthenticated-user-to-authenticated-user-on-aws-cognito/33219337#33219337 – user2977578

回答

1

根本問題是您正在嘗試調用Lambda函數(需要憑據)來獲取憑證。由於您使用的是「默認」客戶端配置,因此當您的開發人員身份驗證客戶端返回響應時,它將覆蓋用於訪問Lambda函數的憑據。此外,一旦該ID已被轉換爲已認證,您將無法使用它來獲取非法流程中的憑證,並且需要生成一個新的未經身份驗證的ID才能再次進行認證,然後返回到已認證的ID。

我強烈建議您在Lambda函數前設置API Gateway以刪除此循環依賴項。

+0

是的你是正確的,請看看我的新流程:我用未經身份驗證的憑證實例化我的用戶。如果credentialsprovider沒有設置登錄名:if(![credentialsProvider logins]){ 我直接撥打電話給我的後端來驗證我的用戶。如果一切正常,那麼我使用通過身份驗證的憑證對我的用戶進行身份驗證。我也給我的身份驗證憑據訪問我的登錄方法,因爲它是返回身份標​​識和令牌的方法。 – user2977578

+0

如果設置了登錄名,那麼我只需刷新我的憑證供應商 – user2977578

+0

@ user2977578同樣,您將不得不維護2個不同的身份。你正在爲自己創造更多的工作。我強烈建議你不要繼續走下去。 –

0

更新基於問題的新的信息... 這裏有幾件事情:1。 避免代碼像while(!finished)來等待一個異步任務來完成。在最好的情況下,這種忙碌的等待方式會消耗100%的CPU /內核,同時不會對電池壽命產生任何有用的影響,並且只會影響應用程序的性能。相反,請在塊中使用通知。由於您已在此實例中擁有AWSTask,因此在[credentialsProvider refresh] continueWithBlock...的末尾不要返回nil,而只需致電[self testAuth],並取消完成/代碼。 2.在您的getIdentityId實現中,第一個if條件檢查是否存在identityId,如果,則返回nil。我猜你的目標是在認證成功後緩存identityId並返回,以便每次調用getIdentityId時不必調用後端。如果是這樣,肯定要返回identityId而不是nil 3.我不認爲這是你問題的原因,但會簡化一些事情:只要你使用Auth/UnAuth配置你的身份池在初始化AWSCognitoCredentialsProvider時,您不必明確地使用它們。

一旦這些問題得到解決,如果您仍然遇到問題,請更詳細地調試代碼,並告訴我們如下內容: 刷新方法是否被調用?如果是這樣,你的if語句的哪些部分進入,結果如何?它是否曾經進入else塊並調用你的後端標識提供者?它是否成功檢索到身份標識並將其返回?

如果您進一步發現但遇到稍微不同的問題,請標記回答此問題併發布單獨問題,而不是繼續編輯此問題。這將有助於保持清楚(這個問題/答案變得很長,並且已經改變)。


原來的答覆初始貼問題/代碼...getIdentity method of the AWSCognitoCredentialsProvider返回AWSTask(即BFTask)。因此,您需要調用類似continueWithBlock的內容才能真正執行該方法。在上面的第一塊代碼中,看起來你並沒有這樣做。

+0

當我添加它時,我比以前有更多的錯誤。以前,當我調用[credentialsProvider refresh]時,它有點工作,因爲它會進入我的刷新方法。現在,當我添加,我得到此錯誤:錯誤:錯誤域= com.amazonaws.AWSLambdaInvokerErrorDomain代碼= 1「操作無法完成。(com.amazonaws.AWSLambdaInvokerErrorDomain錯誤1.)」UserInfo = 0x7f844d0f7ef0 {errorMessage =任務超時3.00秒後超時,com.amazonaws.AWSLambdaInvokerFunctionErrorKey =未處理} – user2977578

+0

一秒鐘,讓我找出一些東西。它仍然通過continueWithBlock進入我的方法。 – user2977578

+0

這看起來像來自lambda函數的錯誤。看看代碼是什麼,這可能會給你一個線索:http://docs.aws.amazon.com/AWSiOSSDK/latest/Constants/AWSLambdaErrorType.html你也可以看看Cloud Trails從lambda函數中記錄日誌。 –