Skip to content

Commit 3aff8d0

Browse files
author
Chuan Ren
authored
Add support of sso (#2684)
1 parent 1e29a34 commit 3aff8d0

15 files changed

+549
-103
lines changed

Example/Auth/Sample/SettingsViewController.m

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
@"GoogleService-Info_multi"
5959
};
6060

61+
/** @var kSharedKeychainAccessGroup
62+
@brief The shared keychain access group for testing.
63+
*/
64+
static NSString *const kSharedKeychainAccessGroup = @"com.google.firebase.auth.keychainGroup1";
65+
6166
/** @var gAPIEndpoints
6267
@brief List of API Hosts by request class name.
6368
*/
@@ -155,6 +160,9 @@ - (void)setUpFirebaseAppOptions {
155160
}
156161

157162
- (void)loadTableView {
163+
NSString *appIdentifierPrefix = NSBundle.mainBundle.infoDictionary[@"AppIdentifierPrefix"];
164+
NSString *fullKeychainAccessGroup = [appIdentifierPrefix stringByAppendingString:kSharedKeychainAccessGroup];
165+
158166
__weak typeof(self) weakSelf = self;
159167
_tableViewManager.contents = [StaticContentTableViewContent contentWithSections:@[
160168
[StaticContentTableViewSection sectionWithTitle:@"Versions" cells:@[
@@ -191,6 +199,23 @@ - (void)loadTableView {
191199
[weakSelf toggleProjectForAppAtIndex:1];
192200
}],
193201
]],
202+
[StaticContentTableViewSection sectionWithTitle:@"Keychain Access Groups" cells:@[
203+
[StaticContentTableViewCell cellWithTitle:@"Current Access Group"
204+
value:[AppManager auth].userAccessGroup ? [AppManager auth].userAccessGroup : @"[none]"
205+
],
206+
[StaticContentTableViewCell cellWithTitle:@"Default Group"
207+
value:@"[none]"
208+
action:^{
209+
[[AppManager auth] useUserAccessGroup:nil error:nil];
210+
[self loadTableView];
211+
}],
212+
[StaticContentTableViewCell cellWithTitle:@"Shared Group"
213+
value:fullKeychainAccessGroup
214+
action:^{
215+
[[AppManager auth] useUserAccessGroup:fullKeychainAccessGroup error:nil];
216+
[self loadTableView];
217+
}],
218+
]],
194219
[StaticContentTableViewSection sectionWithTitle:@"Phone Auth" cells:@[
195220
[StaticContentTableViewCell cellWithTitle:@"APNs Token"
196221
value:[self APNSTokenString]
@@ -281,19 +306,14 @@ - (NSString *)projectIDForAppAtIndex:(int)index {
281306
return @"[none]";
282307
}
283308

284-
/** @fn googleAppIDForAppAtIndex:
285-
@brief Returns the Google App ID for the Firebase app at the given index.
286-
@param index The index for the app in the app manager.
287-
@return The Google App ID of the project.
309+
/** @fn projectIDForAppAtIndex:
310+
@brief Returns the Firebase project ID for the Firebase app at the given index.
311+
@param index The index for the app in the app manager.
312+
@return The ID of the project.
288313
*/
289-
- (NSString *)googleAppIDForAppAtIndex:(int)index {
290-
NSString *APIKey = [[AppManager sharedInstance] appAtIndex:index].options.APIKey;
291-
for (FIROptions *options in gFirebaseAppOptions) {
292-
if ([options.APIKey isEqualToString:APIKey]) {
293-
return options.googleAppID;
294-
}
295-
}
296-
return @"[none]";
314+
- (NSString *)keychainAccessGroupAtIndex:(int)index {
315+
NSArray *array = @[@"123", @"456"];
316+
return array[index];
297317
}
298318

299319
/** @fn toggleProjectForAppAtIndex:

Example/Auth/Tests/FIRAuthUserDefaultsStorageTests.m

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
#import "FIRAuthUserDefaultsStorage.h"
2020

21-
#if FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
22-
2321
NS_ASSUME_NONNULL_BEGIN
2422

2523
/** @var kKey
@@ -151,5 +149,3 @@ - (void)testStandardUserDefaults {
151149
@end
152150

153151
NS_ASSUME_NONNULL_END
154-
155-
#endif // FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE

Firebase/Auth/Source/FIRAuth.m

Lines changed: 141 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#import "FIRAuthKeychain.h"
4343
#import "FIRAuthOperationType.h"
4444
#import "FIRAuthSettings.h"
45+
#import "FIRAuthStoredUserManager.h"
4546
#import "FIRUser_Internal.h"
4647
#import "FirebaseAuth.h"
4748
#import "FIRAuthBackend.h"
@@ -245,6 +246,11 @@ @interface FIRAuth () <FIRLibrary, FIRComponentLifecycleMaintainer>
245246
*/
246247
@property(nonatomic, copy, nullable) NSString *additionalFrameworkMarker;
247248

249+
/** @property storedUserManager
250+
@brief The stored user manager.
251+
*/
252+
@property(nonatomic, strong, nullable) FIRAuthStoredUserManager *storedUserManager;
253+
248254
/** @fn initWithApp:
249255
@brief Creates a @c FIRAuth instance associated with the provided @c FIRApp instance.
250256
@param app The application to associate the auth instance with.
@@ -390,11 +396,29 @@ - (nullable instancetype)initWithAPIKey:(NSString *)APIKey appName:(NSString *)a
390396
if (keychainServiceName) {
391397
strongSelf->_keychain = [[FIRAuthKeychain alloc] initWithService:keychainServiceName];
392398
}
393-
FIRUser *user;
399+
400+
strongSelf.storedUserManager =
401+
[[FIRAuthStoredUserManager alloc] initWithServiceName:keychainServiceName];
402+
394403
NSError *error;
395-
if ([strongSelf getUser:&user error:&error]) {
396-
[strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error];
397-
self->_lastNotifiedUserToken = user.rawAccessToken;
404+
NSString *storedUserAccessGroup = [strongSelf.storedUserManager getStoredUserAccessGroupWithError:&error];
405+
if (!error) {
406+
if (!storedUserAccessGroup) {
407+
FIRUser *user;
408+
if ([strongSelf getUser:&user error:&error]) {
409+
[strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error];
410+
self->_lastNotifiedUserToken = user.rawAccessToken;
411+
} else {
412+
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
413+
@"Error loading saved user when starting up: %@", error);
414+
}
415+
} else {
416+
[strongSelf useUserAccessGroup:storedUserAccessGroup error:&error];
417+
if (error) {
418+
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
419+
@"Error loading saved user when starting up: %@", error);
420+
}
421+
}
398422
} else {
399423
FIRLogError(kFIRLoggerAuth, @"I-AUT000001",
400424
@"Error loading saved user when starting up: %@", error);
@@ -1855,26 +1879,40 @@ - (BOOL)updateCurrentUser:(nullable FIRUser *)user
18551879
/** @fn saveUser:error:
18561880
@brief Persists user.
18571881
@param user The user to save.
1858-
@param error Return value for any error which occurs.
1882+
@param outError Return value for any error which occurs.
18591883
@return @YES on success, @NO otherwise.
18601884
*/
18611885
- (BOOL)saveUser:(FIRUser *)user
1862-
error:(NSError *_Nullable *_Nullable)error {
1886+
error:(NSError *_Nullable *_Nullable)outError {
18631887
BOOL success;
1864-
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
18651888

1866-
if (!user) {
1867-
success = [_keychain removeDataForKey:userKey error:error];
1889+
if (!self.userAccessGroup) {
1890+
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
1891+
if (!user) {
1892+
success = [_keychain removeDataForKey:userKey error:outError];
1893+
} else {
1894+
// Encode the user object.
1895+
NSMutableData *archiveData = [NSMutableData data];
1896+
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];
1897+
[archiver encodeObject:user forKey:userKey];
1898+
[archiver finishEncoding];
1899+
1900+
// Save the user object's encoded value.
1901+
success = [_keychain setData:archiveData forKey:userKey error:outError];
1902+
}
18681903
} else {
1869-
// Encode the user object.
1870-
NSMutableData *archiveData = [NSMutableData data];
1871-
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];
1872-
[archiver encodeObject:user forKey:userKey];
1873-
[archiver finishEncoding];
1874-
1875-
// Save the user object's encoded value.
1876-
success = [_keychain setData:archiveData forKey:userKey error:error];
1904+
if (!user) {
1905+
success = [self.storedUserManager removeStoredUserForAccessGroup:self.userAccessGroup
1906+
projectIdentifier:self.app.options.APIKey
1907+
error:outError];
1908+
} else {
1909+
success = [self.storedUserManager setStoredUser:user
1910+
forAccessGroup:self.userAccessGroup
1911+
projectIdentifier:self.app.options.APIKey
1912+
error:outError];
1913+
}
18771914
}
1915+
18781916
return success;
18791917
}
18801918

@@ -1887,26 +1925,44 @@ - (BOOL)saveUser:(FIRUser *)user
18871925
*/
18881926
- (BOOL)getUser:(FIRUser *_Nullable *)outUser
18891927
error:(NSError *_Nullable *_Nullable)error {
1890-
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
1928+
if (!self.userAccessGroup) {
1929+
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
18911930

1892-
NSError *keychainError;
1893-
NSData *encodedUserData = [_keychain dataForKey:userKey error:&keychainError];
1894-
if (keychainError) {
1895-
if (error) {
1896-
*error = keychainError;
1931+
NSError *keychainError;
1932+
NSData *encodedUserData = [_keychain dataForKey:userKey error:&keychainError];
1933+
if (keychainError) {
1934+
if (error) {
1935+
*error = keychainError;
1936+
}
1937+
return NO;
18971938
}
1898-
return NO;
1899-
}
1900-
if (!encodedUserData) {
1901-
*outUser = nil;
1939+
if (!encodedUserData) {
1940+
*outUser = nil;
1941+
return YES;
1942+
}
1943+
NSKeyedUnarchiver *unarchiver =
1944+
[[NSKeyedUnarchiver alloc] initForReadingWithData:encodedUserData];
1945+
FIRUser *user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey];
1946+
user.auth = self;
1947+
*outUser = user;
1948+
19021949
return YES;
1950+
} else {
1951+
FIRUser *user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup
1952+
projectIdentifier:self.app.options.APIKey
1953+
error:error];
1954+
user.auth = self;
1955+
*outUser = user;
1956+
if (user) {
1957+
return YES;
1958+
} else {
1959+
if (error && *error) {
1960+
return NO;
1961+
} else {
1962+
return YES;
1963+
}
1964+
}
19031965
}
1904-
NSKeyedUnarchiver *unarchiver =
1905-
[[NSKeyedUnarchiver alloc] initForReadingWithData:encodedUserData];
1906-
FIRUser *user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey];
1907-
user.auth = self;
1908-
*outUser = user;
1909-
return YES;
19101966
}
19111967

19121968
#pragma mark - Interoperability
@@ -2011,6 +2067,58 @@ - (nullable NSString *)getUserID {
20112067
return _currentUser.uid;
20122068
}
20132069

2070+
#pragma mark - Keychain sharing
2071+
2072+
- (BOOL)useUserAccessGroup:(NSString *_Nullable)accessGroup
2073+
error:(NSError *_Nullable *_Nullable)outError {
2074+
BOOL success;
2075+
success = [self.storedUserManager setStoredUserAccessGroup:accessGroup error:outError];
2076+
if (!success) {
2077+
return NO;
2078+
}
2079+
2080+
FIRUser *user = [self getStoredUserForAccessGroup:accessGroup error:outError];
2081+
if (!user && outError && *outError) {
2082+
return NO;
2083+
}
2084+
success = [self updateCurrentUser:user byForce:NO savingToDisk:NO error:outError];
2085+
if (!success) {
2086+
return NO;
2087+
}
2088+
2089+
if(_userAccessGroup == nil && accessGroup != nil) {
2090+
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
2091+
[_keychain removeDataForKey:userKey error:outError];
2092+
}
2093+
_userAccessGroup = accessGroup;
2094+
self->_lastNotifiedUserToken = user.rawAccessToken;
2095+
2096+
return YES;
2097+
}
2098+
2099+
- (FIRUser *)getStoredUserForAccessGroup:(NSString *_Nullable)accessGroup
2100+
error:(NSError *_Nullable *_Nullable)outError {
2101+
FIRUser *user;
2102+
if (!accessGroup) {
2103+
NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName];
2104+
NSData *encodedUserData = [_keychain dataForKey:userKey error:outError];
2105+
if (!encodedUserData) {
2106+
return nil;
2107+
}
2108+
2109+
NSKeyedUnarchiver *unarchiver =
2110+
[[NSKeyedUnarchiver alloc] initForReadingWithData:encodedUserData];
2111+
user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey];
2112+
user.auth = self;
2113+
} else {
2114+
user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup
2115+
projectIdentifier:self.app.options.APIKey
2116+
error:outError];
2117+
}
2118+
2119+
return user;
2120+
}
2121+
20142122
@end
20152123

20162124
NS_ASSUME_NONNULL_END

Firebase/Auth/Source/FIRAuthKeychain.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,33 @@ NS_ASSUME_NONNULL_BEGIN
6565
@brief The utility class to manipulate data in iOS Keychain.
6666
*/
6767
@interface FIRAuthKeychain : NSObject <FIRAuthStorage>
68+
69+
/** @fn getItemWithQuery:error:
70+
@brief Get the item from keychain by given query.
71+
@param query The query to query the keychain.
72+
@param outError The address to store any error that occurs during the process, if not nil.
73+
@return The item of the given query. nil if not exsit.
74+
*/
75+
- (NSData *)getItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError;
76+
77+
/** @fn setItem:withQuery:error:
78+
@brief Set the item into keychain with given query.
79+
@param item The item to be added into keychain.
80+
@param query The query to query the keychain.
81+
@param outError The address to store any error that occurs during the process, if not nil.
82+
@return Whether the operation succeed.
83+
*/
84+
- (BOOL)setItem:(NSData *)item withQuery:(NSDictionary *)query
85+
error:(NSError *_Nullable *_Nullable)outError;
86+
87+
/** @fn getItemWithQuery:error:
88+
@brief Remove the item with given queryfrom keychain.
89+
@param query The query to query the keychain.
90+
@param outError The address to store any error that occurs during the process, if not nil.
91+
@return Whether the operation succeed.
92+
*/
93+
- (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError;
94+
6895
@end
6996

7097
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)