Skip to content

feat(auth): Implement UseUserAccessGroup for C++ iOS SDK #1749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
9 changes: 9 additions & 0 deletions auth/src/android/auth_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,15 @@ void Auth::UseEmulator(std::string host, uint32_t port) {
SetEmulatorJni(auth_data_, host.c_str(), port);
}

AuthError Auth::UseUserAccessGroup(const char* access_group) {
// This is an iOS-only feature. No-op on Android.
(void)access_group; // Mark as unused
LogWarning(
"UseUserAccessGroup is an iOS-only feature and has no effect on "
"Android.");
return kAuthErrorNone;
}

// Not implemented for Android.
void EnableTokenAutoRefresh(AuthData* auth_data) {}
void DisableTokenAutoRefresh(AuthData* auth_data) {}
Expand Down
9 changes: 9 additions & 0 deletions auth/src/desktop/auth_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,15 @@ void Auth::UseEmulator(std::string host, uint32_t port) {
auth_impl->assigned_emulator_url.append(std::to_string(port));
}

AuthError Auth::UseUserAccessGroup(const char* access_group) {
// This is an iOS-only feature. No-op on Desktop.
(void)access_group; // Mark as unused
LogWarning(
"UseUserAccessGroup is an iOS-only feature and has no effect on "
"Desktop.");
return kAuthErrorNone;
}

void InitializeTokenRefresher(AuthData* auth_data) {
auto auth_impl = static_cast<AuthImpl*>(auth_data->auth_impl);
auth_impl->token_refresh_thread.Initialize(auth_data);
Expand Down
32 changes: 32 additions & 0 deletions auth/src/include/firebase/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,38 @@ class Auth {
/// Get results of the most recent call to SendPasswordResetEmail.
Future<void> SendPasswordResetEmailLastResult() const;

/// @brief Sets the user access group to use for keychain data sharing.
///
/// This method is only functional on iOS and tvOS. On other platforms, it is
/// a no-op and will return `kAuthErrorNone`.
///
/// Allows you to specify a keychain access group to be used for sharing
/// authentication state across multiple apps from the same publisher.
/// Calling this method will switch the underlying data persistence for the
/// current Auth instance to the specified access group.
///
/// If `access_group` is `nullptr` or an empty string, the access group will
/// be cleared and the default persistence (isolated to the app) will be
/// used.
///
/// @param[in] access_group The keychain access group string (e.g.,
/// "com.example.mygroup"). Pass `nullptr` or an empty string to reset to
/// the default app-specific keychain.
///
/// @return `kAuthErrorNone` on success.
/// Returns `kAuthErrorKeychainError` if an error occurs while
/// accessing the keychain (iOS/tvOS only).
/// Returns `kAuthErrorUnimplemented` if called on a platform other
Copy link
Contributor Author

@jonsimantov jonsimantov Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual stub methods return kAuthErrorNone, please fix this comment.

/// than iOS or tvOS, though current stub implementations return
/// `kAuthErrorNone`.
///
/// @note On tvOS, if `shareAuthStateAcrossDevices` is set to `true`,
/// attempting to set an access group may have specific behaviors or
/// limitations as outlined in the Firebase iOS SDK documentation. Refer to
/// the official Firebase documentation for `[FIRAuth
/// useUserAccessGroup:error:]` for more details.
AuthError UseUserAccessGroup(const char* access_group);

#ifndef SWIG
/// @brief Registers a listener to changes in the authentication state.
///
Expand Down
20 changes: 20 additions & 0 deletions auth/src/ios/auth_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -608,5 +608,25 @@ void DisableTokenAutoRefresh(AuthData *auth_data) {}
void InitializeTokenRefresher(AuthData *auth_data) {}
void DestroyTokenRefresher(AuthData *auth_data) {}

AuthError Auth::UseUserAccessGroup(const char *access_group) {
if (!auth_data_ || !AuthImpl(auth_data_)) {
return kAuthErrorUninitialized;
}

NSString *ns_access_group = nil;
if (access_group && strlen(access_group) > 0) {
ns_access_group = [NSString stringWithUTF8String:access_group];
}

NSError *error = nil;
BOOL success = [AuthImpl(auth_data_) useUserAccessGroup:ns_access_group error:&error];

if (success) {
return kAuthErrorNone;
} else {
return AuthErrorFromNSError(error);
}
}

} // namespace auth
} // namespace firebase
Loading