Skip to content

Commit b991a98

Browse files
authored
Merge pull request #204 from AzureAD/oldalton/merge_release_1.0.0
Merge release 1.0.0 back to dev (cache optimizations and tombstone changes)
2 parents ce6cdfb + 1bbd36a commit b991a98

12 files changed

+146
-118
lines changed

IdentityCore/src/cache/MSIDMacTokenCache.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ - (void)addToItems:(nonnull NSMutableArray *)items
296296
if (item)
297297
{
298298
item = [item copy];
299+
300+
// Skip tombstones generated from previous versions of ADAL.
301+
if ([item isTombstone])
302+
{
303+
return;
304+
}
305+
299306
[items addObject:item];
300307
}
301308
}

IdentityCore/src/cache/accessor/MSIDDefaultTokenCacheAccessor.m

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,17 @@ - (BOOL)saveTokensWithConfiguration:(MSIDConfiguration *)configuration
7676
{
7777
MSID_LOG_VERBOSE(context, @"(Default accessor) Saving multi resource refresh token");
7878

79+
// Save access token
7980
BOOL result = [self saveAccessTokenWithConfiguration:configuration response:response context:context error:error];
8081

8182
if (!result) return result;
8283

84+
// Save ID token
85+
result = [self saveIDTokenWithConfiguration:configuration response:response context:context error:error];
86+
87+
if (!result) return result;
88+
89+
// Save SSO state (refresh token and account)
8390
return [self saveSSOStateWithConfiguration:configuration response:response context:context error:error];
8491
}
8592

@@ -110,28 +117,11 @@ - (BOOL)saveSSOStateWithConfiguration:(MSIDConfiguration *)configuration
110117

111118
MSID_LOG_VERBOSE(context, @"(Legacy accessor) Saving SSO state");
112119

113-
BOOL result = [self saveIDTokenWithConfiguration:configuration response:response context:context error:error];
114-
result &= [self saveRefreshTokenWithConfiguration:configuration response:response context:context error:error];
115-
result &= [self saveAccountWithConfiguration:configuration response:response context:context error:error];
120+
BOOL result = [self saveRefreshTokenWithConfiguration:configuration response:response context:context error:error];
116121

117-
if (!result)
118-
{
119-
return NO;
120-
}
122+
if (!result) return NO;
121123

122-
for (id<MSIDCacheAccessor> accessor in _otherAccessors)
123-
{
124-
if (![accessor saveSSOStateWithConfiguration:configuration
125-
response:response
126-
context:context
127-
error:error])
128-
{
129-
MSID_LOG_WARN(context, @"Failed to save SSO state in other accessor: %@", accessor.class);
130-
MSID_LOG_WARN_PII(context, @"Failed to save SSO state in other accessor: %@, error %@", accessor.class, *error);
131-
}
132-
}
133-
134-
return YES;
124+
return [self saveAccountWithConfiguration:configuration response:response context:context error:error];
135125
}
136126

