You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Firebase Auth登出后无法重新登录的问题求助

问题描述

在Firestore Auth控制台创建的用户可通过应用正常登录,但通过应用创建用户、登出后再尝试登录时,会抛出错误无法完成登录。

错误信息

Error Domain=FIRAuthErrorDomain Code=17004 "The supplied auth credential is malformed or has expired." UserInfo={NSLocalizedDescription=The supplied auth credential is malformed or has expired., FIRAuthErrorUserInfoNameKey=ERROR_INVALID_CREDENTIAL}

相关代码

主应用代码

import SwiftUI
import Firebase
import Resolver

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
    ) -> Bool {
        FirebaseApp.configure()
        return true
    }
}

@main
struct quizApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

    var body: some Scene {
        WindowGroup {
            SetupView()
        }
    }
}

ContentView

import Resolver
import SwiftUI

extension Resolver: ResolverRegistering {
    public static func registerAllServices() {
        let model = AuthViewModel()

        register {
            model
        }
    }
}

struct ContentView: View {
    @InjectedObject var authViewModel: AuthViewModel

    var body: some View {
        if authViewModel.userSession != nil {
            AppTabView()
        } else {
            LoginView()
        }
    }
}

RegistrationView

import Resolver
import SwiftUI

struct RegisterView: View {
    @InjectedObject var viewModel: AuthViewModel
    @State var name: String = ""
    @State var email: String = ""
    @State var password: String = ""

    var body: some View {
        List {
            TextField("Name", text: $name)
            TextField("Email", text: $email)
                .textInputAutocapitalization(.never)
                .keyboardType(.emailAddress)
                .textCase(.lowercase)
            SecureField("Password", text: $password)
            Spacer()
            Button("Sign Up") {
                Task {
                    try await viewModel.register(name: name, email: email, password: email)
                }
            }
        }
        .navigationTitle("Register")
    }
}

LoginView

import Resolver
import SwiftUI

struct LoginView: View {
    @InjectedObject var viewModel: AuthViewModel
    @State var email: String = ""
    @State var password: String = ""

    var body: some View {
        NavigationStack {
            List {
                TextField("Email", text: $email)
                    .textInputAutocapitalization(.never)
                    .keyboardType(.emailAddress)
                    .textCase(.lowercase)
                SecureField("Password", text: $password)
                Spacer()
                Button("Login") {
                    Task {
                        try await viewModel.login(email: email, password: password)
                    }
                }
                NavigationLink("Sign up") {
                    RegisterView()
                }
            }
            .navigationTitle("Login")
        }
    }
}

AuthViewModel

import SwiftUI
import FirebaseAuth
import FirebaseFirestoreSwift
import FirebaseFirestore

final class AuthViewModel: ObservableObject {
    @Published var userSession: FirebaseAuth.User?
    @Published var currentUser: User?

    init() {
        // Read from Firestore cache on device if logged in
        self.userSession = Auth.auth().currentUser
    }

    func login(email: String, password: String) async throws {
        do {
            let result = try await Auth.auth().signIn(withEmail: email, password: password)
            self.userSession = result.user
            try await fetch()
        } catch {
            print(error)
        }
    }

    func register(name: String, email: String, password: String) async throws {
        do {
            let result = try await Auth.auth().createUser(withEmail: email, password: password)
            self.userSession = result.user

            //
            let user = User(id: result.user.uid, name: name, jlptLevel: 5, email: email)
            let encodeUser = try Firestore.Encoder().encode(user)
            try await Firestore.firestore().collection("users").document(user.id).setData(encodeUser)

            //
            try await fetch()
        } catch {
            print("Failed to create user", error)
        }
    }

    func signout() {
        do {
            try Auth.auth().signOut()
            self.userSession = nil
            self.currentUser = nil
        } catch {
            print(error)
        }
    }

    func deleteAccount() {
        if let session = self.userSession {
            session.delete()
            self.userSession = nil
            self.currentUser = nil
        }
    }

    func fetch() async throws {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let snapshot = try await Firestore.firestore().collection("users").document(uid).getDocument()
        self.currentUser = try snapshot.data(as: User.self)
    }
}
解决方案

问题出在RegistrationView的注册按钮逻辑里:

Button("Sign Up") {
    Task {
        try await viewModel.register(name: name, email: email, password: email)
    }
}

这里调用注册方法时,错误地把email作为password参数传入,导致Firebase用邮箱字符串作为用户密码创建账号。但登录时你输入的是自己设置的密码,两者不匹配,就触发了ERROR_INVALID_CREDENTIAL错误。

只需把参数修正为正确的password即可:

Button("Sign Up") {
    Task {
        try await viewModel.register(name: name, email: email, password: password)
    }
}

修改后重新测试,注册和登录流程就能正常运行。


内容的提问来源于stack exchange,提问作者lacking-cypher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:06:04