应用重新启动后的 AWS ExpiredTokenException

AWS ExpiredTokenException after app relaunch

我正在构建一个 iOS (Swift) 应用程序,使用 AWS 作为具有开发人员身份验证的后端。一切正常,直到我关闭应用程序,离开一段时间然后重新启动。在这种情况下,我经常(但并非总是)在尝试从 AWS 检索数据时收到 ExpiredTokenException 错误。

这是我的代码:

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

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

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

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

    override func refresh() -> AWSTask! {
        let apiUrl = "https://url-goes-here"    // call my server to retrieve an OpenIdToken
        request.GET(apiUrl, parameters: nil, progress: nil,
            success: {
                (task: NSURLSessionDataTask, response: AnyObject?) -> Void in

                let tmp = NSMutableDictionary()
                tmp.setObject("temp", forKey: "ExampleApp")
                self.logins = tmp as [ NSObject : AnyObject ]

                let jsonDictionary = response as! NSDictionary
                self.identityId = jsonDictionary["identityId"] as! String
                self._token = jsonDictionary["token"] as! String
                awstask.setResult(response)
            },
            failure: {
                (task: NSURLSessionDataTask?, error: NSError) -> Void in

                awstask.setError(error)
            }
        )

        return awstask.task
    }
}

在 AppDelegate 中:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    let identityProvider = DeveloperAuthenticatedIdentityProvider()

    // set default service configuration
    let credentialsProvider = AWSCognitoCredentialsProvider(regionType: cognitoRegion, identityProvider: identityProvider, unauthRoleArn: unauthRole, authRoleArn: authRole)
    let configuration = AWSServiceConfiguration(region: defaultServiceRegion, credentialsProvider: credentialsProvider)
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration

    // set service configuration for S3 (my bucket is located in a different region to my Cognito and Lambda service)
    let credentialsProviderForS3 = AWSCognitoCredentialsProvider(regionType: cognitoRegion, identityProvider: identityProvider, unauthRoleArn: unauthRole, authRoleArn: unauthRole)
    let awsConfigurationForS3 = AWSServiceConfiguration(region: s3ServiceRegion, credentialsProvider: credentialsProviderForS3)
    AWSS3TransferUtility.registerS3TransferUtilityWithConfiguration(awsConfigurationForS3, forKey: "S3")

    return true
}

post表明Cognito令牌已经过期,需要开发者手动刷新。这似乎过于复杂,因为它需要设置一个计时器来定期刷新、处理应用程序关闭和重新启动以及处理刷新发生时发生的 AWS 请求。有更简单的方法吗?例如,是否可以让 AWS SDK 在尝试使用过期令牌查询服务器时自动调用刷新?

如有任何帮助,我们将不胜感激。我正在为 iOS.

使用 AWS SDK 2.3.5 版

不幸的是,开发者刷新令牌是唯一的方法。

我同意,如果 AWS SDK 处理这个问题,应用程序开发人员会更简单,但 CrdentialsProvider 的设计方式应该对所有提供商都是通用的。例如,如果有人想使用 Facebook 作为提供商,那么 AWS SDK 将无法自行处理刷新,开发人员将无法在他的应用程序中处理。将刷新流排除在 SDK 之外使我们能够保持 CredentialsProvider 通用。

适用于 iOS 2.4.x 的 AWS 移动开发工具包有一个名为 AWSIdentityProviderManager 的新协议。它有以下方法:

/**
 * Each entry in logins represents a single login with an identity provider.
 * The key is the domain of the login provider (e.g. 'graph.facebook.com') and the value is the
 * OAuth/OpenId Connect token that results from an authentication with that login provider.
 */
- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins;

符合此协议的对象的责任是 return 一个有效的 logins 字典,无论何时被请求。因为此方法是异步的,所以如果缓存的令牌已过期,您可以在其中进行网络调用。实现取决于您,但在许多情况下,AWSIdentityProviderManager 管理多个 AWSIdentityProvider,聚合它们并 return logins 字典。