137127
- (MSIDRefreshToken *)getRefreshTokenWithAccount:(MSIDAccountIdentifier *)account
@@ -794,51 +784,60 @@ - (MSIDBaseToken *)getRefreshTokenByLegacyUserId:(NSString *)legacyUserId
794784
context:(id<MSIDRequestContext>)context
795785
error:(NSError **)error
796786
{
787+
MSID_LOG_VERBOSE(context, @"(Default accessor) Looking for token with authority %@, clientId %@", authority, clientId);
788+
MSID_LOG_VERBOSE_PII(context, @"(Default accessor) Looking for token with authority %@, clientId %@, legacy userId %@", authority, clientId, legacyUserId);
789+
797790
MSIDTelemetryCacheEvent *event = [MSIDTelemetry startCacheEventWithName:MSID_TELEMETRY_EVENT_TOKEN_CACHE_LOOKUP context:context];
798791

799792
NSArray<NSString *> *aliases = [_factory defaultCacheAliasesForEnvironment:authority.msidHostWithPortIfNecessary];
800793

801-
for (NSString *alias in aliases)
794+
NSString *clientIdForQueries = clientId;
795+
796+
if (familyId)
802797
{
803-
MSID_LOG_VERBOSE(context, @"(Default accessor) Looking for token with alias %@, clientId %@", alias, clientId);
804-
MSID_LOG_VERBOSE_PII(context, @"(Default accessor) Looking for token with alias %@, clientId %@, legacy userId %@", alias, clientId, legacyUserId);
798+
// If family ID is provided, we don't need to lookup by a specific client ID
799+
clientIdForQueries = nil;
800+
}
805801

806-
MSIDDefaultCredentialCacheQuery *idTokensQuery = [MSIDDefaultCredentialCacheQuery new];
807-
idTokensQuery.environment = alias;
808-
idTokensQuery.clientId = clientId;
809-
idTokensQuery.credentialType = MSIDIDTokenType;
802+
MSIDDefaultCredentialCacheQuery *idTokensQuery = [MSIDDefaultCredentialCacheQuery new];
803+
idTokensQuery.environmentAliases = aliases;
804+
idTokensQuery.clientId = clientIdForQueries;
805+
idTokensQuery.credentialType = MSIDIDTokenType;
810806

811-
NSArray<MSIDCredentialCacheItem *> *matchedIdTokens = [_accountCredentialCache getCredentialsWithQuery:idTokensQuery
812-
legacyUserId:legacyUserId
813-
context:context
814-
error:error];
807+
NSArray<MSIDCredentialCacheItem *> *matchedIdTokens = [_accountCredentialCache getCredentialsWithQuery:idTokensQuery
808+
legacyUserId:legacyUserId
809+
context:context
810+
error:error];
815811

816-
if ([matchedIdTokens count])
817-
{
818-
NSString *homeAccountId = matchedIdTokens[0].homeAccountId;
812+
if ([matchedIdTokens count])
813+
{
814+
MSIDCredentialCacheItem *matchedIdToken = matchedIdTokens[0];
815+
NSString *homeAccountId = matchedIdToken.homeAccountId;
819816

820-
MSIDDefaultCredentialCacheQuery *rtQuery = [MSIDDefaultCredentialCacheQuery new];
821-
rtQuery.homeAccountId = homeAccountId;
822-
rtQuery.environment = alias;
823-
rtQuery.clientId = clientId;
824-
rtQuery.familyId = familyId;
825-
rtQuery.credentialType = MSIDRefreshTokenType;
817+
MSID_LOG_VERBOSE(context, @"(Default accessor] Found Match with environment %@, realm %@, client %@", matchedIdToken.environment, matchedIdToken.realm, matchedIdToken.clientId);
818+
MSID_LOG_VERBOSE_PII(context, @"(Default accessor] Found Match with environment %@, realm %@, client %@, home account ID %@", matchedIdToken.environment, matchedIdToken.realm, matchedIdToken.clientId, matchedIdToken.homeAccountId);
826819

827-
NSArray<MSIDCredentialCacheItem *> *rtCacheItems = [_accountCredentialCache getCredentialsWithQuery:rtQuery
828-
legacyUserId:nil
829-
context:context
830-
error:error];
820+
MSIDDefaultCredentialCacheQuery *rtQuery = [MSIDDefaultCredentialCacheQuery new];
821+
rtQuery.homeAccountId = homeAccountId;
822+
rtQuery.environmentAliases = aliases;
823+
rtQuery.clientId = clientIdForQueries;
824+
rtQuery.familyId = familyId;
825+
rtQuery.credentialType = MSIDRefreshTokenType;
831826

832-
if ([rtCacheItems count])
833-
{
834-
MSID_LOG_VERBOSE(context, @"(Default accessor) Found %lu refresh tokens", (unsigned long)[rtCacheItems count]);
835-
MSIDCredentialCacheItem *resultItem = rtCacheItems[0];
836-
MSIDBaseToken *resultToken = [resultItem tokenWithType:MSIDRefreshTokenType];
837-
resultToken.storageAuthority = resultToken.authority;
838-
resultToken.authority = authority;
839-
[MSIDTelemetry stopCacheEvent:event withItem:resultToken success:YES context:context];
840-
return resultToken;
841-
}
827+
NSArray<MSIDCredentialCacheItem *> *rtCacheItems = [_accountCredentialCache getCredentialsWithQuery:rtQuery
828+
legacyUserId:nil
829+
context:context
830+
error:error];
831+
832+
if ([rtCacheItems count])
833+
{
834+
MSID_LOG_VERBOSE(context, @"(Default accessor) Found %lu refresh tokens", (unsigned long)[rtCacheItems count]);
835+
MSIDCredentialCacheItem *resultItem = rtCacheItems[0];
836+
MSIDBaseToken *resultToken = [resultItem tokenWithType:MSIDRefreshTokenType];
837+
resultToken.storageAuthority = resultToken.authority;
838+
resultToken.authority = authority;
839+
[MSIDTelemetry stopCacheEvent:event withItem:resultToken success:YES context:context];
840+
return resultToken;
842841
}
843842
}
844843

IdentityCore/src/cache/ios/MSIDKeychainTokenCache.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ - (MSIDCredentialCacheItem *)tokenWithKey:(MSIDCacheKey *)key
216216
if (tokenItem)
217217
{
218218
// Delete tombstones generated from previous versions of ADAL.
219-
if ([tokenItem.secret isEqualToString:@"<tombstone>"])
219+
if ([tokenItem isTombstone])
220220
{
221221
[self deleteTombstoneWithService:attrs[(id)kSecAttrService]
222222
account:attrs[(id)kSecAttrAccount]

IdentityCore/src/cache/token/MSIDCredentialCacheItem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,6 @@
8585
targetMatching:(MSIDComparisonOptions)matchingOptions
8686
clientIdMatching:(MSIDComparisonOptions)clientIDMatchingOptions;
8787

88+
- (BOOL)isTombstone;
89+
8890
@end

IdentityCore/src/cache/token/MSIDCredentialCacheItem.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,20 @@ - (BOOL)matchesWithRealm:(nullable NSString *)realm
309309
return NO;
310310
}
311311

312+
if (!clientId && !familyId)
313+
{
314+
return YES;
315+
}
316+
312317
if (clientIDMatchingOptions == MSIDSuperSet)
313318
{
314319
if ((clientId && [self.clientId isEqualToString:clientId])
315320
|| (familyId && [self.familyId isEqualToString:familyId]))
316321
{
317322
return YES;
318323
}
324+
325+
return NO;
319326
}
320327
else
321328
{
@@ -333,4 +340,9 @@ - (BOOL)matchesWithRealm:(nullable NSString *)realm
333340
return YES;
334341
}
335342

343+
- (BOOL)isTombstone
344+
{
345+
return [self.secret isEqualToString:@"<tombstone>"];
346+
}
347+
336348
@end

IdentityCore/src/cache/token/MSIDLegacyTokenCacheItem.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,9 @@ - (MSIDIdTokenClaims *)idTokenClaims
218218
return _idTokenClaims;
219219
}
220220

221+
- (BOOL)isTombstone
222+
{
223+
return self.refreshToken && [self.refreshToken isEqualToString:@"<tombstone>"];
224+
}
225+
221226
@end

IdentityCore/src/oauth2/MSIDWebviewFactory.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ - (NSURL *)startURLFromConfiguration:(MSIDWebviewConfiguration *)configuration r
133133
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:configuration.authorizationEndpoint resolvingAgainstBaseURL:NO];
134134
NSDictionary *parameters = [self authorizationParametersFromConfiguration:configuration requestState:state];
135135

136-
urlComponents.queryItems = [parameters urlQueryItemsArray];
137136
urlComponents.percentEncodedQuery = [parameters msidURLFormEncode];
138137

139138
return urlComponents.URL;

IdentityCore/src/oauth2/aad_v2/MSIDAADV2IdTokenClaims.m

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,16 @@ - (void)initDerivedProperties
5252
}
5353

5454
_uniqueId = [MSIDHelpers normalizeUserId:uniqueId];
55-
_userId = [MSIDHelpers normalizeUserId:self.preferredUsername];
55+
56+
// Set userId
57+
NSString *userId = self.preferredUsername;
58+
59+
if ([NSString msidIsStringNilOrBlank:userId])
60+
{
61+
userId = self.subject;
62+
}
63+
64+
_userId = [MSIDHelpers normalizeUserId:userId];
5665
_userIdDisplayable = YES;
5766
}
5867

