使用共享用户访问组时,Firebase Auth 用户已过时
Posted
技术标签:
【中文标题】使用共享用户访问组时,Firebase Auth 用户已过时【英文标题】:Firebase Auth user is outdated when using shared user access group 【发布时间】:2021-03-10 05:16:30 【问题描述】:在应用与其小部件扩展之间共享身份验证状态,但有时身份验证状态不同步。当用户从我的应用程序登录/注销时,它会刷新小部件时间线,然后检查身份验证状态以显示正确的项目。但是,如果我将用户注销,有时对 Auth.auth().currentUser 的调用仍会返回有效用户。
我已确认这两个应用都在同一个用户访问组中,并且我已在每个目标的功能中启用了该应用组。一组更新身份验证状态与另一组可以访问该状态之间是否存在延迟?
小部件代码
struct Provider: TimelineProvider
...
func getTimeline(in context: Context, completion: @escaping (Timeline<BirthdaysEntry>) -> Void)
if let uid = Auth.auth().currentUser?.uid
// fetch data from firestore
else
// logged out
...
@main
struct MyWidget: Widget
private let kind = "my_widget"
init()
FirebaseApp.configure()
if Auth.auth().userAccessGroup == nil
do
try Auth.auth().useUserAccessGroup("group.com.****.******")
catch let error as NSError
...
var body: some WidgetConfiguration
StaticConfiguration(kind: kind, provider: Provider()) entry in
WidgetEntryView(entry: entry)
应用代码
// part of main file
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
FirebaseApp.configure()
...
// migrate to shared keychain
if Auth.auth().userAccessGroup == nil
let user = Auth.auth().currentUser
do
try Auth.auth().useUserAccessGroup("group.com.****.****") // same group
catch let error as NSError
...
// when we switch to app group, user will be set to nil, so
// if user is logged in, update them in the app group
if user != nil
Auth.auth().updateCurrentUser(user!) (err) in
if let err = err
print(err.localizedDescription)
return true
// in a viewmodel somewhere else
Auth.auth().addStateDidChangeListener [weak self] (auth, user) in
WidgetCenter.shared.reloadTimelines(ofKind: "my_widget")
....
【问题讨论】:
【参考方案1】:文档说明:
注意:共享钥匙串不会跨应用实时自动更新用户。如果您在一个应用中对用户进行了更改,则必须在任何其他共享钥匙串应用中重新加载该用户,然后才能看到更改。
这里有一些代码可以帮助您入门:
func refreshUser()
do
let currentUser = Auth.auth().currentUser
let sharedUser = try Auth.auth().getStoredUser(forAccessGroup: accessGroup)
print("Current user: \(String(describing: currentUser)), shared User: \(sharedUser.uid)")
if currentUser != sharedUser
updateUser(user: sharedUser)
catch
do
try Auth.auth().signOut()
catch
print("Error when trying to sign out: \(error.localizedDescription)")
func updateUser(user: User)
Auth.auth().updateCurrentUser(user) error in
if let error = error
print("Error when trying to update the user: \(error.localizedDescription)")
以下代码展示了如何在您的主 SwiftUI 应用程序中使用它,但可以轻松地适应 Widget:
var body: some Scene
WindowGroup
ContentView()
.environmentObject(authenticationService)
.onChange(of: scenePhase) phase in
print("Current phase \(phase)")
if let user = Auth.auth().currentUser
print("User: \(user.uid)")
else
print("No user present")
if phase == .active
// Uncomment this to refresh the user once the app becomes active
authenticationService.refreshUser()
【讨论】:
这太好了,谢谢彼得。今天晚些时候我可以测试它后我会接受。如果我从我的 getTimeline() 函数运行 refreshUser() 会很糟糕,还是应该在视图模型中使用它?以上是关于使用共享用户访问组时,Firebase Auth 用户已过时的主要内容,如果未能解决你的问题,请参考以下文章
使用 auth.uid 限制对 Firebase-Database 的访问不起作用
使用 Firebase Auth 访问 Google Calendar API