diff --git a/FirebaseAuth/Sources/Swift/Auth/Auth.swift b/FirebaseAuth/Sources/Swift/Auth/Auth.swift index 8effd15c101..3ac7f43b9bc 100644 --- a/FirebaseAuth/Sources/Swift/Auth/Auth.swift +++ b/FirebaseAuth/Sources/Swift/Auth/Auth.swift @@ -295,9 +295,9 @@ extension Auth: AuthInterop { Task { do { let response = try await AuthBackend.call(with: request) - Auth.wrapMainAsync(callback: completion, withParam: response.signinMethods, error: nil) + Auth.wrapMainAsync(callback: completion, with: .success(response.signinMethods)) } catch { - Auth.wrapMainAsync(callback: completion, withParam: nil, error: error) + Auth.wrapMainAsync(callback: completion, with: .failure(error)) } } } @@ -1004,9 +1004,9 @@ extension Auth: AuthInterop { let actionCodeInfo = ActionCodeInfo(withOperation: operation, email: email, newEmail: response.verifiedEmail) - Auth.wrapMainAsync(callback: completion, withParam: actionCodeInfo, error: nil) + Auth.wrapMainAsync(callback: completion, with: .success(actionCodeInfo)) } catch { - Auth.wrapMainAsync(callback: completion, withParam: nil, error: error) + Auth.wrapMainAsync(callback: completion, with: .failure(error)) } } } @@ -2224,7 +2224,11 @@ extension Auth: AuthInterop { ((AuthDataResult?, Error?) -> Void)?) -> (AuthDataResult?, Error?) -> Void { let authDataCallback: (((AuthDataResult?, Error?) -> Void)?, AuthDataResult?, Error?) -> Void = { callback, result, error in - Auth.wrapMainAsync(callback: callback, withParam: result, error: error) + if let result { + Auth.wrapMainAsync(callback: callback, with: .success(result)) + } else if let error { + Auth.wrapMainAsync(callback: callback, with: .failure(error)) + } } return { authResult, error in if let error { @@ -2261,11 +2265,14 @@ extension Auth: AuthInterop { } class func wrapMainAsync(callback: ((T?, Error?) -> Void)?, - withParam param: T?, - error: Error?) -> Void { - if let callback { - DispatchQueue.main.async { - callback(param, error) + with result: Result) -> Void { + guard let callback else { return } + DispatchQueue.main.async { + switch result { + case let .success(success): + callback(success, nil) + case let .failure(error): + callback(nil, error) } } } diff --git a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift index 32d15499f74..a8651d12e01 100644 --- a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift +++ b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift @@ -86,9 +86,9 @@ import Foundation uiDelegate: uiDelegate, multiFactorSession: multiFactorSession ) - Auth.wrapMainAsync(callback: completion, withParam: verificationID, error: nil) + Auth.wrapMainAsync(callback: completion, with: .success(verificationID)) } catch { - Auth.wrapMainAsync(callback: completion, withParam: nil, error: error) + Auth.wrapMainAsync(callback: completion, with: .failure(error)) } } } @@ -184,7 +184,7 @@ import Foundation private func internalVerify(phoneNumber: String, uiDelegate: AuthUIDelegate?, multiFactorSession: MultiFactorSession? = nil) async throws - -> String? { + -> String { guard phoneNumber.count > 0 else { throw AuthErrorUtils.missingPhoneNumberError(message: nil) } @@ -209,7 +209,7 @@ import Foundation private func verifyClAndSendVerificationCode(toPhoneNumber phoneNumber: String, retryOnInvalidAppCredential: Bool, uiDelegate: AuthUIDelegate?) async throws - -> String? { + -> String { let codeIdentity = try await verifyClient(withUIDelegate: uiDelegate) let request = SendVerificationCodeRequest(phoneNumber: phoneNumber, codeIdentity: codeIdentity, @@ -236,7 +236,7 @@ import Foundation retryOnInvalidAppCredential: Bool, multiFactorSession session: MultiFactorSession?, uiDelegate: AuthUIDelegate?) async throws - -> String? { + -> String { if let settings = auth.settings, settings.isAppVerificationDisabledForTesting { let request = SendVerificationCodeRequest( @@ -264,7 +264,10 @@ import Foundation enrollmentInfo: startMFARequestInfo, requestConfiguration: auth.requestConfiguration) let response = try await AuthBackend.call(with: request) - return response.phoneSessionInfo?.sessionInfo + guard let sessionInfo = response.phoneSessionInfo?.sessionInfo else { + throw AuthErrorUtils.error(code: .missingMultiFactorInfo) + } + return sessionInfo } else { let request = StartMFASignInRequest(MFAPendingCredential: session.mfaPendingCredential, MFAEnrollmentID: session.multiFactorInfo?.uid, @@ -272,7 +275,10 @@ import Foundation requestConfiguration: auth.requestConfiguration) let response = try await AuthBackend.call(with: request) - return response.responseInfo?.sessionInfo + guard let sessionInfo = response.responseInfo?.sessionInfo else { + throw AuthErrorUtils.error(code: .multiFactorInfoNotFound) + } + return sessionInfo } } catch { return try await handleVerifyErrorWithRetry( @@ -289,7 +295,7 @@ import Foundation phoneNumber: String, retryOnInvalidAppCredential: Bool, multiFactorSession session: MultiFactorSession?, - uiDelegate: AuthUIDelegate?) async throws -> String? { + uiDelegate: AuthUIDelegate?) async throws -> String { if (error as NSError).code == AuthErrorCode.invalidAppCredential.rawValue { if retryOnInvalidAppCredential { auth.appCredentialManager.clearCredential() diff --git a/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift b/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift index cc597172010..deba2ba1557 100644 --- a/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift +++ b/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift @@ -16,7 +16,8 @@ import Foundation @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) struct StartMFASignInResponse: AuthRPCResponse { - var responseInfo: AuthProtoStartMFAPhoneResponseInfo? +// var responseInfo: AuthProtoStartMFAPhoneResponseInfo? + private(set) var responseInfo: AuthProtoStartMFAPhoneResponseInfo? mutating func setFields(dictionary: [String: AnyHashable]) throws { if let data = dictionary["phoneResponseInfo"] as? [String: AnyHashable] { diff --git a/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift b/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift index f9e6872cfcb..8f844c25f8c 100644 --- a/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift +++ b/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift @@ -15,9 +15,13 @@ import Foundation struct SendVerificationCodeResponse: AuthRPCResponse { - var verificationID: String? + // Default value will be overridden when `setField(dictionary:)` is called. + private(set) var verificationID: String = "" mutating func setFields(dictionary: [String: AnyHashable]) throws { - verificationID = dictionary["sessionInfo"] as? String + guard let verificationID = dictionary["sessionInfo"] as? String else { + throw AuthErrorUtils.unexpectedResponse(deserializedResponse: dictionary) + } + self.verificationID = verificationID } } diff --git a/FirebaseAuth/Tests/Unit/RPCBaseTests.swift b/FirebaseAuth/Tests/Unit/RPCBaseTests.swift index 009289a1b44..06ef5cf7151 100644 --- a/FirebaseAuth/Tests/Unit/RPCBaseTests.swift +++ b/FirebaseAuth/Tests/Unit/RPCBaseTests.swift @@ -97,7 +97,7 @@ class RPCBaseTests: XCTestCase { XCTFail("decodedRequest is not a dictionary") } // Dummy response to unblock await. - let _ = try self.rpcIssuer?.respond(withJSON: [:]) + let _ = try self.rpcIssuer?.respond(withJSON: ["sessionInfo": "verification_id_123"]) } let _ = try await AuthBackend.call(with: request) }