2015-02-14 11 views
5

Es fällt mir schwer herauszufinden, wie ich die von meinem Server (über AWS) bereitgestellten Entwickleranmeldeinformationen an meinen Beispielidentitätsanbieter zurücksenden kann.AWS iOS SDK Cognito-Entwicklerauthentifizierung (Swift)

Es scheint, ich muss dies synchron innerhalb der refresh-Methode für die ExampleIdentityProvider-Klasse tun. Ich benutze AFNetworking, um die Anfrage zu stellen, aber es ist eine asynchrone Anfrage GET. Wie kann ich das synchron für die Refresh-Methode auf meinem IdentityProvider tun?

Folgendes ist in Swift:

class ExampleIdentityProvider: AWSAbstractIdentityProvider { 
    var newToken: String! 

    override var token: String { 
     get { 
      return newToken 
     } 
     set { 
      newToken = newValue 
     } 
    } 

    override func getIdentityId() -> BFTask! { 
     if self.identityId != nil { 
      return BFTask(result: self.identityId) 
     }else{ 
      return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in 
       if self.identityId == nil { 
        return self.refresh() 
       } 
       return BFTask(result: self.identityId) 
      }) 
     } 
    } 

    override func refresh() -> BFTask! { 
     return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in 
      let result = AFNETWORKING REQUEST FOR CREDENTIALS TO MY SERVER 
      self.identityId = result.identityId 
      self.token = result.token 

      return BFTask(result: self.identityId) 
     }) 
    } 
} 

Antwort

11

Ich glaube, ich es herausgefunden haben. Ich musste BFTask verwenden, die für die Bearbeitung von Hintergrundaufgaben mit Abschluss erstellt wurde.

Für Menschen mit einer Swift Implementierung von Entwickler-Authentifizierung mit Cognito kämpfen, die eine ähnliche Einrichtung zu mir haben könnten, das ist, wie ich es erreicht:

class ExampleAppIdentityProvider: AWSAbstractCognitoIdentityProvider { 
    var _token: String! 
    var _logins: [ NSObject : AnyObject ]! 

    // Header stuff you may not need but I use for auth with my server 
    let acceptHeader = "application/vnd.exampleapp-api+json;version=1;" 
    let authHeader = "Token token=" 
    let userDefaults = NSUserDefaults.standardUserDefaults() 
    let authToken = self.userDefaults.valueForKey("authentication_token") as String 

    // End point that my server gives amazon identityId and tokens to authorized users 
    let url = "https://api.myapp.com/api/amazon_id/" 

    override var token: String { 
     get { 
      return _token 
     } 
    } 

    override var logins: [ NSObject : AnyObject ]! { 
     get { 
      return _logins 
     } 
     set { 
      _logins = newValue 
     } 
    } 

    override func getIdentityId() -> BFTask! { 
     if self.identityId != nil { 
      return BFTask(result: self.identityId) 
     }else{ 
      return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in 
       if self.identityId == nil { 
        return self.refresh() 
       } 
       return BFTask(result: self.identityId) 
      }) 
     } 
    } 

    override func refresh() -> BFTask! { 
     let task = BFTaskCompletionSource() 
     let request = AFHTTPRequestOperationManager() 
     request.requestSerializer.setValue(self.acceptHeader, forHTTPHeaderField: "ACCEPT") 
     request.requestSerializer.setValue(self.authHeader+authToken, forHTTPHeaderField: "AUTHORIZATION") 
     request.GET(self.url, parameters: nil, success: { (request: AFHTTPRequestOperation!, response: AnyObject!) -> Void in 
      // The following 3 lines are required as referenced here: http://stackoverflow.com/a/26741208/535363 
      var tmp = NSMutableDictionary() 
      tmp.setObject("temp", forKey: "ExampleApp") 
      self.logins = tmp 

      // Get the properties from my server response 
      let properties: NSDictionary = response.objectForKey("properties") as NSDictionary 
      let amazonId = properties.objectForKey("amazon_identity") as String 
      let amazonToken = properties.objectForKey("token") as String 

      // Set the identityId and token for the ExampleAppIdentityProvider 
      self.identityId = amazonId 
      self._token = amazonToken 

      task.setResult(response) 
     }, failure: { (request: AFHTTPRequestOperation!, error: NSError!) -> Void in 
      task.setError(error) 
     }) 
     return task.task 
    } 
} 

und initialisiert die ExampleAppIdentityProvider, indem Sie:

