Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions FirebaseAuth/Sources/Auth/FIRAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -2020,12 +2020,15 @@ - (BOOL)saveUser:(nullable FIRUser *)user error:(NSError *_Nullable *_Nullable)o
}
} else {
if (!user) {
success = [self.storedUserManager removeStoredUserForAccessGroup:self.userAccessGroup
projectIdentifier:self.app.options.APIKey
error:outError];
success =
[self.storedUserManager removeStoredUserForAccessGroup:self.userAccessGroup
shareAuthStateAcrossDevices:self.shareAuthStateAcrossDevices
projectIdentifier:self.app.options.APIKey
error:outError];
} else {
success = [self.storedUserManager setStoredUser:user
forAccessGroup:self.userAccessGroup
shareAuthStateAcrossDevices:self.shareAuthStateAcrossDevices
projectIdentifier:self.app.options.APIKey
error:outError];
}
Expand Down Expand Up @@ -2077,9 +2080,11 @@ - (BOOL)getUser:(FIRUser *_Nullable *)outUser error:(NSError *_Nullable *_Nullab

return YES;
} else {
FIRUser *user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup
projectIdentifier:self.app.options.APIKey
error:error];
FIRUser *user =
[self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup
shareAuthStateAcrossDevices:self.shareAuthStateAcrossDevices
projectIdentifier:self.app.options.APIKey
error:error];
user.auth = self;
*outUser = user;
if (user) {
Expand Down Expand Up @@ -2254,6 +2259,7 @@ - (nullable FIRUser *)getStoredUserForAccessGroup:(NSString *_Nullable)accessGro
user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey];
} else {
user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup
shareAuthStateAcrossDevices:self.shareAuthStateAcrossDevices
projectIdentifier:self.app.options.APIKey
error:outError];
}
Expand Down
8 changes: 8 additions & 0 deletions FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,14 @@ NS_SWIFT_NAME(Auth)
*/
@property(readonly, nonatomic, copy, nullable) NSString *userAccessGroup;

/** @property shareAuthStateAcrossDevices
@brief Contains shareAuthStateAcrossDevices setting related to the auth object.
@remarks If userAccessGroup is not set, setting shareAuthStateAcrossDevices will
have no effect. You should set shareAuthStateAcrossDevices to it's desired
state and then set the userAccessGroup after.
*/
@property(nonatomic) BOOL shareAuthStateAcrossDevices;

/** @property tenantID
@brief The tenant ID of the auth instance. nil if none is available.
*/
Expand Down
15 changes: 12 additions & 3 deletions FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,35 +62,44 @@ NS_ASSUME_NONNULL_BEGIN
/** @fn getStoredUserForAccessGroup:projectID:error:
@brief The getter of the user stored locally.
@param accessGroup The access group to retrieve the user from.
@param shareAuthStateAcrossDevices If true, the keychain will be synced across the end-user's
iCloud.
@param projectIdentifier An identifier of the project that the user associates with. Currently,
we use API KEY.
@param outError Return value for any error which occurs.
*/
- (nullable FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError;

/** @fn setStoredUser:forAccessGroup:projectID:error:
@brief The setter of the user stored locally.
@param user The user to be stored.
@param accessGroup The access group to store the user in.
@param shareAuthStateAcrossDevices If true, the keychain will be synced across the end-user's
iCloud.
@param projectIdentifier An identifier of the project that the user associates with. Currently,
we use API KEY.
@param outError Return value for any error which occurs.
*/
- (BOOL)setStoredUser:(FIRUser *)user
forAccessGroup:(NSString *)accessGroup
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError;
forAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError;

/** @fn removeStoredUserForAccessGroup:projectID:error:
@brief Remove the user that stored locally.
@param accessGroup The access group to remove the user from.
@param shareAuthStateAcrossDevices If true, the keychain will be synced across the end-user's
iCloud.
@param projectIdentifier An identifier of the project that the user associates with. Currently,
we use API KEY.
@param outError Return value for any error which occurs.
*/
- (BOOL)removeStoredUserForAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError;

Expand Down
34 changes: 27 additions & 7 deletions FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ - (BOOL)setStoredUserAccessGroup:(NSString *_Nullable)accessGroup
#pragma mark - User for Access Group

- (FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError {
NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
Expand All @@ -80,6 +81,9 @@ - (FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup
query[(__bridge id)kSecAttrAccessGroup] = accessGroup;
query[(__bridge id)kSecAttrService] = projectIdentifier;
query[(__bridge id)kSecAttrAccount] = kSharedKeychainAccountValue;
if (shareAuthStateAcrossDevices) {
query[(__bridge id)kSecAttrSynchronizable] = (__bridge id)kCFBooleanTrue;
}

NSData *data = [self.keychainServices getItemWithQuery:query error:outError];
// If there's an outError parameter and it's populated, or there's no data, return.
Expand All @@ -105,17 +109,25 @@ - (FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup
}

- (BOOL)setStoredUser:(FIRUser *)user
forAccessGroup:(NSString *)accessGroup
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError {
forAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError {
NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge id)kSecAttrAccessible] =
(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
if (shareAuthStateAcrossDevices) {
query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlock;
} else {
query[(__bridge id)kSecAttrAccessible] =
(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
}

query[(__bridge id)kSecAttrAccessGroup] = accessGroup;
query[(__bridge id)kSecAttrService] = projectIdentifier;
query[(__bridge id)kSecAttrAccount] = kSharedKeychainAccountValue;
if (shareAuthStateAcrossDevices) {
query[(__bridge id)kSecAttrSynchronizable] = (__bridge id)kCFBooleanTrue;
}

#if TARGET_OS_WATCH
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:false];
Expand All @@ -138,12 +150,20 @@ - (BOOL)setStoredUser:(FIRUser *)user
}

- (BOOL)removeStoredUserForAccessGroup:(NSString *)accessGroup
shareAuthStateAcrossDevices:(BOOL)shareAuthStateAcrossDevices
projectIdentifier:(NSString *)projectIdentifier
error:(NSError *_Nullable *_Nullable)outError {
NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge id)kSecAttrAccessible] =
(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
if (shareAuthStateAcrossDevices) {
query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlock;
} else {
query[(__bridge id)kSecAttrAccessible] =
(__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
}
if (shareAuthStateAcrossDevices) {
query[(__bridge id)kSecAttrSynchronizable] = (__bridge id)kCFBooleanTrue;
}

query[(__bridge id)kSecAttrAccessGroup] = accessGroup;
query[(__bridge id)kSecAttrService] = projectIdentifier;
Expand Down