IdentityCore/tests/integration/MSIDDefaultAccessorSSOIntegrationTests.m

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ - (void)testSaveTokensWithFactory_whenMultiResourceResponse_andNoOtherAccessors_
201201
XCTAssertEqualObjects(account.authority.absoluteString, @"https://login.microsoftonline.com/tenantId.onmicrosoft.com");
202202
}
203203

204-
- (void)testSaveTokensWithFactory_whenMultiResourceResponse_savesTokensToBothAccessors
204+
- (void)testSaveTokensWithFactory_whenMultiResourceResponse_savesTokensOnlyToDefaultAccessor
205205
{
206206
NSString *idToken = [MSIDTestIdTokenUtil idTokenWithPreferredUsername:@"upn@test.com" subject:@"subject" givenName:@"Hello" familyName:@"World" name:@"Hello World" version:@"2.0" tid:@"tenantId.onmicrosoft.com"];
207207

@@ -283,21 +283,10 @@ - (void)testSaveTokensWithFactory_whenMultiResourceResponse_savesTokensToBothAcc
283283
XCTAssertEqual([legacyAccessTokens count], 0);
284284

285285
NSArray *legacyRefreshTokens = [self getAllLegacyRefreshTokens];
286-
XCTAssertEqual([legacyRefreshTokens count], 1);
287-
288-
MSIDLegacyRefreshToken *legacyRefreshToken = legacyRefreshTokens[0];
289-
XCTAssertEqualObjects(legacyRefreshToken.idToken, idToken);
290-
XCTAssertEqualObjects(legacyRefreshToken.accountIdentifier.legacyAccountId, @"upn@test.com");
291-
XCTAssertEqualObjects(legacyRefreshToken.refreshToken, @"refresh token");
292-
XCTAssertNil(legacyRefreshToken.familyId);
293-
XCTAssertEqual(legacyRefreshToken.credentialType, MSIDRefreshTokenType);
294-
XCTAssertEqualObjects(legacyRefreshToken.authority.absoluteString, @"https://login.microsoftonline.com/common");
295-
XCTAssertEqualObjects(legacyRefreshToken.clientId, @"test_client_id");
296-
XCTAssertEqualObjects(legacyRefreshToken.accountIdentifier.homeAccountId, @"uid.utid");
297-
XCTAssertEqualObjects(legacyRefreshToken.additionalServerInfo, [NSDictionary dictionary]);
286+
XCTAssertEqual([legacyRefreshTokens count], 0);
298287
}
299288

