Skip to content

Commit 7f08ed7

Browse files
authored
Merge pull request #793 from AzureAD/oldalton/account_collapsing_fixes
MSAL account collapsing improvements for guest users
2 parents 8576bc8 + 3ce3824 commit 7f08ed7

File tree

8 files changed

+145
-21
lines changed

8 files changed

+145
-21
lines changed

MSAL/src/MSALAccount+Internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
@property (nonatomic) MSALAccountId *homeAccountId;
4343
@property (nonatomic) NSString *username;
4444
@property (nonatomic) NSString *environment;
45-
@property (nonatomic) NSMutableArray<MSALTenantProfile *> *mTenantProfiles;
45+
@property (nonatomic) NSMutableDictionary<NSString *, MSALTenantProfile *> *mTenantProfiles;
4646
@property (nonatomic) NSDictionary<NSString *, NSString *> *accountClaims;
4747
@property (nonatomic) NSString *identifier;
4848
@property (nonatomic) MSIDAccountIdentifier *lookupAccountIdentifier;

MSAL/src/MSALAccount.m

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,7 @@ - (instancetype)initWithUsername:(NSString *)username
6161
_identifier = homeAccountId.identifier;
6262
_lookupAccountIdentifier = [[MSIDAccountIdentifier alloc] initWithDisplayableId:username homeAccountId:homeAccountId.identifier];
6363

64-
if (tenantProfiles.count > 0)
65-
{
66-
self.mTenantProfiles = [[NSMutableArray alloc] initWithArray:tenantProfiles];
67-
}
64+
[self addTenantProfiles:tenantProfiles];
6865
}
6966

7067
return self;
@@ -80,7 +77,7 @@ - (instancetype)initWithMSIDAccount:(MSIDAccount *)account
8077

8178
MSALTenantProfile *tenantProfile = [[MSALTenantProfile alloc] initWithIdentifier:account.localAccountId
8279
tenantId:account.realm
83-
environment:account.environment
80+
environment:account.storageEnvironment ?: account.environment
8481
isHomeTenantProfile:account.isHomeTenantAccount
8582
claims:allClaims];
8683
if (tenantProfile)
@@ -95,7 +92,7 @@ - (instancetype)initWithMSIDAccount:(MSIDAccount *)account
9592

9693
return [self initWithUsername:account.username
9794
homeAccountId:homeAccountId
98-
environment:account.environment
95+
environment:account.storageEnvironment ?: account.environment
9996
tenantProfiles:tenantProfiles];
10097
}
10198

@@ -135,7 +132,7 @@ - (instancetype)copyWithZone:(NSZone *)zone
135132
NSString *username = [self.username copyWithZone:zone];
136133
MSALAccountId *homeAccountId = [self.homeAccountId copyWithZone:zone];
137134
NSString *environment = [self.environment copyWithZone:zone];
138-
NSArray *tenantProfiles = [[NSMutableArray alloc] initWithArray:self.mTenantProfiles copyItems:YES];
135+
NSArray *tenantProfiles = [[NSMutableArray alloc] initWithArray:[self tenantProfiles] copyItems:YES];
139136

140137
MSALAccount *account = [[MSALAccount allocWithZone:zone] initWithUsername:username homeAccountId:homeAccountId environment:environment tenantProfiles:tenantProfiles];
141138
account.accountClaims = [self.accountClaims copyWithZone:zone];
@@ -162,8 +159,6 @@ - (BOOL)isEqual:(id)object
162159
- (NSUInteger)hash
163160
{
164161
NSUInteger hash = 0;
165-
hash = hash * 31 + self.username.hash;
166-
hash = hash * 31 + self.homeAccountId.hash;
167162
hash = hash * 31 + self.environment.hash;
168163
return hash;
169164
}
@@ -173,8 +168,16 @@ - (BOOL)isEqualToAccount:(MSALAccount *)user
173168
if (!user) return NO;
174169

175170
BOOL result = YES;
176-
result &= (!self.username && !user.username) || [self.username isEqualToString:user.username];
177-
result &= (!self.homeAccountId && !user.homeAccountId) || [self.homeAccountId.identifier isEqualToString:user.homeAccountId.identifier];
171+
172+
if (self.homeAccountId.identifier && user.homeAccountId.identifier)
173+
{
174+
result &= [self.homeAccountId.identifier isEqualToString:user.homeAccountId.identifier];
175+
}
176+
else if (self.username || user.username)
177+
{
178+
result &= [self.username.lowercaseString isEqualToString:user.username.lowercaseString];
179+
}
180+
178181
result &= (!self.environment && !user.environment) || [self.environment isEqualToString:user.environment];
179182
return result;
180183
}
@@ -183,20 +186,24 @@ - (BOOL)isEqualToAccount:(MSALAccount *)user
183186

