Bläddra i källkod

[Auth] Forward secure coding calls for TOTPMultiFactorInfo (#13592)

Nick Cooke 1 år sedan
förälder
incheckning
424516b5ab

+ 3 - 0
FirebaseAuth/CHANGELOG.md

@@ -7,6 +7,9 @@
   in methods and a `nil` error. In such cases, an empty array is instead
   returned with the `nil` error. (#13550)
 - [Fixed] Fixed user session persistence in multi tenant projects. Introduced in 11.0.0. (#13565)
+- [Fixed] Fixed encoding crash that occurs when using TOTP multi-factor
+  authentication. Note that this fix will not be in the 11.2.0 zip and Carthage
+  distributions, but will be included from 11.3.0 onwards. (#13591)
 
 # 11.1.0
 - [fixed] Fixed `Swift.error` conformance for `AuthErrorCode`. (#13430)

+ 2 - 0
FirebaseAuth/Sources/Swift/Backend/RPC/Proto/AuthProtoMFAEnrollment.swift

@@ -16,6 +16,8 @@ import Foundation
 
 class AuthProtoMFAEnrollment: NSObject, AuthProto {
   let phoneInfo: String?
+  // In practice, this will be an empty dictionary. The presence of which
+  // indicates TOTP MFA enrollment rather than phone MFA enrollment.
   let totpInfo: NSObject?
   let mfaEnrollmentID: String?
   let displayName: String?

+ 5 - 6
FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorInfo.swift

@@ -22,19 +22,18 @@ import Foundation
   ///
   /// This class is available on iOS only.
   class TOTPMultiFactorInfo: MultiFactorInfo {
-    /// This is the totp info for the second factor.
-    let totpInfo: NSObject?
-
     /// Initialize the AuthProtoMFAEnrollment instance with proto.
     /// - Parameter proto: AuthProtoMFAEnrollment proto object.
     init(proto: AuthProtoMFAEnrollment) {
-      totpInfo = proto.totpInfo
       super.init(proto: proto, factorID: PhoneMultiFactorInfo.TOTPMultiFactorID)
     }
 
-    @available(*, unavailable)
     required init?(coder: NSCoder) {
-      fatalError("init(coder:) has not been implemented")
+      super.init(coder: coder)
+    }
+
+    override class var supportsSecureCoding: Bool {
+      super.supportsSecureCoding
     }
   }
 #endif

+ 23 - 10
FirebaseAuth/Tests/Unit/UserTests.swift

@@ -141,12 +141,21 @@ class UserTests: RPCBaseTests {
       "phoneNumber": kPhoneNumber,
       "createdAt": String(Int(kCreationDateTimeIntervalInSeconds) * 1000), // to nanoseconds
       "lastLoginAt": String(Int(kLastSignInDateTimeIntervalInSeconds) * 1000),
-      "mfaInfo": [[
-        "phoneInfo": kPhoneInfo,
-        "mfaEnrollmentId": kEnrollmentID,
-        "displayName": kDisplayName,
-        "enrolledAt": kEnrolledAt,
-      ]],
+      "mfaInfo": [
+        [
+          "phoneInfo": kPhoneInfo,
+          "mfaEnrollmentId": kEnrollmentID,
+          "displayName": kDisplayName,
+          "enrolledAt": kEnrolledAt,
+        ],
+        [
+          // In practice, this will be an empty dictionary.
+          "totpInfo": [AnyHashable: AnyHashable](),
+          "mfaEnrollmentId": kEnrollmentID,
+          "displayName": kDisplayName,
+          "enrolledAt": kEnrolledAt,
+        ] as [AnyHashable: AnyHashable],
+      ],
     ]]
 
     let expectation = self.expectation(description: #function)
@@ -346,11 +355,15 @@ class UserTests: RPCBaseTests {
 
           // Verify MultiFactorInfo properties.
           let enrolledFactors = try XCTUnwrap(user.multiFactor.enrolledFactors)
+          XCTAssertEqual(enrolledFactors.count, 2)
           XCTAssertEqual(enrolledFactors[0].factorID, PhoneMultiFactorInfo.PhoneMultiFactorID)
-          XCTAssertEqual(enrolledFactors[0].uid, kEnrollmentID)
-          XCTAssertEqual(enrolledFactors[0].displayName, self.kDisplayName)
-          let date = try XCTUnwrap(enrolledFactors[0].enrollmentDate)
-          XCTAssertEqual("\(date)", kEnrolledAtMatch)
+          XCTAssertEqual(enrolledFactors[1].factorID, PhoneMultiFactorInfo.TOTPMultiFactorID)
+          for enrolledFactor in enrolledFactors {
+            XCTAssertEqual(enrolledFactor.uid, kEnrollmentID)
+            XCTAssertEqual(enrolledFactor.displayName, self.kDisplayName)
+            let date = try XCTUnwrap(enrolledFactor.enrollmentDate)
+            XCTAssertEqual("\(date)", kEnrolledAtMatch)
+          }
         #endif
       } catch {
         XCTFail("Caught an error in \(#function): \(error)")