Skip to content

Commit 2d15e0f

Browse files
wxxionroyjitharsh62
authored
fix(AWSCore): Add sync control to avoid crash during concurrent credential requests (#4527)
* Add sync control to avoid crash during concurrent credential requests * Update CHANGELOG.md --------- Co-authored-by: Jithin Roy <[email protected]> Co-authored-by: Harshdeep Singh <[email protected]>
1 parent 960555b commit 2d15e0f

File tree

5 files changed

+74
-42
lines changed

5 files changed

+74
-42
lines changed

AWSCore/Authentication/AWSCredentialsProvider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ typedef NS_ENUM(NSInteger, AWSCognitoCredentialsProviderErrorType) {
176176
/**
177177
The identity id associated with this provider. This value will be fetched from the keychain at startup. If you do not want to reuse the existing identity id, you must call the clearKeychain method.
178178
*/
179-
@property (nonatomic, strong, readonly, nullable) NSString *identityId;
179+
@property (atomic, strong, readonly, nullable) NSString *identityId;
180180

181181
/**
182182
The identity pool id associated with this provider. Also used to create a namedspaced keychain area to store identity id and credentials.

AWSCore/Authentication/AWSCredentialsProvider.m

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ @interface AWSWebIdentityCredentialsProvider()
194194

195195
@property (nonatomic, strong) AWSSTS *sts;
196196
@property (nonatomic, strong) AWSUICKeyChainStore *keychain;
197-
@property (nonatomic, strong) AWSCredentials *internalCredentials;
197+
@property (atomic, strong) AWSCredentials *internalCredentials;
198198

199199
@end
200200

@@ -267,22 +267,26 @@ - (void)invalidateCachedTemporaryCredentials {
267267
#pragma mark -
268268

269269
- (AWSCredentials *)internalCredentials {
270-
if (! _internalCredentials) {
271-
_internalCredentials = [[AWSCredentials alloc] initFromKeychain:self.keychain];
270+
@synchronized (self) {
271+
if (! _internalCredentials) {
272+
_internalCredentials = [[AWSCredentials alloc] initFromKeychain:self.keychain];
273+
}
274+
return _internalCredentials;
272275
}
273-
return _internalCredentials;
274276
}
275277

276278
- (void)setInternalCredentials:(AWSCredentials *)internalCredentials {
277-
_internalCredentials = internalCredentials;
278-
279-
self.keychain[AWSCredentialsProviderKeychainAccessKeyId] = internalCredentials.accessKey;
280-
self.keychain[AWSCredentialsProviderKeychainSecretAccessKey] = internalCredentials.secretKey;
281-
self.keychain[AWSCredentialsProviderKeychainSessionToken] = internalCredentials.sessionKey;
282-
if (internalCredentials.expiration) {
283-
self.keychain[AWSCredentialsProviderKeychainExpiration] = [NSString stringWithFormat:@"%f", [internalCredentials.expiration timeIntervalSince1970]];
284-
} else {
285-
self.keychain[AWSCredentialsProviderKeychainExpiration] = nil;
279+
@synchronized (self) {
280+
_internalCredentials = internalCredentials;
281+
282+
self.keychain[AWSCredentialsProviderKeychainAccessKeyId] = internalCredentials.accessKey;
283+
self.keychain[AWSCredentialsProviderKeychainSecretAccessKey] = internalCredentials.secretKey;
284+
self.keychain[AWSCredentialsProviderKeychainSessionToken] = internalCredentials.sessionKey;
285+
if (internalCredentials.expiration) {
286+
self.keychain[AWSCredentialsProviderKeychainExpiration] = [NSString stringWithFormat:@"%f", [internalCredentials.expiration timeIntervalSince1970]];
287+
} else {
288+
self.keychain[AWSCredentialsProviderKeychainExpiration] = nil;
289+
}
286290
}
287291
}
288292

@@ -298,9 +302,9 @@ @interface AWSCognitoCredentialsProvider()
298302
@property (nonatomic, strong) AWSExecutor *refreshExecutor;
299303
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
300304
@property (atomic, assign) BOOL useEnhancedFlow;
301-
@property (nonatomic, strong) AWSCredentials *internalCredentials;
305+
@property (atomic, strong) AWSCredentials *internalCredentials;
302306
@property (atomic, assign, getter=isRefreshingCredentials) BOOL refreshingCredentials;
303-
@property (nonatomic, strong) NSDictionary<NSString *, NSString *> *cachedLogins;
307+
@property (atomic, strong) NSDictionary<NSString *, NSString *> *cachedLogins;
304308
// This is a temporary solution to bypass the requirement of protocol check for `AWSIdentityProviderManager`.
305309
@property (nonatomic, strong) NSString *customRoleArnOverride;
306310

@@ -659,7 +663,8 @@ - (void)setUpWithRegionType:(AWSRegionType)regionType
659663
// 2. The cached credentials is nil.
660664
// 3. The credentials expire within 10 minutes.
661665
credentials = self.internalCredentials.copy;
662-
if ((!self.cachedLogins || [self.cachedLogins isEqualToDictionary:logins])
666+
NSDictionary<NSString *, NSString *> *cachedLogins = self.cachedLogins;
667+
if ((!cachedLogins || [cachedLogins isEqualToDictionary:logins])
663668
&& credentials
664669
&& credentials.isValid) {
665670
return [AWSTask taskWithResult:credentials];
@@ -679,7 +684,8 @@ - (void)setUpWithRegionType:(AWSRegionType)regionType
679684
return [AWSTask cancelledTask];
680685
}
681686
credentials = self.internalCredentials.copy;
682-
if ((!self.cachedLogins || [self.cachedLogins isEqualToDictionary:logins])
687+
cachedLogins = self.cachedLogins;
688+
if ((!cachedLogins || [cachedLogins isEqualToDictionary:logins])
683689
&& credentials
684690
&& credentials.isValid) {
685691
return [AWSTask taskWithResult:credentials];
@@ -806,30 +812,39 @@ - (NSString *)identityId {
806812
if (identityId) {
807813
return identityId;
808814
}
809-
return [self.keychain stringForKey:AWSCredentialsProviderKeychainIdentityId];
815+
816+
@synchronized (self) {
817+
return [self.keychain stringForKey:AWSCredentialsProviderKeychainIdentityId];
818+
}
810819
}
811820

812821
- (void)setIdentityId:(NSString *)identityId {
813-
self.keychain[AWSCredentialsProviderKeychainIdentityId] = identityId;
822+
@synchronized (self) {
823+
self.keychain[AWSCredentialsProviderKeychainIdentityId] = identityId;
824+
}
814825
}
815826

816827
- (AWSCredentials *)internalCredentials {
817-
if (! _internalCredentials) {
818-
_internalCredentials = [[AWSCredentials alloc] initFromKeychain:self.keychain];
828+
@synchronized (self) {
829+
if (!_internalCredentials) {
830+
_internalCredentials = [[AWSCredentials alloc] initFromKeychain:self.keychain];
831+
}
832+
return _internalCredentials;
819833
}
820-
return _internalCredentials;
821834
}
822835

823836
- (void)setInternalCredentials:(AWSCredentials *)internalCredentials {
824-
_internalCredentials = internalCredentials;
825-
826-
self.keychain[AWSCredentialsProviderKeychainAccessKeyId] = internalCredentials.accessKey;
827-
self.keychain[AWSCredentialsProviderKeychainSecretAccessKey] = internalCredentials.secretKey;
828-
self.keychain[AWSCredentialsProviderKeychainSessionToken] = internalCredentials.sessionKey;
829-
if (internalCredentials.expiration) {
830-
self.keychain[AWSCredentialsProviderKeychainExpiration] = [NSString stringWithFormat:@"%f", [internalCredentials.expiration timeIntervalSince1970]];
831-
} else {
832-
self.keychain[AWSCredentialsProviderKeychainExpiration] = nil;
837+
@synchronized (self) {
838+
_internalCredentials = internalCredentials;
839+
840+
self.keychain[AWSCredentialsProviderKeychainAccessKeyId] = internalCredentials.accessKey;
841+
self.keychain[AWSCredentialsProviderKeychainSecretAccessKey] = internalCredentials.secretKey;
842+
self.keychain[AWSCredentialsProviderKeychainSessionToken] = internalCredentials.sessionKey;
843+
if (internalCredentials.expiration) {
844+
self.keychain[AWSCredentialsProviderKeychainExpiration] = [NSString stringWithFormat:@"%f", [internalCredentials.expiration timeIntervalSince1970]];
845+
} else {
846+
self.keychain[AWSCredentialsProviderKeychainExpiration] = nil;
847+
}
833848
}
834849
}
835850

AWSCore/Authentication/AWSIdentityProvider.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ typedef NS_ENUM(NSInteger, AWSCognitoCredentialsProviderHelperErrorType) {
8787
/**
8888
The identity id as determined by the Amazon Cognito service
8989
*/
90-
@property (nonatomic, strong, nullable) NSString *identityId;
90+
@property (atomic, strong, nullable) NSString *identityId;
9191

9292
/**
9393
*/
@@ -123,7 +123,7 @@ typedef NS_ENUM(NSInteger, AWSCognitoCredentialsProviderHelperErrorType) {
123123
/**
124124
The identity id as determined by the Amazon Cognito service
125125
*/
126-
@property (nonatomic, strong, nullable) NSString *identityId;
126+
@property (atomic, strong, nullable) NSString *identityId;
127127

128128
/**
129129
The identity provider manager that asynchronously returns `logins`.

AWSCore/Authentication/AWSIdentityProvider.m

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ @interface AWSAbstractCognitoCredentialsProviderHelper()
4141

4242
@property (nonatomic, strong) id<AWSIdentityProviderManager> identityProviderManager;
4343
@property (nonatomic, strong) NSString *identityPoolId;
44-
@property (nonatomic, strong) NSDictionary *cachedLogins;
44+
@property (atomic, strong) NSDictionary *cachedLogins;
4545

4646
@end
4747

@@ -53,6 +53,8 @@ - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration;
5353

5454
@implementation AWSAbstractCognitoCredentialsProviderHelper
5555

56+
@synthesize identityId = _identityId;
57+
5658
#pragma mark - AWSIdentityProvider
5759

5860
// Sub classes should override this.
@@ -88,11 +90,19 @@ - (BOOL)isAuthenticated {
8890
return [self.cachedLogins count] > 0;
8991
}
9092

93+
- (NSString *)identityId {
94+
@synchronized (self) {
95+
return _identityId;
96+
}
97+
}
98+
9199
- (void)setIdentityId:(NSString *)identityId {
92-
if (identityId && ![identityId isEqualToString:_identityId]) {
93-
[self postIdentityIdChangedNotification:identityId];
100+
@synchronized (self) {
101+
if (identityId && ![identityId isEqualToString:_identityId]) {
102+
[self postIdentityIdChangedNotification:identityId];
103+
}
104+
_identityId = identityId;
94105
}
95-
_identityId = identityId;
96106
}
97107

98108
- (void)postIdentityIdChangedNotification:(NSString *)newId {
@@ -272,10 +282,10 @@ - (NSString *)identityProviderName {
272282
if (self.identityProviderManager && self.useEnhancedFlow) {
273283
self.cachedLogins = nil;
274284
return [[self getIdentityId] continueWithSuccessBlock:^id _Nullable(AWSTask<NSString *> * _Nonnull task) {
275-
if(self.cachedLogins){
276-
return [AWSTask taskWithResult:self.cachedLogins];
277-
}
278-
else {
285+
NSDictionary *cachedLogins = self.cachedLogins;
286+
if (cachedLogins) {
287+
return [AWSTask taskWithResult:cachedLogins];
288+
} else {
279289
return [self.identityProviderManager logins];
280290
}
281291
}];

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# AWS Mobile SDK for iOS CHANGELOG
22

3+
## 2.30.4
4+
5+
### Bug Fixes
6+
7+
- **AWSCore**
8+
- Add sync control to avoid crash during concurrent credential requests
9+
310
## 2.30.3
411

512
### Bug Fixes

0 commit comments

Comments
 (0)