awslabs / aws-mobile-appsync-sdk-ios

iOS SDK for AWS AppSync.
https://awslabs.github.io/aws-mobile-appsync-sdk-ios/
Other
262 stars 130 forks source link

AppSync API calls Fails to Return Data #118

Closed yunfei356 closed 5 years ago

yunfei356 commented 5 years ago

State your question I am using AWSMobileClient to sign my users into my app, and then use Amazon Cognito to access AWS resources inside the app. Below are the setup I did for the authentication:

1) Followed the guide here and successfully set up AWSMobileClient so that users signed up using my app were successfully added to Cognito user pool. I tested and the sign up, sign in, and initialization features all work successfully.

2) I initialized AppSync and AWSMobileClient in my project.

3) For the auth and unauth roles created by Cognito identity pool, I added policies to the former that allows the auth role to call AppSync, Lambda, and DynamoDB.

However, even with this set up, calling AppSync from the app returned nil data. When I call AppSync in the console, I could see correct data returned.

Also, I saw some sample authentication code using AWSCognitoAuth. What is the difference between AWSCognitoAuth and AWSCognito?

Provide code snippets (if applicable)

import UIKit
import AWSAppSync
import AWSMobileClient

func initializeAppSync() {
        let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.USWest2, identityPoolId:"us-west-2:XXXX")

        let configuration = AWSServiceConfiguration(region:.USWest2, credentialsProvider:credentialsProvider)

        AWSServiceManager.default().defaultServiceConfiguration = configuration

        let databaseURL = URL(fileURLWithPath:NSTemporaryDirectory()).appendingPathComponent("zhiyou-db")
        do {
            let appSyncConfig = try AWSAppSyncClientConfiguration(appSyncClientInfo: AWSAppSyncClientInfo(), userPoolsAuthProvider: {
                class MyCognitoUserPoolsAuthProvider : AWSCognitoUserPoolsAuthProviderAsync {
                    func getLatestAuthToken(_ callback: @escaping (String?, Error?) -> Void) {
                        AWSMobileClient.sharedInstance().getTokens { (tokens, error) in
                            if error != nil {
                                callback(nil, error)
                            } else {
                                callback(tokens?.idToken?.tokenString, nil)
                            }
                        }
                    }
                }
                return MyCognitoUserPoolsAuthProvider()}(), databaseURL:databaseURL)
            appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncConfig)
        } catch {
            print("Error initializing appsync client. \(error)")
        }
    }

Environment(please complete the following information):

Device Information (please complete the following information):

rohandubal commented 5 years ago

Hello @yunfei356

Can you please confirm what type of Authentication are you using for your AppSync API? Is it AWS_IAM or Amazon_Cognito_UserPools?

In the code which you have pasted above, the AWSAppSyncClient is initialized with authentication mode of Amazon_Cognito_UserPools and not AWS_IAM. But the description which you have posted says that you attached permissions on the Cognito Identity role which would mean it is attached for AWS_IAM. You need to update the initialization code to use AWSMobileClient.sharedInstance() as the credentials provider for AWSAppSyncClient to make that work.

Hope this helps.

Thanks, Rohan

yunfei356 commented 5 years ago

Hi @rohandubal ,

I am using Amazon_Cognito_UserPools. The IAM permissions I added are for the two auth and unauth roles created by Identity Pools. I read on a guide (I forgot where now) that this is necessary.

Can you point out where in my code I need to change and how? I already use tokens retrieved from AWSMobileClient.sharedInstance() to initialize AppSync. I am not aware of another way to do this. It would be great if you can provide some sample code.

Thanks!

yunfei356 commented 5 years ago

Hi @rohandubal,

I know you guys are probably super busy but it would be great if you can point me to the right direction as I am blocked in my project because of this authentication issue. Whenever you have time, can you provide some sample code as to how to do this authentication correctly? I followed everything in the guides and still not getting any data from AppSync.

Thanks a ton.

rohandubal commented 5 years ago

Hello @yunfei356

You have the correct code for the use-case you are trying to achieve.

AWSCognitoAuth is an SDK which offers a web view based authentication rather than the native solution offered by AWSMobileClient. AWSCognito is a completely different SDK for data sync.

Does this help answer your questions?

Thanks, Rohan

yunfei356 commented 5 years ago

Hi @rohandubal,

I discovered that the issue I was having was not with authentication, because I can make an AppSync query call without triggering any errors. The call succeeded but the data returned is nil. I tried calling on the console and it returned data fine that way. I am pretty sure my code is correct. Do you have any idea why it would return nil? Below are my snippets of code:

let appDelegate = UIApplication.shared.delegate as! AppDelegate appSyncClient = appDelegate.appSyncClient

let getProfileInput = GetProfileInput(personId: self.personId) appSyncClient?.fetch(query: GetProfileQuery(input: getProfileInput)) { (result, error) in if error != nil { print(error?.localizedDescription ?? "") return } print("result: ", result?.data ?? "No data") }

palpatim commented 5 years ago

Hi @yunfei356,

Sorry for the delayed response. The behavior you're describing could be happening for a number of reasons. For example, your AppSync resolver may have authorization or authentication logic that the console query fulfills in a way that your app setup does not. Similarly, you may be passing subtly different data from the console than your app.

One thing you can do is to turn on CloudWatch logging in your AppSync development endpoint, so you can view logs from the resolvers to see if there are any errors being generated. You can find instructions for enabling CloudWatch logs here.

Do your CloudWatch logs show any errors during the request flow?

yunfei356 commented 5 years ago

Hi @palpatim,

I actually stopped working on this project. If I work on it anymore in the future and experience this problem again, I will reopen the issue. Thanks.