How to refresh AWSCredentials?
Related to this issue https://github.com/aws-amplify/aws-sdk-ios/issues/1691
I am using @palpatim solution to refresh aws credential
[[[[[AWSS3 defaultS3] configuration] credentialsProvider] credentials] waitUntilFinished];
But some time when credential expire, it can not be refreshed.
As I debug in to SDK, App run into waiting for google sdk.
AWSCredentialsProvider.m, Line 625
if (self.isRefreshingCredentials) {
// Waits up to 60 seconds for the Google SDK to refresh a token.
if (dispatch_semaphore_wait(self.semaphore, dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC)) != 0) {
NSError *error = [NSError errorWithDomain:AWSCognitoCredentialsProviderErrorDomain
code:AWSCognitoCredentialsProviderCredentialsRefreshTimeout
userInfo:nil];
return [AWSTask taskWithError:error];
}
}
What can I do in this case? As we can not use the AWS credential any more (create pre-signed url request fail)
It seem that restart the app fixed the problem.
P/s: We also develop an android version of our app using aws android sdk. It is not neccessary to refresh credential there.
@phanchutoan Few questions:
- Are you using userpools to signIn and then retrieve the credentials?
- What you mean by credentials expire? Do you get a signOut callback?
- Are you running
[[[[[AWSS3 defaultS3] configuration] credentialsProvider] credentials] waitUntilFinished];in the main queue?
I am not using user pool, I am using identity pool with developer authenticated identities.
[[[[[AWSS3 defaultS3] configuration] credentialsProvider] credentials] waitUntilFinished]; works some time but not always, as i said above, when i try to debug in to sdk, it stuck at // Waits up to 60 seconds for the Google SDK to refresh a token.
@palpatim @royjit any updates on this issue? For more detail information about this issue:
State your question Refresh Credentials always ends up waitinig for Google SDK
Which AWS Services are you utilizing? AWSCognito AWSS3
Environment
SDK Version: 2.13.4 Dependency Manager: Cocoapods Swift Version : 5.0
Device Information: Device: iPhone XR iOS Version: iOS 13.5.1
Previous questions:
- Are you using userpools to signIn and then retrieve the credentials?
I'm using Developer Authenticated Identities
class DeveloperAuthenticatedIdentityProvider: AWSCognitoCredentialsProviderHelper {
convenience override init() {
self.init(regionType: .APNortheast1, identityPoolId: AWS.identityPool, useEnhancedFlow: true, identityProviderManager: nil)
}
override func token() -> AWSTask<NSString> {
let cognitoToken = DefaultStorage.cognitoToken! as NSString
identityId = DefaultStorage.cognitoId
return AWSTask(result: cognitoToken)
}
}
With AWSServiceManager initialization:
func configureAWSServiceManager() {
let devAuth = DeveloperAuthenticatedIdentityProvider()
let cognitoCredentialsProvider = AWSCognitoCredentialsProvider(regionType: .APNortheast1, identityProvider: devAuth)
let configuration = AWSServiceConfiguration(region: .APNortheast1, credentialsProvider: cognitoCredentialsProvider)
AWSServiceManager.default()?.defaultServiceConfiguration = configuration
}
- What you mean by credentials expire? Do you get a signOut callback?
We're builing an app that show many photos using UICollectionView, the photo's image will be displayed using Presigned URL if it's not cached before on the device.
After some minutes the app runs, when creating PresignedURL the library will return AWSCognitoCredentialsProviderErrorDomain code 4
as @palpatim 's solution, by calling [[[[[AWSS3 defaultS3] configuration] credentialsProvider] credentials] waitUntilFinished] seems work, but when app entered to background for some minutes (about 8~12 minutes) and opens the app, there's a possibility that the library always waiting 60s for Google SDK to refresh a token.
it's always ends up on AWSCredentialsProvider.m: Line 626 inside this function:
AWSTask<AWSCredentials *> *)credentialsWithCancellationToken:(AWSCancellationTokenSource *) cancellationTokenSource
and will lead to throw an error AWSCognitoCredentialsProviderErrorDomain code 4 : AWSCognitoCredentialsProviderInvalidCognitoIdentityToken
if (self.isRefreshingCredentials) {
// Waits up to 60 seconds for the Google SDK to refresh a token.
if (dispatch_semaphore_wait(self.semaphore, dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC)) != 0) {
NSError *error = [NSError errorWithDomain:AWSCognitoCredentialsProviderErrorDomain
code:AWSCognitoCredentialsProviderCredentialsRefreshTimeout
userInfo:nil];
return [AWSTask taskWithError:error];
}
}
- Are you running
[[[[[AWSS3 defaultS3] configuration] credentialsProvider] credentials] waitUntilFinished]in the main queue? No, I'm calling that method inside global queue withuserInteractiveqos
Apologies for loosing track on this issue. I am trying to see if this logic work without the waiting for Google, preliminary testing looks promising. I have attached a branch here for testing https://github.com/aws-amplify/aws-sdk-ios/tree/royjit.credentialsproviderfix
If you still facing this issue could you please try this this branch and see if the issue exists?
Hi @royjit , it's been 2 years and I really appreciate your follow up.
I've change my podfile like below.
platform :ios, '13.0'
use_frameworks!
def install_pods
pod 'AWSCore', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSCognito'
pod 'AWSS3'
end
However it seems the AWSCognito version is not compatible with the branch you pushed.
[!] CocoaPods could not find compatible versions for pod "AWSCore":
In snapshot (Podfile.lock):
AWSCore (from `https://github.com/aws-amplify/aws-sdk-ios.git`, branch `royjit.credentialsproviderfix`)
In Podfile:
AWSCognito was resolved to 2.1.0, which depends on
AWSCore (~> 2.1.0)
AWSCore (from `https://github.com/aws-amplify/aws-sdk-ios.git`, branch `royjit.credentialsproviderfix`)
Could you assist me which version should I use for AWSCognito and AWSS3 to handle that error?
Will you be able to point other pods as well to the fix?
pod 'AWSCore', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSCognito', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSS3', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
Hi @royjit.
I have tried to set the podfile like above.
However it's still no luck when installing the pod since the Unable to find a specification for 'AWSCognito'error occurs.
Could you assist me regarding why this error occurs?
Podfile:
def install_pods
pod 'AWSCore', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSCognito', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSS3', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
end
Console Output:
-> Pre-downloading: `AWSCognito` from `https://github.com/aws-amplify/aws-sdk-ios.git`, branch `royjit.credentialsproviderfix`
$ /usr/bin/git ls-remote https://github.com/aws-amplify/aws-sdk-ios.git royjit.credentialsproviderfix
84f634107c7bf0c0199b374b9bf75ae7c2301458 refs/heads/royjit.credentialsproviderfix
> Git download
> Git download
$ /usr/bin/git clone https://github.com/aws-amplify/aws-sdk-ios.git
/var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221107-78023-1cmkjxs --template=
Cloning into '/var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221107-78023-1cmkjxs'...
$ /usr/bin/git -C /var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221107-78023-1cmkjxs checkout --quiet
84f634107c7bf0c0199b374b9bf75ae7c2301458
[!] Unable to find a specification for 'AWSCognito'.
Could you try reset the cocoapod cache and try again?
rm -rf "${HOME}/Library/Caches/CocoaPods"
rm -rf "`pwd`/Pods/"
pod update
Hi @phantumcode. I have tried above steps to reset the cocoapods. However, it's still no luck when updating the pods.
rm -rf "${HOME}/Library/Caches/CocoaPods"
rm -rf "`pwd`/Pods/"
pod update --verbose
Update all pods
Preparing
Updating local specs repositories
CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only performed in repo update
Updating spec repo `master`
Updating spec repo `artsy`
Analyzing dependencies
Inspecting targets to integrate
Using `ARCHS` setting to build architectures of target `Pods-Fueru`: (``)
Finding Podfile changes
A AWSCore
M AWSCognito
M AWSS3
Fetching external sources
-> Pre-downloading: `AWSCognito` from `https://github.com/aws-amplify/aws-sdk-ios.git`, branch `royjit.credentialsproviderfix`
$ /usr/bin/git ls-remote https://github.com/aws-amplify/aws-sdk-ios.git royjit.credentialsproviderfix
84f634107c7bf0c0199b374b9bf75ae7c2301458 refs/heads/royjit.credentialsproviderfix
> Git download
> Git download
$ /usr/bin/git clone https://github.com/aws-amplify/aws-sdk-ios.git /var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221204-15385-1hjbo7c --template=
Cloning into '/var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221204-15385-1hjbo7c'...
$ /usr/bin/git -C /var/folders/5f/pnvqw1g156n5m7vyz7623mhm0000gn/T/d20221204-15385-1hjbo7c checkout --quiet 84f634107c7bf0c0199b374b9bf75ae7c2301458
[!] Unable to find a specification for 'AWSCognito'.
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/external_sources/abstract_external_source.rb:124:in `block in pre_download'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/user_interface.rb:86:in `titled_section'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/external_sources/abstract_external_source.rb:113:in `pre_download'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/external_sources/downloader_source.rb:13:in `fetch'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:993:in `fetch_external_source'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:972:in `block (2 levels) in fetch_external_sources'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:971:in `each'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:971:in `block in fetch_external_sources'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/user_interface.rb:64:in `section'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:970:in `fetch_external_sources'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer/analyzer.rb:117:in `analyze'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer.rb:416:in `analyze'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer.rb:241:in `block in resolve_dependencies'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/user_interface.rb:64:in `section'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer.rb:240:in `resolve_dependencies'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/installer.rb:161:in `install!'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/command/update.rb:63:in `run'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/claide-1.1.0/lib/claide/command.rb:334:in `run'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/lib/cocoapods/command.rb:52:in `run'
/Users/-/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/cocoapods-1.11.3/bin/pod:55:in `<top (required)>'
/Users/-/.rbenv/versions/2.7.1/bin/pod:25:in `load'
/Users/-/.rbenv/versions/2.7.1/bin/pod:25:in `<main>'
Apologies for losing track on this. I see that you are depending on a deprecated pod - AWSCognito. If you are trying to use Cognito User pool you should be using AWSCognitoIdentityProvider . So does updating the podfile to the below should work:
pod 'AWSCore', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSCognitoIdentityProvider', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
pod 'AWSS3', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.credentialsproviderfix'
Hi @royjit, I tried using that podfile and it worked well. After keeping the app in the background for several hours/days and then navigating to the foreground, I was still able to retrieve the Presigned URL from Cognito. It seems that I can say the royjit.credentialsproviderfix branch fixed the issue.
However, based on the changes you have made, is it safe to just remove the waiting credential things?
@ghani-ma @royjit I encountered the same issue. This commit seems to be the proper fix as this is already merged in the main branch. The fix was released in version https://github.com/aws-amplify/aws-sdk-ios/releases/tag/2.28.2. IMHO, I would prefer to use the main branch and released version changes than use the workaround branch mentioned above. Anyway, the information above was really helpful. Thanks a lot! 👍