300-
- (void)testSaveTokensWithFactory_whenMultiResourceFOCIResponse_savesTokensToBothAccessors
289+
- (void)testSaveTokensWithFactory_whenMultiResourceFOCIResponse_savesTokensOnlyToDefaultAccessor
301290
{
302291
NSString *idToken = [MSIDTestIdTokenUtil idTokenWithPreferredUsername:@"upn@test.com" subject:@"subject" givenName:@"Hello" familyName:@"World" name:@"Hello World" version:@"2.0" tid:@"tenantId.onmicrosoft.com"];
303292

@@ -322,16 +311,7 @@ - (void)testSaveTokensWithFactory_whenMultiResourceFOCIResponse_savesTokensToBot
322311
XCTAssertEqual([legacyAccessTokens count], 0);
323312

324313
NSArray *legacyRefreshTokens = [self getAllLegacyRefreshTokens];
325-
XCTAssertEqual([legacyRefreshTokens count], 2);
326-
XCTAssertNotEqualObjects(legacyRefreshTokens[0], legacyRefreshTokens[1]);
327-
328-
MSIDLegacyRefreshToken *refreshToken1 = legacyRefreshTokens[0];
329-
MSIDLegacyRefreshToken *refreshToken2 = legacyRefreshTokens[1];
330-
331-
XCTAssertEqualObjects(refreshToken1.familyId, @"2");
332-
XCTAssertEqualObjects(refreshToken2.familyId, @"2");
333-
XCTAssertEqualObjects(refreshToken1.clientId, @"test_client_id");
334-
XCTAssertEqualObjects(refreshToken2.clientId, @"foci-2");
314+
XCTAssertEqual([legacyRefreshTokens count], 0);
335315

336316
NSArray *defaultAccessTokens = [self getAllAccessTokens];
337317
XCTAssertEqual([defaultAccessTokens count], 1);
@@ -361,23 +341,23 @@ - (void)testSaveTokensWithFactory_whenMultiResourceFOCIResponse_savesTokensToBot
361341
context:nil
362342
error:&error];
363343

