Skip to content

Commit 71e0502

Browse files
falkobuttlertoto
authored andcommitted
Added support for different keychain groups (multi-user)
1 parent 792c98d commit 71e0502

File tree

5 files changed

+70
-48
lines changed

5 files changed

+70
-48
lines changed

Sources/OAuth2Client/NXOAuth2Account.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ - (NXOAuth2Client *)oauthClient;
8181
NSURL *authorizeURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationAuthorizeURL];
8282
NSURL *tokenURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenURL];
8383
NSString *tokenType = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenType];
84+
NSString *keychainGroup = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenType];
8485
NSDictionary *additionalQueryParams = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters];
8586

8687
oauthClient = [[NXOAuth2Client alloc] initWithClientID:clientID
@@ -89,6 +90,7 @@ - (NXOAuth2Client *)oauthClient;
8990
tokenURL:tokenURL
9091
accessToken:self.accessToken
9192
tokenType:tokenType
93+
keyChainGroup:keychainGroup
9294
persistent:NO
9395
delegate:self];
9496
if (additionalQueryParams) {

Sources/OAuth2Client/NXOAuth2AccountStore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ typedef void(^NXOAuth2PreparedAuthorizationURLHandler)(NSURL *preparedURL);
9393
authorizationURL:(NSURL *)anAuthorizationURL
9494
tokenURL:(NSURL *)aTokenURL
9595
redirectURL:(NSURL *)aRedirectURL
96+
keyChainGroup:(NSString *)aKeyChainGroup
9697
forAccountType:(NSString *)anAccountType;
9798

9899
- (void)setClientID:(NSString *)aClientID
@@ -101,6 +102,7 @@ typedef void(^NXOAuth2PreparedAuthorizationURLHandler)(NSURL *preparedURL);
101102
authorizationURL:(NSURL *)anAuthorizationURL
102103
tokenURL:(NSURL *)aTokenURL
103104
redirectURL:(NSURL *)aRedirectURL
105+
keyChainGroup:(NSString *)aKeyChainGroup
104106
tokenType:(NSString *)aTokenType
105107
forAccountType:(NSString *)anAccountType;
106108

Sources/OAuth2Client/NXOAuth2AccountStore.m

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
NSString * const kNXOAuth2AccountStoreConfigurationScope = @"kNXOAuth2AccountStoreConfigurationScope";
4444
NSString * const kNXOAuth2AccountStoreConfigurationTokenType = @"kNXOAuth2AccountStoreConfigurationTokenType";
4545
NSString * const kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod = @"kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod";
46+
NSString * const kNXOAuth2AccountStoreConfigurationKeyChainGroup = @"kNXOAuth2AccountStoreConfigurationKeyChainGroup";
4647
NSString * const kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters = @"kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters";
4748

4849
#pragma mark Account Type
@@ -104,17 +105,17 @@ - (id)init;
104105
self.configurations = [NSMutableDictionary dictionary];
105106
self.trustModeHandler = [NSMutableDictionary dictionary];
106107
self.trustedCertificatesHandler = [NSMutableDictionary dictionary];
107-
108+
108109
[[NSNotificationCenter defaultCenter] addObserver:self
109110
selector:@selector(accountDidChangeUserData:)
110111
name:NXOAuth2AccountDidChangeUserDataNotification
111112
object:nil];
112-
113+
113114
[[NSNotificationCenter defaultCenter] addObserver:self
114115
selector:@selector(accountDidChangeAccessToken:)
115116
name:NXOAuth2AccountDidChangeAccessTokenNotification
116117
object:nil];
117-
118+
118119
[[NSNotificationCenter defaultCenter] addObserver:self
119120
selector:@selector(accountDidLoseAccessToken:)
120121
name:NXOAuth2AccountDidLoseAccessTokenNotification
@@ -180,17 +181,17 @@ - (void)requestAccessToAccountWithType:(NSString *)accountType
180181
withPreparedAuthorizationURLHandler:(NXOAuth2PreparedAuthorizationURLHandler)aPreparedAuthorizationURLHandler;
181182
{
182183
NSAssert(aPreparedAuthorizationURLHandler, @"Prepared Authorization Handler must not be nil.");
183-
184+
184185
NXOAuth2Client *client = [self pendingOAuthClientForAccountType:accountType];
185-
186+
186187
NSDictionary *configuration;
187188
@synchronized (self.configurations) {
188189
configuration = [self.configurations objectForKey:accountType];
189190
}
190-
191+
191192
NSURL *redirectURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationRedirectURL];
192193
NSURL *preparedURL = [client authorizationURLWithRedirectURL:redirectURL];
193-
194+
194195
aPreparedAuthorizationURLHandler(preparedURL);
195196
}
196197

@@ -247,6 +248,7 @@ - (void)setClientID:(NSString *)aClientID
247248
authorizationURL:(NSURL *)anAuthorizationURL
248249
tokenURL:(NSURL *)aTokenURL
249250
redirectURL:(NSURL *)aRedirectURL
251+
keyChainGroup:(NSString *)aKeyChainGroup
250252
forAccountType:(NSString *)anAccountType;
251253
{
252254
[self setConfiguration:[NSDictionary dictionaryWithObjectsAndKeys:
@@ -255,6 +257,7 @@ - (void)setClientID:(NSString *)aClientID
255257
theScope, kNXOAuth2AccountStoreConfigurationScope,
256258
anAuthorizationURL, kNXOAuth2AccountStoreConfigurationAuthorizeURL,
257259
aTokenURL, kNXOAuth2AccountStoreConfigurationTokenURL,
260+
aKeyChainGroup, kNXOAuth2AccountStoreConfigurationKeyChainGroup,
258261
aRedirectURL, kNXOAuth2AccountStoreConfigurationRedirectURL, nil]
259262
forAccountType:anAccountType];
260263
}
@@ -265,6 +268,7 @@ - (void)setClientID:(NSString *)aClientID
265268
authorizationURL:(NSURL *)anAuthorizationURL
266269
tokenURL:(NSURL *)aTokenURL
267270
redirectURL:(NSURL *)aRedirectURL
271+
keyChainGroup:(NSString *)aKeyChainGroup
268272
tokenType:(NSString *)aTokenType
269273
forAccountType:(NSString *)anAccountType;
270274
{
@@ -275,6 +279,7 @@ - (void)setClientID:(NSString *)aClientID
275279
anAuthorizationURL, kNXOAuth2AccountStoreConfigurationAuthorizeURL,
276280
aTokenURL, kNXOAuth2AccountStoreConfigurationTokenURL,
277281
aTokenType, kNXOAuth2AccountStoreConfigurationTokenType,
282+
aKeyChainGroup, kNXOAuth2AccountStoreConfigurationKeyChainGroup,
278283
aRedirectURL, kNXOAuth2AccountStoreConfigurationRedirectURL, nil]
279284
forAccountType:anAccountType];
280285
}
@@ -286,7 +291,7 @@ - (void)setConfiguration:(NSDictionary *)configuration
286291
NSAssert1([configuration objectForKey:kNXOAuth2AccountStoreConfigurationSecret], @"Missing OAuth2 client secret for account type '%@'.", accountType);
287292
NSAssert1([configuration objectForKey:kNXOAuth2AccountStoreConfigurationAuthorizeURL], @"Missing OAuth2 authorize URL for account type '%@'.", accountType);
288293
NSAssert1([configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenURL], @"Missing OAuth2 token URL for account type '%@'.", accountType);
289-
294+
290295
@synchronized (self.configurations) {
291296
[self.configurations setObject:configuration forKey:accountType];
292297
}
@@ -339,13 +344,13 @@ - (BOOL)handleRedirectURL:(NSURL *)aURL;
339344
{
340345
__block NSURL *fixedRedirectURL = nil;
341346
NSSet *accountTypes;
342-
347+
343348
@synchronized (self.configurations) {
344349
accountTypes = [self.configurations keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
345350
NSDictionary *configuration = obj;
346351
NSURL *redirectURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationRedirectURL];
347352
if ( [[[aURL absoluteString] lowercaseString] hasPrefix:[[redirectURL absoluteString] lowercaseString]]) {
348-
353+
349354
// WORKAROUND: The URL which is passed to this method may be lower case also the scheme is registered in camel case. Therefor replace the prefix with the stored redirectURL.
350355
if (fixedRedirectURL == nil) {
351356
if ([aURL.scheme isEqualToString:redirectURL.scheme]) {
@@ -358,14 +363,14 @@ - (BOOL)handleRedirectURL:(NSURL *)aURL;
358363
withString:redirectURL.absoluteString]];
359364
}
360365
}
361-
366+
362367
return YES;
363368
} else {
364369
return NO;
365370
}
366371
}];
367372
}
368-
373+
369374
for (NSString *accountType in accountTypes) {
370375
NXOAuth2Client *client = [self pendingOAuthClientForAccountType:accountType];
371376
if ([client openRedirectURL:fixedRedirectURL]) {
@@ -383,45 +388,50 @@ - (NXOAuth2Client *)pendingOAuthClientForAccountType:(NSString *)accountType;
383388
NXOAuth2Client *client = nil;
384389
@synchronized (self.pendingOAuthClients) {
385390
client = [self.pendingOAuthClients objectForKey:accountType];
386-
391+
387392
if (!client) {
388393
NSDictionary *configuration;
389394
@synchronized (self.configurations) {
390395
configuration = [self.configurations objectForKey:accountType];
391396
}
392-
397+
393398
NSString *clientID = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationClientID];
394399
NSString *clientSecret = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationSecret];
395400
NSSet *scope = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationScope];
396401
NSURL *authorizeURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationAuthorizeURL];
397402
NSURL *tokenURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenURL];
398403
NSString *tokenType = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenType];
404+
<<<<<<< HEAD
399405
NSString *tokenRequestHTTPMethod = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod];
406+
=======
407+
NSString *keychainGroup = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationKeyChainGroup];
408+
>>>>>>> 13211ba... Added support for different keychain groups (multi-user)
400409
NSDictionary *additionalAuthenticationParameters = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters];
401-
410+
402411
client = [[NXOAuth2Client alloc] initWithClientID:clientID
403412
clientSecret:clientSecret
404413
authorizeURL:authorizeURL
405414
tokenURL:tokenURL
406415
accessToken:nil
407416
tokenType:tokenType
417+
keyChainGroup:keychainGroup
408418
persistent:YES
409419
delegate:self];
410-
420+
411421
client.persistent = NO;
412-
422+
413423
if (tokenRequestHTTPMethod != nil) {
414424
client.tokenRequestHTTPMethod = tokenRequestHTTPMethod;
415425
}
416426
if (additionalAuthenticationParameters != nil) {
417427
NSAssert([additionalAuthenticationParameters isKindOfClass:[NSDictionary class]], @"additionalAuthenticationParameters have to be a NSDictionary");
418428
client.additionalAuthenticationParameters = additionalAuthenticationParameters;
419429
}
420-
430+
421431
if (scope != nil) {
422432
client.desiredScope = scope;
423433
}
424-
434+
425435
[self.pendingOAuthClients setObject:client forKey:accountType];
426436
}
427437
}
@@ -450,15 +460,15 @@ - (NSString *)accountTypeOfPendingOAuthClient:(NXOAuth2Client *)oauthClient;
450460
- (void)oauthClientNeedsAuthentication:(NXOAuth2Client *)client;
451461
{
452462
NSString *accountType = [self accountTypeOfPendingOAuthClient:client];
453-
463+
454464
NSDictionary *configuration;
455465
@synchronized (self.configurations) {
456466
configuration = [self.configurations objectForKey:accountType];
457467
}
458-
468+
459469
NSURL *redirectURL = [configuration objectForKey:kNXOAuth2AccountStoreConfigurationRedirectURL];
460470
NSURL *preparedURL = [client authorizationURLWithRedirectURL:redirectURL];
461-
471+
462472
#if TARGET_OS_IPHONE
463473
[[UIApplication sharedApplication] openURL:preparedURL];
464474
#else
@@ -473,16 +483,16 @@ - (void)oauthClientDidGetAccessToken:(NXOAuth2Client *)client;
473483
accountType = [self accountTypeOfPendingOAuthClient:client];
474484
[self.pendingOAuthClients removeObjectForKey:accountType];
475485
}
476-
486+
477487
NXOAuth2Account *account = [[NXOAuth2Account alloc] initAccountWithOAuthClient:client accountType:accountType];
478488
@synchronized (self.accountsDict) {
479489
[self.accountsDict setValue:account forKey:account.identifier];
480490
[NXOAuth2AccountStore storeAccountsInDefaultKeychain:self.accountsDict];
481491
}
482-
492+
483493
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:account
484494
forKey:NXOAuth2AccountStoreNewAccountUserInfoKey];
485-
495+
486496
[[NSNotificationCenter defaultCenter] postNotificationName:NXOAuth2AccountStoreAccountsDidChangeNotification
487497
object:self
488498
userInfo:userInfo];
@@ -492,7 +502,7 @@ - (void)oauthClientDidLoseAccessToken:(NXOAuth2Client *)client;
492502
{
493503
// This delegate method should never be called because the account store
494504
// does not act as an delegate for established connections.
495-
505+
496506
// If there is one case that was overlooked, we will remove the oauth
497507
// client from the list of pending oauth clients as a precaution.
498508
NSString *accountType;
@@ -509,11 +519,11 @@ - (void)oauthClient:(NXOAuth2Client *)client didFailToGetAccessTokenWithError:(N
509519
accountType = [self accountTypeOfPendingOAuthClient:client];
510520
[self.pendingOAuthClients removeObjectForKey:accountType];
511521
}
512-
522+
513523
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
514524
accountType, kNXOAuth2AccountStoreAccountType,
515525
error, NXOAuth2AccountStoreErrorKey, nil];
516-
526+
517527
[[NSNotificationCenter defaultCenter] postNotificationName:NXOAuth2AccountStoreDidFailToRequestAccessNotification
518528
object:self
519529
userInfo:userInfo];
@@ -579,7 +589,7 @@ + (NSString *)keychainServiceName;
579589
+ (NSDictionary *)accountsFromDefaultKeychain;
580590
{
581591
NSString *serviceName = [self keychainServiceName];
582-
592+
583593
NSDictionary *result = nil;
584594
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
585595
(__bridge NSString *)kSecClassGenericPassword, kSecClass,
@@ -589,21 +599,21 @@ + (NSDictionary *)accountsFromDefaultKeychain;
589599
CFTypeRef cfResult = nil;
590600
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &cfResult);
591601
result = (__bridge_transfer NSDictionary *)cfResult;
592-
602+
593603
if (status != noErr) {
594604
NSAssert1(status == errSecItemNotFound, @"Unexpected error while fetching accounts from keychain: %ld", status);
595605
return nil;
596606
}
597-
607+
598608
return [NSKeyedUnarchiver unarchiveObjectWithData:[result objectForKey:(__bridge NSString *)kSecAttrGeneric]];
599609
}
600610