184187
- (NSArray<MSALTenantProfile *> *)tenantProfiles
185188
{
186-
return self.mTenantProfiles;
189+
return self.mTenantProfiles.allValues;
187190
}
188191

189192
- (void)addTenantProfiles:(NSArray<MSALTenantProfile *> *)tenantProfiles
190193
{
191194
if (tenantProfiles.count <= 0) return;
192195

193-
if (self.mTenantProfiles)
196+
if (!self.mTenantProfiles)
194197
{
195-
[self.mTenantProfiles addObjectsFromArray:tenantProfiles];
198+
self.mTenantProfiles = [NSMutableDictionary new];
196199
}
197-
else
200+
201+
for (MSALTenantProfile *profile in tenantProfiles)
198202
{
199-
self.mTenantProfiles = [[NSMutableArray alloc] initWithArray:tenantProfiles];
203+
if (profile.tenantId && !self.mTenantProfiles[profile.tenantId])
204+
{
205+
self.mTenantProfiles[profile.tenantId] = profile;
206+
}
200207
}
201208
}
202209

MSAL/src/configuration/external/ios/MSALLegacySharedADALAccount.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ - (instancetype)initWithJSONDictionary:(NSDictionary *)jsonDictionary error:(NSE
9595
{
9696
_identifier = [MSIDAccountIdentifier homeAccountIdentifierFromUid:_objectId utid:_tenantId];
9797
}
98+
else
99+
{
100+
NSDictionary *additionalPropertiesDictionary = [jsonDictionary msidObjectForKey:@"additionalProperties" ofClass:[NSDictionary class]];
101+
102+
if (additionalPropertiesDictionary)
103+
{
104+
NSString *homeAccountId = [additionalPropertiesDictionary msidObjectForKey:@"home_account_id" ofClass:[NSString class]];
105+
106+
if (![NSString msidIsStringNilOrBlank:homeAccountId])
107+
{
108+
_identifier = homeAccountId;
109+
}
110+
}
111+
}
98112

99113
NSMutableDictionary *claims = [NSMutableDictionary new];
100114

MSAL/src/configuration/external/ios/MSALLegacySharedAccount.m

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ - (instancetype)initWithMSALAccount:(id<MSALAccount>)account
104104

105105
jsonDictionary[@"signInStatus"] = @{appBundleId : @"SignedIn"};
106106
jsonDictionary[@"username"] = account.username;
107-
jsonDictionary[@"additionalProperties"] = @{@"createdBy": appName};
107+
108+
NSMutableDictionary *additionalProperties = [NSMutableDictionary new];
109+
[additionalProperties addEntriesFromDictionary:@{@"createdBy": appName}];
110+
[additionalProperties addEntriesFromDictionary:[self additionalPropertiesFromMSALAccount:account claims:claims]];
111+
jsonDictionary[@"additionalProperties"] = additionalProperties;
108112
[jsonDictionary addEntriesFromDictionary:[self claimsFromMSALAccount:account claims:claims]];
109113
return [self initWithJSONDictionary:jsonDictionary error:error];
110114
}
@@ -180,6 +184,7 @@ - (BOOL)updateAccountWithMSALAccount:(id<MSALAccount>)account
180184

181185
mutableAdditionalInfo[@"updatedBy"] = appName;
182186
mutableAdditionalInfo[@"updatedAt"] = [[[self class] dateFormatter] stringFromDate:[NSDate date]];
187+
[mutableAdditionalInfo addEntriesFromDictionary:[self additionalPropertiesFromMSALAccount:account claims:nil]];
183188

184189
oldDictionary[@"additionalProperties"] = mutableAdditionalInfo;
185190

@@ -198,6 +203,16 @@ - (NSDictionary *)claimsFromMSALAccount:(id<MSALAccount>)account claims:(NSDicti
198203
return nil;
199204
}
200205

206+
- (NSDictionary *)additionalPropertiesFromMSALAccount:(id<MSALAccount>)account claims:(NSDictionary *)claims
207+
{
208+
if (account.identifier)
209+
{
210+
return @{@"home_account_id": account.identifier};
211+
}
212+
213+
return nil;
214+
}
215+
201216
#pragma mark - Helpers
202217

203218
+ (NSDateFormatter *)dateFormatter

MSAL/src/instance/MSALAccountsProvider.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#import "MSALAccountEnumerationParameters.h"
4848
#import "MSALErrorConverter.h"
4949
#import "MSALTenantProfile.h"
50+
#import "MSALAccount+MultiTenantAccount.h"
5051

5152
@interface MSALAccountsProvider()
5253

@@ -231,7 +232,7 @@ - (MSALAccount *)accountForParameters:(MSALAccountEnumerationParameters *)parame
231232

