43
43
NSString * const kNXOAuth2AccountStoreConfigurationScope = @" kNXOAuth2AccountStoreConfigurationScope" ;
44
44
NSString * const kNXOAuth2AccountStoreConfigurationTokenType = @" kNXOAuth2AccountStoreConfigurationTokenType" ;
45
45
NSString * const kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod = @" kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod" ;
46
+ NSString * const kNXOAuth2AccountStoreConfigurationKeyChainGroup = @" kNXOAuth2AccountStoreConfigurationKeyChainGroup" ;
46
47
NSString * const kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters = @" kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters" ;
47
48
48
49
#pragma mark Account Type
@@ -104,17 +105,17 @@ - (id)init;
104
105
self.configurations = [NSMutableDictionary dictionary ];
105
106
self.trustModeHandler = [NSMutableDictionary dictionary ];
106
107
self.trustedCertificatesHandler = [NSMutableDictionary dictionary ];
107
-
108
+
108
109
[[NSNotificationCenter defaultCenter ] addObserver: self
109
110
selector: @selector (accountDidChangeUserData: )
110
111
name: NXOAuth2AccountDidChangeUserDataNotification
111
112
object: nil ];
112
-
113
+
113
114
[[NSNotificationCenter defaultCenter ] addObserver: self
114
115
selector: @selector (accountDidChangeAccessToken: )
115
116
name: NXOAuth2AccountDidChangeAccessTokenNotification
116
117
object: nil ];
117
-
118
+
118
119
[[NSNotificationCenter defaultCenter ] addObserver: self
119
120
selector: @selector (accountDidLoseAccessToken: )
120
121
name: NXOAuth2AccountDidLoseAccessTokenNotification
@@ -180,17 +181,17 @@ - (void)requestAccessToAccountWithType:(NSString *)accountType
180
181
withPreparedAuthorizationURLHandler : (NXOAuth2PreparedAuthorizationURLHandler)aPreparedAuthorizationURLHandler ;
181
182
{
182
183
NSAssert (aPreparedAuthorizationURLHandler, @" Prepared Authorization Handler must not be nil." );
183
-
184
+
184
185
NXOAuth2Client *client = [self pendingOAuthClientForAccountType: accountType];
185
-
186
+
186
187
NSDictionary *configuration;
187
188
@synchronized (self.configurations ) {
188
189
configuration = [self .configurations objectForKey: accountType];
189
190
}
190
-
191
+
191
192
NSURL *redirectURL = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationRedirectURL ];
192
193
NSURL *preparedURL = [client authorizationURLWithRedirectURL: redirectURL];
193
-
194
+
194
195
aPreparedAuthorizationURLHandler (preparedURL);
195
196
}
196
197
@@ -247,6 +248,7 @@ - (void)setClientID:(NSString *)aClientID
247
248
authorizationURL : (NSURL *)anAuthorizationURL
248
249
tokenURL : (NSURL *)aTokenURL
249
250
redirectURL : (NSURL *)aRedirectURL
251
+ keyChainGroup : (NSString *)aKeyChainGroup
250
252
forAccountType : (NSString *)anAccountType ;
251
253
{
252
254
[self setConfiguration: [NSDictionary dictionaryWithObjectsAndKeys:
@@ -255,6 +257,7 @@ - (void)setClientID:(NSString *)aClientID
255
257
theScope, kNXOAuth2AccountStoreConfigurationScope ,
256
258
anAuthorizationURL, kNXOAuth2AccountStoreConfigurationAuthorizeURL ,
257
259
aTokenURL, kNXOAuth2AccountStoreConfigurationTokenURL ,
260
+ aKeyChainGroup, kNXOAuth2AccountStoreConfigurationKeyChainGroup ,
258
261
aRedirectURL, kNXOAuth2AccountStoreConfigurationRedirectURL , nil ]
259
262
forAccountType: anAccountType];
260
263
}
@@ -265,6 +268,7 @@ - (void)setClientID:(NSString *)aClientID
265
268
authorizationURL : (NSURL *)anAuthorizationURL
266
269
tokenURL : (NSURL *)aTokenURL
267
270
redirectURL : (NSURL *)aRedirectURL
271
+ keyChainGroup : (NSString *)aKeyChainGroup
268
272
tokenType : (NSString *)aTokenType
269
273
forAccountType : (NSString *)anAccountType ;
270
274
{
@@ -275,6 +279,7 @@ - (void)setClientID:(NSString *)aClientID
275
279
anAuthorizationURL, kNXOAuth2AccountStoreConfigurationAuthorizeURL ,
276
280
aTokenURL, kNXOAuth2AccountStoreConfigurationTokenURL ,
277
281
aTokenType, kNXOAuth2AccountStoreConfigurationTokenType ,
282
+ aKeyChainGroup, kNXOAuth2AccountStoreConfigurationKeyChainGroup ,
278
283
aRedirectURL, kNXOAuth2AccountStoreConfigurationRedirectURL , nil ]
279
284
forAccountType: anAccountType];
280
285
}
@@ -286,7 +291,7 @@ - (void)setConfiguration:(NSDictionary *)configuration
286
291
NSAssert1 ([configuration objectForKey: kNXOAuth2AccountStoreConfigurationSecret ], @" Missing OAuth2 client secret for account type '%@ '." , accountType);
287
292
NSAssert1 ([configuration objectForKey: kNXOAuth2AccountStoreConfigurationAuthorizeURL ], @" Missing OAuth2 authorize URL for account type '%@ '." , accountType);
288
293
NSAssert1 ([configuration objectForKey: kNXOAuth2AccountStoreConfigurationTokenURL ], @" Missing OAuth2 token URL for account type '%@ '." , accountType);
289
-
294
+
290
295
@synchronized (self.configurations ) {
291
296
[self .configurations setObject: configuration forKey: accountType];
292
297
}
@@ -339,13 +344,13 @@ - (BOOL)handleRedirectURL:(NSURL *)aURL;
339
344
{
340
345
__block NSURL *fixedRedirectURL = nil ;
341
346
NSSet *accountTypes;
342
-
347
+
343
348
@synchronized (self.configurations ) {
344
349
accountTypes = [self .configurations keysOfEntriesPassingTest: ^(id key, id obj, BOOL *stop) {
345
350
NSDictionary *configuration = obj;
346
351
NSURL *redirectURL = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationRedirectURL ];
347
352
if ( [[[aURL absoluteString ] lowercaseString ] hasPrefix: [[redirectURL absoluteString ] lowercaseString ]]) {
348
-
353
+
349
354
// 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.
350
355
if (fixedRedirectURL == nil ) {
351
356
if ([aURL.scheme isEqualToString: redirectURL.scheme]) {
@@ -358,14 +363,14 @@ - (BOOL)handleRedirectURL:(NSURL *)aURL;
358
363
withString: redirectURL.absoluteString]];
359
364
}
360
365
}
361
-
366
+
362
367
return YES ;
363
368
} else {
364
369
return NO ;
365
370
}
366
371
}];
367
372
}
368
-
373
+
369
374
for (NSString *accountType in accountTypes) {
370
375
NXOAuth2Client *client = [self pendingOAuthClientForAccountType: accountType];
371
376
if ([client openRedirectURL: fixedRedirectURL]) {
@@ -383,45 +388,50 @@ - (NXOAuth2Client *)pendingOAuthClientForAccountType:(NSString *)accountType;
383
388
NXOAuth2Client *client = nil ;
384
389
@synchronized (self.pendingOAuthClients ) {
385
390
client = [self .pendingOAuthClients objectForKey: accountType];
386
-
391
+
387
392
if (!client) {
388
393
NSDictionary *configuration;
389
394
@synchronized (self.configurations ) {
390
395
configuration = [self .configurations objectForKey: accountType];
391
396
}
392
-
397
+
393
398
NSString *clientID = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationClientID ];
394
399
NSString *clientSecret = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationSecret ];
395
400
NSSet *scope = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationScope ];
396
401
NSURL *authorizeURL = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationAuthorizeURL ];
397
402
NSURL *tokenURL = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationTokenURL ];
398
403
NSString *tokenType = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationTokenType ];
404
+ <<<<<<< HEAD
399
405
NSString *tokenRequestHTTPMethod = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod ];
406
+ =======
407
+ NSString *keychainGroup = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationKeyChainGroup ];
408
+ >>>>>>> 13211ba... Added support for different keychain groups (multi-user)
400
409
NSDictionary *additionalAuthenticationParameters = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters ];
401
-
410
+
402
411
client = [[NXOAuth2Client alloc ] initWithClientID: clientID
403
412
clientSecret: clientSecret
404
413
authorizeURL: authorizeURL
405
414
tokenURL: tokenURL
406
415
accessToken: nil
407
416
tokenType: tokenType
417
+ keyChainGroup: keychainGroup
408
418
persistent: YES
409
419
delegate: self ];
410
-
420
+
411
421
client.persistent = NO ;
412
-
422
+
413
423
if (tokenRequestHTTPMethod != nil ) {
414
424
client.tokenRequestHTTPMethod = tokenRequestHTTPMethod;
415
425
}
416
426
if (additionalAuthenticationParameters != nil ) {
417
427
NSAssert ([additionalAuthenticationParameters isKindOfClass: [NSDictionary class ]], @" additionalAuthenticationParameters have to be a NSDictionary" );
418
428
client.additionalAuthenticationParameters = additionalAuthenticationParameters;
419
429
}
420
-
430
+
421
431
if (scope != nil ) {
422
432
client.desiredScope = scope;
423
433
}
424
-
434
+
425
435
[self .pendingOAuthClients setObject: client forKey: accountType];
426
436
}
427
437
}
@@ -450,15 +460,15 @@ - (NSString *)accountTypeOfPendingOAuthClient:(NXOAuth2Client *)oauthClient;
450
460
- (void )oauthClientNeedsAuthentication : (NXOAuth2Client *)client ;
451
461
{
452
462
NSString *accountType = [self accountTypeOfPendingOAuthClient: client];
453
-
463
+
454
464
NSDictionary *configuration;
455
465
@synchronized (self.configurations ) {
456
466
configuration = [self .configurations objectForKey: accountType];
457
467
}
458
-
468
+
459
469
NSURL *redirectURL = [configuration objectForKey: kNXOAuth2AccountStoreConfigurationRedirectURL ];
460
470
NSURL *preparedURL = [client authorizationURLWithRedirectURL: redirectURL];
461
-
471
+
462
472
#if TARGET_OS_IPHONE
463
473
[[UIApplication sharedApplication ] openURL: preparedURL];
464
474
#else
@@ -473,16 +483,16 @@ - (void)oauthClientDidGetAccessToken:(NXOAuth2Client *)client;
473
483
accountType = [self accountTypeOfPendingOAuthClient: client];
474
484
[self .pendingOAuthClients removeObjectForKey: accountType];
475
485
}
476
-
486
+
477
487
NXOAuth2Account *account = [[NXOAuth2Account alloc ] initAccountWithOAuthClient: client accountType: accountType];
478
488
@synchronized (self.accountsDict ) {
479
489
[self .accountsDict setValue: account forKey: account.identifier];
480
490
[NXOAuth2AccountStore storeAccountsInDefaultKeychain: self .accountsDict];
481
491
}
482
-
492
+
483
493
NSDictionary *userInfo = [NSDictionary dictionaryWithObject: account
484
494
forKey: NXOAuth2AccountStoreNewAccountUserInfoKey];
485
-
495
+
486
496
[[NSNotificationCenter defaultCenter ] postNotificationName: NXOAuth2AccountStoreAccountsDidChangeNotification
487
497
object: self
488
498
userInfo: userInfo];
@@ -492,7 +502,7 @@ - (void)oauthClientDidLoseAccessToken:(NXOAuth2Client *)client;
492
502
{
493
503
// This delegate method should never be called because the account store
494
504
// does not act as an delegate for established connections.
495
-
505
+
496
506
// If there is one case that was overlooked, we will remove the oauth
497
507
// client from the list of pending oauth clients as a precaution.
498
508
NSString *accountType;
@@ -509,11 +519,11 @@ - (void)oauthClient:(NXOAuth2Client *)client didFailToGetAccessTokenWithError:(N
509
519
accountType = [self accountTypeOfPendingOAuthClient: client];
510
520
[self .pendingOAuthClients removeObjectForKey: accountType];
511
521
}
512
-
522
+
513
523
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
514
524
accountType, kNXOAuth2AccountStoreAccountType ,
515
525
error, NXOAuth2AccountStoreErrorKey, nil ];
516
-
526
+
517
527
[[NSNotificationCenter defaultCenter ] postNotificationName: NXOAuth2AccountStoreDidFailToRequestAccessNotification
518
528
object: self
519
529
userInfo: userInfo];
@@ -579,7 +589,7 @@ + (NSString *)keychainServiceName;
579
589
+ (NSDictionary *)accountsFromDefaultKeychain ;
580
590
{
581
591
NSString *serviceName = [self keychainServiceName ];
582
-
592
+
583
593
NSDictionary *result = nil ;
584
594
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
585
595
(__bridge NSString *)kSecClassGenericPassword , kSecClass ,
@@ -589,21 +599,21 @@ + (NSDictionary *)accountsFromDefaultKeychain;
589
599
CFTypeRef cfResult = nil ;
590
600
OSStatus status = SecItemCopyMatching ((__bridge CFDictionaryRef)query, &cfResult);
591
601
result = (__bridge_transfer NSDictionary *)cfResult;
592
-
602
+
593
603
if (status != noErr) {
594
604
NSAssert1 (status == errSecItemNotFound, @" Unexpected error while fetching accounts from keychain: %ld " , status);
595
605
return nil ;
596
606
}
597
-
607
+
598
608
return [NSKeyedUnarchiver unarchiveObjectWithData: [result objectForKey: (__bridge NSString *)kSecAttrGeneric ]];
599
609
}
600
610
601
611
+ (void )storeAccountsInDefaultKeychain : (NSDictionary *)accounts ;
602
612
{
603
613
[self removeFromDefaultKeychain ];
604
-
614
+
605
615
NSString *serviceName = [self keychainServiceName ];
606
-
616
+
607
617
NSData *data = [NSKeyedArchiver archivedDataWithRootObject: accounts];
608
618
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
609
619
(__bridge NSString *)kSecClassGenericPassword , kSecClass ,
@@ -632,7 +642,7 @@ + (void)removeFromDefaultKeychain;
632
642
+ (NSDictionary *)accountsFromDefaultKeychain ;
633
643
{
634
644
NSString *serviceName = [self keychainServiceName ];
635
-
645
+
636
646
SecKeychainItemRef item = nil ;
637
647
OSStatus err = SecKeychainFindGenericPassword (NULL ,
638
648
strlen ([serviceName UTF8String ]),
@@ -646,22 +656,22 @@ + (NSDictionary *)accountsFromDefaultKeychain;
646
656
NSAssert1 (err == errSecItemNotFound, @" Unexpected error while fetching accounts from keychain: %d " , err);
647
657
return nil ;
648
658
}
649
-
659
+
650
660
// from Advanced Mac OS X Programming, ch. 16
651
661
UInt32 length;
652
662
char *password;
653
663
NSData *result = nil ;
654
664
SecKeychainAttribute attributes[8 ];
655
665
SecKeychainAttributeList list;
656
-
666
+
657
667
attributes[0 ].tag = kSecAccountItemAttr ;
658
668
attributes[1 ].tag = kSecDescriptionItemAttr ;
659
669
attributes[2 ].tag = kSecLabelItemAttr ;
660
670
attributes[3 ].tag = kSecModDateItemAttr ;
661
-
671
+
662
672
list.count = 4 ;
663
673
list.attr = attributes;
664
-
674
+
665
675
err = SecKeychainItemCopyContent (item, NULL , &list, &length, (void **)&password);
666
676
if (err == noErr) {
667
677
if (password != NULL ) {
@@ -680,11 +690,11 @@ + (NSDictionary *)accountsFromDefaultKeychain;
680
690
+ (void )storeAccountsInDefaultKeychain : (NSDictionary *)accounts ;
681
691
{
682
692
[self removeFromDefaultKeychain ];
683
-
693
+
684
694
NSString *serviceName = [self keychainServiceName ];
685
-
695
+
686
696
NSData *data = [NSKeyedArchiver archivedDataWithRootObject: accounts];
687
-
697
+
688
698
OSStatus __attribute__ ((unused))err = SecKeychainAddGenericPassword (NULL ,
689
699
strlen ([serviceName UTF8String ]),
690
700
[serviceName UTF8String ],
@@ -693,14 +703,14 @@ OSStatus __attribute__((unused))err = SecKeychainAddGenericPassword(NULL,
693
703
[data length ],
694
704
[data bytes ],
695
705
NULL );
696
-
706
+
697
707
NSAssert1 (err == noErr, @" Error while storing accounts in keychain: %d " , err);
698
708
}
699
709
700
710
+ (void )removeFromDefaultKeychain ;
701
711
{
702
712
NSString *serviceName = [self keychainServiceName ];
703
-
713
+
704
714
SecKeychainItemRef item = nil ;
705
715
OSStatus err = SecKeychainFindGenericPassword (NULL ,
706
716
strlen ([serviceName UTF8String ]),
0 commit comments