601611
+ (void)storeAccountsInDefaultKeychain:(NSDictionary *)accounts;
602612
{
603613
[self removeFromDefaultKeychain];
604-
614+
605615
NSString *serviceName = [self keychainServiceName];
606-
616+
607617
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:accounts];
608618
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
609619
(__bridge NSString *)kSecClassGenericPassword, kSecClass,
@@ -632,7 +642,7 @@ + (void)removeFromDefaultKeychain;
632642
+ (NSDictionary *)accountsFromDefaultKeychain;
633643
{
634644
NSString *serviceName = [self keychainServiceName];
635-
645+
636646
SecKeychainItemRef item = nil;
637647
OSStatus err = SecKeychainFindGenericPassword(NULL,
638648
strlen([serviceName UTF8String]),
@@ -646,22 +656,22 @@ + (NSDictionary *)accountsFromDefaultKeychain;
646656
NSAssert1(err == errSecItemNotFound, @"Unexpected error while fetching accounts from keychain: %d", err);
647657
return nil;
648658
}
649-
659+
650660
// from Advanced Mac OS X Programming, ch. 16
651661
UInt32 length;
652662
char *password;
653663
NSData *result = nil;
654664
SecKeychainAttribute attributes[8];
655665
SecKeychainAttributeList list;
656-
666+
657667
attributes[0].tag = kSecAccountItemAttr;
658668
attributes[1].tag = kSecDescriptionItemAttr;
659669
attributes[2].tag = kSecLabelItemAttr;
660670
attributes[3].tag = kSecModDateItemAttr;
661-
671+
662672
list.count = 4;
663673
list.attr = attributes;
664-
674+
665675
err = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);
666676
if (err == noErr) {
667677
if (password != NULL) {
@@ -680,11 +690,11 @@ + (NSDictionary *)accountsFromDefaultKeychain;
680690
+ (void)storeAccountsInDefaultKeychain:(NSDictionary *)accounts;
681691
{
682692
[self removeFromDefaultKeychain];
683-
693+
684694
NSString *serviceName = [self keychainServiceName];
685-
695+
686696
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:accounts];
687-
697+
688698
OSStatus __attribute__((unused))err = SecKeychainAddGenericPassword(NULL,
689699
strlen([serviceName UTF8String]),
690700
[serviceName UTF8String],
@@ -693,14 +703,14 @@ OSStatus __attribute__((unused))err = SecKeychainAddGenericPassword(NULL,
693703
[data length],
694704
[data bytes],
695705
NULL);
696-
706+
697707
NSAssert1(err == noErr, @"Error while storing accounts in keychain: %d", err);
698708
}
699709

700710
+ (void)removeFromDefaultKeychain;
701711
{
702712
NSString *serviceName = [self keychainServiceName];
703-
713+
704714
SecKeychainItemRef item = nil;
705715
OSStatus err = SecKeychainFindGenericPassword(NULL,
706716
strlen([serviceName UTF8String]),

0 commit comments

Comments
 (0)