tokens identities federated expiration create cognito aws admin_no_srp_auth ios swift amazon-web-services aws-sdk amazon-cognito

ios - identities - create user cognito



AWS iOS SDK Cognito Developer Authentication(Swift) (2)

Creo que lo he descubierto. Necesitaba utilizar BFTask, que está diseñado para manejar tareas en segundo plano con finalización.

Para las personas que luchan con una implementación de Swift de autenticación de desarrollador con Cognito que podría tener una configuración similar a la mía, así es como lo logré:

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 } }

Y inicializó el ExampleAppIdentityProvider haciendo:

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)

GlobalVariables una struct llamada GlobalVariables con variables de entorno globales que contienen valores para bucket , unAuthRoleArn , authRoleArn , etc. Por supuesto que no tienes que hacer eso, pero lo estoy mencionando en caso de que alguien esté confundido.

Me está resultando difícil descifrar cómo devolver las credenciales de desarrollador proporcionadas por mi servidor (a través de AWS) a mi proveedor de identidades de ejemplo.

Parece que necesito hacer esto sincrónicamente dentro del método de refresh en la clase ExampleIdentityProvider. Estoy usando AFNetworking para hacer la solicitud, pero es una solicitud async GET . ¿Cómo puedo hacer esto sincrónicamente para el método de actualización en mi IdentityProvider?

Lo siguiente está en 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) }) } }


puedes generar tu clase personalizada para la autenticación cognito

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 } }

y puedes usar el delegado de la aplicación

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 }