232233
if ([externalAccount.mTenantProfiles count])
233234
{
234-
NSArray<MSALTenantProfile *> *homeTenantProfileArray = [externalAccount.mTenantProfiles filteredArrayUsingPredicate:self.homeTenantFilterPredicate];
235+
NSArray<MSALTenantProfile *> *homeTenantProfileArray = [externalAccount.tenantProfiles filteredArrayUsingPredicate:self.homeTenantFilterPredicate];
235236
if ([homeTenantProfileArray count] == 1) accountClaims = homeTenantProfileArray[0].claims;
236237
}
237238

@@ -252,12 +253,13 @@ - (void)addMSALAccount:(MSALAccount *)account toSet:(NSMutableSet *)allAccountsS
252253
}
253254
else
254255
{
255-
[existingAccount addTenantProfiles:account.mTenantProfiles];
256+
[existingAccount addTenantProfiles:account.tenantProfiles];
256257
}
257258

258259
if (accountClaims)
259260
{
260261
existingAccount.accountClaims = accountClaims;
262+
existingAccount.username = account.username;
261263
}
262264
}
263265

MSAL/test/unit/MSALAccountTests.m

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,56 @@ - (void)testAddTenantProfiles_whenAddValidTenantProfiles_shouldAddIt
190190
XCTAssertEqual(account.tenantProfiles[1].isHomeTenantProfile, YES);
191191
}
192192

193+
- (void)testAddTenantProfiles_whenDuplicateTenantProfile_shouldNotAddToExistingAccount
194+
{
195+
// Create MSAL account 1
196+
MSIDAccount *msidAccount = [MSIDAccount new];
197+
msidAccount.accountIdentifier = [[MSIDAccountIdentifier alloc] initWithDisplayableId:@"[email protected]" homeAccountId:@"uid.tid"];
198+
msidAccount.username = @"[email protected]";
199+
msidAccount.accountType = MSIDAccountTypeMSSTS;
200+
msidAccount.name = @"User";
201+
msidAccount.localAccountId = @"guest_oid";
202+
__auto_type authorityUrl = [NSURL URLWithString:@"https://login.microsoftonline.com/guest_tid"];
203+
__auto_type authority = [[MSIDAADAuthority alloc] initWithURL:authorityUrl context:nil error:nil];
204+
msidAccount.environment = authority.environment;
205+
msidAccount.realm = authority.realm;
206+
NSDictionary *clientInfoClaims = @{ @"uid" : @"uid",
207+
@"utid" : @"tid"
208+
};
209+
210+
211+
MSIDClientInfo *clientInfo = [[MSIDClientInfo alloc] initWithJSONDictionary:clientInfoClaims error:nil];
212+
msidAccount.clientInfo = clientInfo;
213+
214+
NSDictionary *idTokenDictionary = @{ @"aud" : @"b6c69a37",
215+
@"oid" : @"ff9feb5a"
216+
};
217+
218+
MSIDIdTokenClaims *idTokenClaims = [[MSIDIdTokenClaims alloc] initWithJSONDictionary:idTokenDictionary error:nil];
219+
XCTAssertNotNil(idTokenClaims);
220+
msidAccount.idTokenClaims = idTokenClaims;
221+
MSALAccount *account = [[MSALAccount alloc] initWithMSIDAccount:msidAccount createTenantProfile:YES];
222+
223+
// Create MSAL account 2
224+
MSIDAccount *msidAccount2 = [msidAccount copy];
225+
msidAccount2.localAccountId = @"new_oid";
226+
__auto_type homeAuthorityUrl = [NSURL URLWithString:@"https://login.microsoftonline.com/guest_tid"];
227+
__auto_type homeAuthority = [[MSIDAADAuthority alloc] initWithURL:homeAuthorityUrl context:nil error:nil];
228+
msidAccount2.environment = homeAuthority.environment;
229+
msidAccount2.realm = homeAuthority.realm;
230+
231+
MSALAccount *account2 = [[MSALAccount alloc] initWithMSIDAccount:msidAccount2 createTenantProfile:YES];
232+
XCTAssertNotNil(account2);
233+
234+
// Add tenant profiles
235+
[account addTenantProfiles:account2.tenantProfiles];
236+
237+
XCTAssertEqual(account.tenantProfiles.count, 1);
238+
XCTAssertEqualObjects(account.tenantProfiles[0].identifier, @"guest_oid");
239+
XCTAssertEqualObjects(account.tenantProfiles[0].tenantId, @"guest_tid");
240+
XCTAssertEqual(account.tenantProfiles[0].isHomeTenantProfile, NO);
241+
}
242+
193243
- (void)testAddTenantProfiles_whenAddNilTenantProfiles_shouldNotAddToExistingAccount
194244
{
195245
MSALAuthority *authority = [MSALAuthority authorityWithURL:[NSURL URLWithString:@"https://login.microsoftonline.com/tid"]
@@ -324,4 +374,35 @@ - (void)testEquals_whenEqual_shouldReturnTrue
324374
XCTAssertEqualObjects(account, account2);
325375
}
326376

377+
- (void)testEquals_whenIdentifiersEqual_userNameDifferent_shouldConsiderEqual
378+
{
379+
MSALAccountId *accountId = [[MSALAccountId alloc] initWithAccountIdentifier:@"1.2" objectId:@"1" tenantId:@"2"];
380+
MSALAccount *account1 = [[MSALAccount alloc] initWithUsername:@"displayableID"
381+
homeAccountId:accountId
382+
environment:@"login.microsoftonline.com"
383+
tenantProfiles:nil];
384+
385+
XCTAssertNotNil(account1);
386+
MSALAccount *account2 = [account1 copy];
387+
account2.username = @"differentDisplayableIDAlias";
388+
389+
XCTAssertNotNil(account2);
390+
XCTAssertEqualObjects(account1, account2);
391+
}
392+
393+
- (void)testEquals_whenIdentifiersMissing_userNameDifferent_shouldConsiderDifferentAccount
394+
{
395+
MSALAccount *account1 = [[MSALAccount alloc] initWithUsername:@"displayableID"
396+
homeAccountId:nil
397+
environment:@"login.microsoftonline.com"
398+
tenantProfiles:nil];
399+
400+
XCTAssertNotNil(account1);
401+
MSALAccount *account2 = [account1 copy];
402+
account2.username = @"differentDisplayableIDAlias";
403+
404+
XCTAssertNotNil(account2);
405+
XCTAssertNotEqualObjects(account1, account2);
406+
}
407+
327408
@end

MSAL/test/unit/ios/external-cache/MSALLegacySharedADALAccountTests.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,20 @@ - (void)testInitWithJSONDictionary_whenAllInformationPresentAndGuestTenant_shoul
115115

116116
NSMutableDictionary *mutableDict = [adalAccountDictionary mutableCopy];
117117
mutableDict[@"authEndpointUrl"] = @"https://login.microsoftonline.com/contoso.com";
118+
mutableDict[@"additionalProperties"] = @{@"home_account_id": @"uid.utid"};
118119

119120
NSError *error = nil;
120121
MSALLegacySharedADALAccount *account = [[MSALLegacySharedADALAccount alloc] initWithJSONDictionary:mutableDict error:&error];
121122
XCTAssertNotNil(account);
122123
XCTAssertNil(error);
123124
XCTAssertEqualObjects(account.accountType, @"ADAL");
124125
XCTAssertEqualObjects(account.environment, @"login.microsoftonline.com");
125-
XCTAssertNil(account.identifier);
126126
XCTAssertEqualObjects(account.accountIdentifier, accountId);
127127
XCTAssertEqualObjects(account.username, @"[email protected]");
128128
XCTAssertEqualObjects(account.accountClaims[@"oid"], objectId);
129129
XCTAssertEqualObjects(account.accountClaims[@"tid"], tenantId);
130130
XCTAssertEqualObjects(account.accountClaims[@"name"], @"myDisplayName.contoso.user");
131+
XCTAssertEqualObjects(account.identifier, @"uid.utid");
131132
}
132133

