cannot authenticate user for aws appsync with swif

2019-07-23 11:06发布

问题:

I am trying to connect to my AWS AppSync service from my Swift mobile app using the AWS Swift SDK but keep getting the following error:

Error occurred: (401 unauthorized) Did not receive a successful HTTP code.

I am using User Pools and have set everything up following the tutorial for swift. My question is, how do I incorporate the AppSync.json config file generated in the console in my request? That is not mentioned in the tutorial and may be the reason I cannot connect.

The json file looks like this:

{
    "graphqlEndpoint": "my_endpoint_url",
    "region": "us-east-1",
    "authenticationType": "AMAZON_COGNITO_USER_POOLS",
    "apiKey": null
}

At the moment I am using the following configuration:

// Set up  Amazon Cognito credentials
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: CognitoIdentityRegion,
                                                        identityPoolId: CognitoIdentityPoolId, identityProviderManager: pool)
// You can choose your database location, accessible by SDK
let databaseURL = URL(fileURLWithPath:NSTemporaryDirectory()).appendingPathComponent(database_name)

do {
    // Initialize the AWS AppSync configuration

    let appSyncConfig = try AWSAppSyncClientConfiguration(url: AppSyncEndpointURL,
                                                          serviceRegion: AppSyncRegion,
                                                          credentialsProvider: credentialsProvider,
                                                          databaseURL:databaseURL)

    appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncConfig)
    // Set id as the cache key for objects
    appSyncClient?.apolloClient?.cacheKeyForObject = { $0["id"] }
} catch {
    print("Error initializing appsync client. \(error)")
}

EDIT #1

It turns out the example is using the API key method rather than user pools. So now I have changed the config to:

let appSyncConfig = try AWSAppSyncClientConfiguration(url: AppSyncEndpointURL, serviceRegion: AppSyncRegion, userPoolsAuthProvider: CognitoUserPoolsAuthProvider(pool: pool))

The problem is the message now is:

Use of unresolved identifier 'CognitoUserPoolsAuthProvider'

if I try:

let appSyncConfig = try AWSAppSyncClientConfiguration(url: AppSyncEndpointURL, serviceRegion: AppSyncRegion, userPoolsAuthProvider: AWSCognitoUserPoolsAuthProvider(pool: pool))

the error is:

'AWSCognitoUserPoolsAuthProvider' cannot be constructed because it has no accessible initializers

Not sure how to satisfy the userPoolsAuthProvider: argument in the config.

回答1:

To address your specific issue, userPoolsAuthProvider needs to accept a class that extends the AWSCognitoUserPoolsAuthProvider protocol. So your instantiation would look something like this:

 let appSyncConfig = try AWSAppSyncClientConfiguration(url: AppSyncEndpointURL,
                                                          serviceRegion: AppSyncRegion,
                                                          userPoolsAuthProvider: self,
                                                          databaseURL:databaseURL)

And then in the class in which you are creating the AppSyncClient, you would extend like this:

extension YourClass: AWSCognitoUserPoolsAuthProvider {
  func getLatestAuthToken() -> String {
    var token: String = ""

    // pool is an instance of AWSCognitoIdentityUserPool
    self.pool?.currentUser()?.getSession().continueOnSuccessWith(block: { (task) -> Any? in 
      token = task.result!.idToken!.tokenString
      return nil
    }).waitUnitFinished()
  }

  return token
}

Also I think the AppSync configuration by default looks for an awsconfiguration.json file in your project. You posted this a while back so possibly things have changed with AWS services and AppSync.

Hope this helps