Skip to content

Instantly share code, notes, and snippets.

@longvudai
Last active July 10, 2022 06:30
Show Gist options
  • Save longvudai/cc0d64abacc83050e12e92a2e591fe52 to your computer and use it in GitHub Desktop.
Save longvudai/cc0d64abacc83050e12e92a2e591fe52 to your computer and use it in GitHub Desktop.
import Firebase
import FirebaseAuth
extension FirebaseApp {
private static var didConfigForAppExtension = false
static func configureFirebaseForAppExtension(
extensionPlistName: String,
accessGroup: String,
force: Bool = false
) {
func configure() {
// Shared firebase auth state for extension
copyContainerFirebaseData()
configureFirebase(plistName: extensionPlistName, accessGroup: accessGroup)
}
if !force {
guard !didConfigForAppExtension else {
return
}
configure()
didConfigForAppExtension = true
} else {
configure()
}
}
static func configureFirebase(plistName: String, accessGroup: String) {
func configure(plistName: String) {
guard
let configURL = Bundle.main.url(forResource: plistName, withExtension: "plist"),
let options = FirebaseOptions(contentsOfFile: configURL.path)
else {
return
}
FirebaseApp.configure(options: options)
}
configure(plistName: plistName)
// In each app, set the access group to the keychain access group or app group
Auth.switchToUsingAppGroup(accessGroup)
Auth.migrateFirebaseAuthToAccessGroupIfNeeded(accessGroup)
}
private static func copyContainerFirebaseData() {
do {
let fileManager = FileManager.default
guard let localFirebaseURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("firebase") else {
assertionFailure("Unable to get shared container")
return
}
try PersistenceSyncManager.shared.copyContentsFromSharedTarget(to: localFirebaseURL)
} catch {
assertionFailure(error.localizedDescription)
}
}
}
private extension FirebaseAuth.Auth {
static func switchToUsingAppGroup(_ accessGroup: String) {
do {
try Auth.auth().useUserAccessGroup(accessGroup)
} catch let error as NSError {
print("Error changing user access group: %@", error)
}
}
// it basically checks if Auth is already using the correct userAccessGroup and
// if so, nothing needs to be done.
// If not, the existing user is temporary saved,
// then Firebase Auth is configured to use the Access Group and then the user is moved to it.
static func migrateFirebaseAuthToAccessGroupIfNeeded(_ accessGroup: String) {
let auth = Auth.auth()
// get current user (so we can migrate later)
guard let user = auth.currentUser else {
print("currentUser is nil")
return
}
if auth.userAccessGroup == accessGroup {
print("Firebase Auth is already using the correct acces group \(accessGroup)")
return
}
print("Firebase Auth is not yet using correct access group \(accessGroup). 🔄 Migrating...")
// for extension (widget) we want to share our auth status
do {
// switch to using app group
try auth.useUserAccessGroup(accessGroup)
// migrate current user
auth.updateCurrentUser(user) { error in
if let error = error {
print("Auth.auth().updateCurrentUser \(error.localizedDescription)")
} else {
print("Firebase Auth user migrated")
}
}
} catch let error as NSError {
print("❌ Error changing user access group \(accessGroup): \(error.localizedDescription)")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment