应用重新启动后的 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
字典。
我正在构建一个 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
字典。