diff --git a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift index 61e5693f374..c0395182268 100644 --- a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift +++ b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift @@ -15,11 +15,13 @@ import FirebaseCore import Foundation +// TODO(Swift 6 Breaking): Make checked Sendable. + /// A concrete implementation of `AuthProvider` for phone auth providers. /// /// This class is available on iOS only. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) -@objc(FIRPhoneAuthProvider) open class PhoneAuthProvider: NSObject { +@objc(FIRPhoneAuthProvider) open class PhoneAuthProvider: NSObject, @unchecked Sendable { /// A string constant identifying the phone identity provider. @objc public static let id = "phone" private static let recaptchaVersion = "RECAPTCHA_ENTERPRISE" @@ -56,7 +58,7 @@ import Foundation @objc(verifyPhoneNumber:UIDelegate:completion:) open func verifyPhoneNumber(_ phoneNumber: String, uiDelegate: AuthUIDelegate? = nil, - completion: ((_: String?, _: Error?) -> Void)?) { + completion: (@MainActor (String?, Error?) -> Void)?) { verifyPhoneNumber(phoneNumber, uiDelegate: uiDelegate, multiFactorSession: nil, @@ -75,7 +77,7 @@ import Foundation open func verifyPhoneNumber(_ phoneNumber: String, uiDelegate: AuthUIDelegate? = nil, multiFactorSession: MultiFactorSession? = nil, - completion: ((_: String?, _: Error?) -> Void)?) { + completion: (@MainActor (String?, Error?) -> Void)?) { Task { do { let verificationID = try await verifyPhoneNumber( @@ -83,13 +85,9 @@ import Foundation uiDelegate: uiDelegate, multiFactorSession: multiFactorSession ) - await MainActor.run { - completion?(verificationID, nil) - } + await completion?(verificationID, nil) } catch { - await MainActor.run { - completion?(nil, error) - } + await completion?(nil, error) } } } @@ -135,7 +133,7 @@ import Foundation open func verifyPhoneNumber(with multiFactorInfo: PhoneMultiFactorInfo, uiDelegate: AuthUIDelegate? = nil, multiFactorSession: MultiFactorSession?, - completion: ((_: String?, _: Error?) -> Void)?) { + completion: ((String?, Error?) -> Void)?) { Task { do { let verificationID = try await verifyPhoneNumber( @@ -641,7 +639,6 @@ import Foundation private let auth: Auth private let callbackScheme: String private let usingClientIDScheme: Bool - private var recaptchaVerifier: AuthRecaptchaVerifier? init(auth: Auth) { self.auth = auth @@ -662,7 +659,6 @@ import Foundation return } callbackScheme = "" - recaptchaVerifier = AuthRecaptchaVerifier.shared(auth: auth) } private let kAuthTypeVerifyApp = "verifyApp" diff --git a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorInfo.swift b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorInfo.swift index 0115afc7533..839e405fc05 100644 --- a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorInfo.swift +++ b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorInfo.swift @@ -14,13 +14,15 @@ import Foundation +// TODO(Swift 6 Breaking): Make checked Sendable. + #if os(iOS) extension MultiFactorInfo: NSSecureCoding {} /// Safe public structure used to represent a second factor entity from a client perspective. /// /// This class is available on iOS only. - @objc(FIRMultiFactorInfo) open class MultiFactorInfo: NSObject { + @objc(FIRMultiFactorInfo) open class MultiFactorInfo: NSObject, @unchecked Sendable { /// The multi-factor enrollment ID. @objc(UID) public let uid: String diff --git a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorSession.swift b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorSession.swift index c4bda3eba36..33f7ef927ce 100644 --- a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorSession.swift +++ b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorSession.swift @@ -27,33 +27,46 @@ import Foundation @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) @objc(FIRMultiFactorSession) open class MultiFactorSession: NSObject { /// The ID token for an enroll flow. This has to be retrieved after recent authentication. - var idToken: String? + let idToken: String? /// The pending credential after an enrolled second factor user signs in successfully with the /// first factor. - var mfaPendingCredential: String? + let mfaPendingCredential: String? + + /// Current user object. + let currentUser: User? /// Multi factor info for the current user. var multiFactorInfo: MultiFactorInfo? - /// Current user object. - var currentUser: User? - class func session(for user: User?) -> MultiFactorSession { let currentUser = user ?? Auth.auth().currentUser guard let currentUser else { fatalError("Internal Auth Error: missing user for multifactor auth") } - return .init(idToken: currentUser.tokenService.accessToken, currentUser: currentUser) + return .init( + idToken: currentUser.tokenService.accessToken, + mfaPendingCredential: nil, + multiFactorInfo: nil, + currentUser: currentUser + ) } - init(idToken: String?, currentUser: User) { - self.idToken = idToken - self.currentUser = currentUser + convenience init(mfaCredential: String?) { + self.init( + idToken: nil, + mfaPendingCredential: mfaCredential, + multiFactorInfo: nil, + currentUser: nil + ) } - init(mfaCredential: String?) { - mfaPendingCredential = mfaCredential + private init(idToken: String?, mfaPendingCredential: String?, multiFactorInfo: MultiFactorInfo?, + currentUser: User?) { + self.idToken = idToken + self.mfaPendingCredential = mfaPendingCredential + self.multiFactorInfo = multiFactorInfo + self.currentUser = currentUser } } diff --git a/FirebaseAuth/Sources/Swift/MultiFactor/Phone/PhoneMultiFactorInfo.swift b/FirebaseAuth/Sources/Swift/MultiFactor/Phone/PhoneMultiFactorInfo.swift index 58e5fc5fb8b..b847407c48a 100644 --- a/FirebaseAuth/Sources/Swift/MultiFactor/Phone/PhoneMultiFactorInfo.swift +++ b/FirebaseAuth/Sources/Swift/MultiFactor/Phone/PhoneMultiFactorInfo.swift @@ -14,6 +14,8 @@ import Foundation +// TODO(Swift 6 Breaking): Make checked Sendable. + #if os(iOS) /// Extends the MultiFactorInfo class for phone number second factors. @@ -21,7 +23,8 @@ import Foundation /// The identifier of this second factor is "phone". /// /// This class is available on iOS only. - @objc(FIRPhoneMultiFactorInfo) open class PhoneMultiFactorInfo: MultiFactorInfo { + @objc(FIRPhoneMultiFactorInfo) open class PhoneMultiFactorInfo: MultiFactorInfo, + @unchecked Sendable { /// The string identifier for using phone as a second factor. @objc(FIRPhoneMultiFactorID) public static let PhoneMultiFactorID = "phone" diff --git a/FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorInfo.swift b/FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorInfo.swift index b1c3f7b7d95..dbb2eeb7042 100644 --- a/FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorInfo.swift +++ b/FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorInfo.swift @@ -14,6 +14,9 @@ import Foundation +// TODO(Swift 6 Breaking): Make checked Sendable. Also, does this need +// to be public? + #if os(iOS) /// Extends the MultiFactorInfo class for time based one-time password second factors. @@ -21,7 +24,7 @@ import Foundation /// The identifier of this second factor is "totp". /// /// This class is available on iOS only. - class TOTPMultiFactorInfo: MultiFactorInfo { + class TOTPMultiFactorInfo: MultiFactorInfo, @unchecked Sendable { /// Initialize the AuthProtoMFAEnrollment instance with proto. /// - Parameter proto: AuthProtoMFAEnrollment proto object. init(proto: AuthProtoMFAEnrollment) {