I've successfully set up authentication within my app using Google Sign-In to where I am able to return a Firebase User. I am attempting to set up a Sign-In screen that is only shown when there is no authenticated Firebase User, however with my current code the Sign-In screen is always visible even though I am consistently returning an authenticated user.
I've implemented the didSignInFor function in AppDelegate
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
// ...
if let error = error {
print(error.localizedDescription)
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
// ...
Auth.auth().signIn(with: credential) { (authResult, error) in
if let error = error {
print(error.localizedDescription)
return
}
let session = FirebaseSession.shared
if let user = Auth.auth().currentUser {
session.user = User(uid: user.uid, displayName: user.displayName, email: user.email)
print("User sign in successful: \(user.email!)")
}
}
}
as well as a few lines in didFinishLaunchingWithOptions that sets the isLoggedIn property of my ObservableObject FirebaseSession
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
let auth = Auth.auth()
if auth.currentUser != nil {
FirebaseSession.shared.isLoggedIn = true
print(auth.currentUser?.email!)
} else {
FirebaseSession.shared.isLoggedIn = false
}
//Cache
let settings = FirestoreSettings()
settings.isPersistenceEnabled = false
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
return true
}
My ObservableObject
class FirebaseSession: ObservableObject {
static let shared = FirebaseSession()
init () {}
//MARK: Properties
@Published var user: User?
@Published var isLoggedIn: Bool?
@Published var items: [Thought] = []
var ref: DatabaseReference = Database.database().reference(withPath: "\(String(describing: Auth.auth().currentUser?.uid ?? "Error"))")
//MARK: Functions
func listen() {
_ = Auth.auth().addStateDidChangeListener { (auth, user) in
if auth.currentUser != nil {
self.isLoggedIn = true
}
if let user = user {
self.user = User(uid: user.uid, displayName: user.displayName, email: user.email)
} else {
self.user = nil
}
}
}
}
Finally, I perform my authentication check in the main view of my app here accessing FirebaseSession via my ObservedObject
struct AppView: View {
@ObservedObject var session = FirebaseSession.shared
@State var modalSelection = 1
@State var isPresentingAddThoughtModal = false
var body: some View {
NavigationView {
Group {
if session.isLoggedIn == true {
ThoughtsView()
} else {
SignInView()
}
}
}
}
}
As mentioned above my check doesn't seem to work. Even though my user is authenticated, SignInView is always visible.
How can I successfully check my user authentication each time my app loads?
UPDATE
I am now able to check authentication when the app loads, but after implementing Sohil's solution I am not observing realtime changes to my ObservableObject FirebaseSession. I want to observe changes to FirebaseSession so that after a new user signs in, the body of AppView will be redrawn and present ThoughtsView instead of SignInView. Currently I have to reload the app in order for the check to occur after authentication.
How do I observe changes to FirestoreSession from AppView?