364-
XCTAssertEqual([clientAccounts count], 1);
344+
XCTAssertEqual([clientAccounts count], 0);
365345

366346
NSArray *familyAccounts = [_otherAccessor allAccountsForEnvironment:@"login.microsoftonline.com"
367347
clientId:nil
368348
familyId:@"2"
369349
context:nil
370350
error:&error];
371351

372-
XCTAssertEqual([familyAccounts count], 1);
352+
XCTAssertEqual([familyAccounts count], 0);
373353

374354
NSArray *allAccounts = [_otherAccessor allAccountsForEnvironment:@"login.microsoftonline.com"
375355
clientId:@"test_client_id"
376356
familyId:@"2"
377357
context:nil
378358
error:&error];
379359

380-
XCTAssertEqual([allAccounts count], 1);
360+
XCTAssertEqual([allAccounts count], 0);
381361
}
382362

383363

@@ -1759,6 +1739,18 @@ - (void)testClearCacheForAccount_whenAccountProvided_shouldRemoveTokens
17591739
familyId:nil
17601740
accessor:_defaultAccessor];
17611741

1742+
[self saveResponseWithUPN:@"upn@test.com"
1743+
clientId:@"test_client_id"
1744+
authority:@"https://login.windows.net/common"
1745+
responseScopes:@"user.sing2 user.dance"
1746+
inputScopes:@"user.sing2 user.dance"
1747+
uid:@"uid"
1748+
utid:@"utid"
1749+
accessToken:@"access token 2"
1750+
refreshToken:@"refresh token"
1751+
familyId:nil
1752+
accessor:_otherAccessor];
1753+
17621754
NSError *error = nil;
17631755
NSArray *accounts = [_defaultAccessor allAccountsForEnvironment:@"login.windows.net" clientId:@"test_client_id" familyId:nil context:nil error:&error];
17641756

IdentityCore/tests/integration/MSIDDefaultTokenCacheIntegrationTests.m

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,10 @@ - (void)testGetTokenWithType_whenTypeRefreshAccountWithUtidAndUidProvided_should
559559

560560
- (void)testGetTokenWithType_whenTypeRefreshAccountWithLegacyIDProvided_shouldReturnToken
561561
{
562-
[_cacheAccessor saveSSOStateWithConfiguration:[MSIDTestConfiguration v2DefaultConfiguration]
563-
response:[MSIDTestTokenResponse v2DefaultTokenResponse]
564-
context:nil
565-
error:nil];
566-
562+
[_cacheAccessor saveTokensWithConfiguration:[MSIDTestConfiguration v2DefaultConfiguration]
563+
response:[MSIDTestTokenResponse v2DefaultTokenResponse]
564+
context:nil
565+
error:nil];
567566

568567
MSIDAccountIdentifier *account = [[MSIDAccountIdentifier alloc] initWithLegacyAccountId:DEFAULT_TEST_ID_TOKEN_USERNAME
569568
homeAccountId:nil];

0 commit comments

Comments
 (0)