let identityProvider = ExampleAppIdentityProvider() 
    let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityProvider: identityProvider, unauthRoleArn: GlobalVariables.cognitoUnauthRoleArn, authRoleArn: GlobalVariables.cognitoAuthRoleArn) 
    let defaultServiceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialsProvider) 
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration 

    let transferManager = AWSS3TransferManager.defaultS3TransferManager() 

    let uploadRequest = AWSS3TransferManagerUploadRequest() 
    uploadRequest.bucket = GlobalVariables.awsBucket 
    uploadRequest.key = "\(GlobalVariables.environment)/uploads/users/\(userId)/\(type)/\(timestamp)/original.jpg" 
    uploadRequest.ACL = .AuthenticatedRead 
    uploadRequest.body = tmpFileUrl 

    // Upload file 
    let task = transferManager.upload(uploadRequest) 

ich habe eine structGlobalVariables mit globalen Umgebungsvariablen benannt, die Werte für bucket halten, unAuthRoleArn, authRoleArn usw. O Natürlich müssen Sie das nicht tun, aber ich erwähne es, falls jemand verwirrt ist.

+0

zeigen Ihnen, wie Sie den Anbieter/Konfiguration initialisiert für die AWS Zeug, diese verwenden können ? – user871177

+0

@ user871177 siehe den aktualisierten Code oben. Hoffe das ist hilfreich. – Yavin4

+0

wow, so nützlich. –

0

können Sie Sie benutzerdefinierte Klasse für cognito Authentifizierung erzeugen

import AWSS3 
import AWSCore 
import Alamofire 

//This variable is store aws credential token 
var cachedLogin : NSDictionary? 
final class AmazonIdentityProvider : AWSCognitoCredentialsProviderHelper{ 

    // Handles getting the login 
    override func logins() -> AWSTask<NSDictionary> { 
     guard let cachedLoginObj = cachedLogin else { 
      return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSDictionary> in 
       guard let credential = credentialTask.result else { 
        return AWSTask(result: nil) 
       } 

       self.setCognitoTokenKey(credential: credential) 

       return AWSTask(result: cachedLogin) 
      }) as! AWSTask<NSDictionary> 
     } 
     return AWSTask(result: cachedLoginObj) 
    } 

    // Handles getting a token from the server 
    override func token() -> AWSTask<NSString> { 
     return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSString> in 
      guard let credential = credentialTask.result else { 
       return AWSTask(result: nil) 
      } 

      self.setCognitoTokenKey(credential: credential) 

      return AWSTask(result: credential.token as NSString) 
     }) as! AWSTask<NSString> 
    } 

    // Handles getting the identity id 
    override func getIdentityId() -> AWSTask<NSString> { 

     return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSString> in 
      guard let credential = credentialTask.result else { 
       return AWSTask(result: nil) 
      } 

      self.setCognitoTokenKey(credential: credential) 

      return AWSTask(result: credential.identityId as NSString) 
     }) as! AWSTask<NSString> 
    } 

    //This method is used to AWS Token set 
    func setCognitoTokenKey(credential : AmazonCognitoCredential){ 
     let login: NSDictionary = ["cognito-identity.amazonaws.com": credential.token] 
     cachedLogin = login 
     self.identityId = credential.identityId 
    } 

    // Gets credentials from server 
    func getCredentials() -> AWSTask<AmazonCognitoCredential> { 
     let tokenRequest = AWSTaskCompletionSource<AmazonCognitoCredential>() 
     getAwsToken { (isSuccess, error, credentials) in 
      if isSuccess 
      { 
       tokenRequest.set(result: credentials) 
      } 
      else 
      { 
       tokenRequest.set(error: error!) 
      } 
     } 
     return tokenRequest.task 
    } 
    typealias CompletionBlock = (_ success:Bool,_ errorMassage:Error?,_ responce:AmazonCognitoCredential?) -> Void 
    func getAwsToken(complitionBlock : @escaping CompletionBlock) { 
//Your server token code 
} 
/// AmazonCognito credential custom class 
final class AmazonCognitoCredential { 
    let token: String 
    let identityId: String 

    init(token: String, identityId: String) { 
     self.token = token 
     self.identityId = identityId 
    } 
} 

und Sie in AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

    AWSDDLog.sharedInstance.logLevel = .all 
    let identityProvider = AmazonIdentityProvider() 
    let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, unauthRoleArn: CognitoRoleUnauth, authRoleArn: CognitoRoleAuth, identityProvider: identityProvider) 
    let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialsProvider) 
    AWSServiceManager.default().defaultServiceConfiguration = configuration 

    let task = identityProvider.getIdentityId() 
    task.continueWith { (task:AWSTask) -> Any? in 
     if (task.error != nil) { 
      print("\(String(describing: task.error))") 
     } else { 
      print("Task result: \(String(describing: task.result))") 
     } 
     return nil 
    } 
    return true 
}