n0_quarter
n0_quarter

Reputation: 538

How to properly use Amazon Cognito iOS SDK with Swift 3?

I'm using Swift 3 and Xcode 8.1 and I'm using Amazon Cognito iOS SDK together with Facebook SDK to provide user authentication.

I'm facing number of issues while using the latest Amazon Cognito SDK (2.4.11). Main issues are:

I'd really appreciate an official Amazon SDK developers comment here. I find it very frustrating that I have to hunt after a solution in the internet and not being able to just follow official Amazon documentation, because it's outdated.

Upvotes: 2

Views: 1762

Answers (2)

perpil
perpil

Reputation: 1584

I would recommend against following the push paradigm that is suggested above and switch to the pull paradigm. The purpose of AWSIdentityProviderManager is to prompt you for a token only when the SDK needs it, not for you to set it externally periodically whether the SDK needs it or not. This way you don't have to manage token expiry yourself, just make sure your token is valid when logins is called and if it isn't you can use an AWSCompletionSource to get a fresh one.

Assuming you have integrated Facebook login, your IdentityProviderManager should look something like this:

import Foundation
import AWSCore
import FacebookLogin
import FacebookCore

class FacebookProvider: NSObject, AWSIdentityProviderManager {
    func logins() -> AWSTask<NSDictionary> {
        if let token = AccessToken.current?.authenticationToken {
            return AWSTask(result: [AWSIdentityProviderFacebook:token])
        }
        return AWSTask(error:NSError(domain: "Facebook Login", code: -1 , userInfo: ["Facebook" : "No current Facebook access token"]))
    }
}

To use it:

let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.YOUR_REGION, identityPoolId: "YOUR_IDENTITY_POOL_ID", identityProviderManager: FacebookProvider())
let configuration = AWSServiceConfiguration(region: AWSRegionType.usEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration

And then to test getting credentials:

AWSServiceManager.default().defaultServiceConfiguration.credentialsProvider.credentials().continue(with: AWSExecutor.default(), with: { (task) -> Any? in
            print(task.result ?? "nil")
            return task
        })

BTW, I needed to add this to my app delegate to get Facebook Login to work with Swift which is not mentioned in the instructions here https://developers.facebook.com/docs/swift/login :

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
    }

Upvotes: 1

Karthick Selvaraj
Karthick Selvaraj

Reputation: 2505

Yes in latest SDK logins property get deprecated, so we need to assign IdentityProvider to logins by using AWSIdentityProviderManager delegate. So do as follows,

  1. Create one custom class which adopt AWSIdentityProviderManager delegate.

    import UIKit
    import AWSCognitoIdentityProvider
    import AWSCore
    import Foundation
    
    class DVCustomIdentityProvider: NSObject, AWSIdentityProviderManager {
     var tokens: NSDictionary = [String : String]() as NSDictionary
    
     init(tokens: [String : String]) {
        self.tokens = tokens as NSDictionary
     }
    
     func logins() -> AWSTask<NSDictionary> { // AWSIdentityProviderManager delegate method
       return AWSTask(result: tokens)
     }
    
    }
    
  2. Add following code in view controller you want.

    @IBAction func loginButtonPressed(_ sender: UIButton) {
    if (phoneNumberTextField.text != nil) && (passwordTextField.text != nil) {
        // Change userName.getSession.... with your Facebook method to get authenticate from Facebook, in success block add what I added in my success block. 
        userName.getSession(phoneNumberTextField.text!, password: passwordTextField.text!, validationData: nil).continue(with: AWSExecutor.mainThread(), withSuccessBlock: { (task: AWSTask<AWSCognitoIdentityUserSession>) -> Any? in // Your Facebook call will go here 
    
            if task.error != nil {
              // Error
            } else { 
                // SUCCESS BLOCK
                self.updateCredentials()
            }
            return nil
        })
    } else {
       // Credential empty
    }
    }
    
        func updateCredentials() {
           let customcedentialProvider = DVCustomIdentityProvider(tokens: ["graph.facebook.com" : token]))
           let credentialsProvider = AWSCognitoCredentialsProvider(regionType: "Your region", identityPoolId: "Your pool id", unauthRoleArn: "Your unearth role name", authRoleArn: "Your auth role name", identityProviderManager: customcedentialProvider)
           let configuration = AWSServiceConfiguration(region: "Your region", credentialsProvider:credentialsProvider)
           AWSServiceManager.default().defaultServiceConfiguration = configuration
           credentialsProvider.getIdentityId().continue(with: AWSExecutor.mainThread(), withSuccessBlock: { (taskTask: AWSTask<NSString>) -> Any? in
             if taskTask.error == nil && taskTask.exception == nil {
                kUserIdentityID = taskTask.result as String? // Im saving user identity id in constant variable called "kUserIdentityID"
    
             } else {
                // Do Nothing
             }
          return nil
         })
        }
    

import following in your view controller

import AWSCognitoIdentityProvider
import AWSCore
import AWSCognito

Note: This code is written in swift 3

Upvotes: 0

Related Questions