133134
#pragma mark - InitWithMSALAccount

MSAL/test/unit/ios/external-cache/MSALLegacySharedAccountTests.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ - (void)testUpdateAccountWithMSALAccount_whenRemoveOperation_shouldUpdateSigninS
208208
XCTAssertNotNil(updatedAt);
209209
XCTAssertEqualObjects(account.accountType, @"ADAL");
210210
XCTAssertEqualObjects(account.accountIdentifier, accountId);
211+
NSString *homeAccountId = [account jsonDictionary][@"additionalProperties"][@"home_account_id"];
212+
XCTAssertEqualObjects(homeAccountId, @"uid.utid");
211213
}
212214

213215
- (void)testUpdateAccountWithMSALAccount_whenUpdateOperation_shouldUpdateSigninStatusAndUpdatedDict
@@ -238,6 +240,8 @@ - (void)testUpdateAccountWithMSALAccount_whenUpdateOperation_shouldUpdateSigninS
238240
XCTAssertNotNil(updatedAt);
239241
XCTAssertEqualObjects(account.accountType, @"ADAL");
240242
XCTAssertEqualObjects(account.accountIdentifier, accountId);
243+
NSString *homeAccountId = [account jsonDictionary][@"additionalProperties"][@"home_account_id"];
244+
XCTAssertEqualObjects(homeAccountId, @"uid.utid");
241245
}
242246

243247
@end

0 commit comments

Comments
 (0)