From e14f88d1478db7251c3defb6a0d52f769cb07c45 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 22:42:22 +0000 Subject: [PATCH 1/6] Fix: Throw invalidUserToken error in retrieveUser Instead of generating a fatalError in the retrieveUser function in User.swift, this change throws an invalidUserToken error. A corresponding unit test has been added to verify this new behavior. --- FirebaseAuth/Sources/Swift/User/User.swift | 2 +- .../Sources/Swift/Utilities/AuthErrorUtils.swift | 4 ++-- FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift | 2 +- FirebaseAuth/Tests/Unit/AuthTests.swift | 10 ++++++++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/FirebaseAuth/Sources/Swift/User/User.swift b/FirebaseAuth/Sources/Swift/User/User.swift index db128df0baa..02f2e8f35b0 100644 --- a/FirebaseAuth/Sources/Swift/User/User.swift +++ b/FirebaseAuth/Sources/Swift/User/User.swift @@ -1081,7 +1081,7 @@ extension User: NSSecureCoding {} anonymous: Bool) async throws -> User { guard let accessToken = accessToken, let refreshToken = refreshToken else { - fatalError("Internal FirebaseAuth Error: nil token") + throw AuthErrorUtils.invalidUserToken } let tokenService = SecureTokenService(withRequestConfiguration: auth.requestConfiguration, accessToken: accessToken, diff --git a/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift b/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift index 01ff6449b7f..0bede23a576 100644 --- a/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift +++ b/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift @@ -123,8 +123,8 @@ class AuthErrorUtils { error(code: .requiresRecentLogin, message: message) } - static func invalidUserTokenError(message: String?) -> Error { - error(code: .invalidUserToken, message: message) + static func invalidUserTokenError() -> Error { + error(code: .invalidUserToken) } static func invalidEmailError(message: String?) -> Error { diff --git a/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift b/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift index 4e97f492866..9b873846b1d 100644 --- a/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift +++ b/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift @@ -380,7 +380,7 @@ import Foundation case .noSuchProvider: return kErrorNoSuchProvider case .invalidUserToken: - return kErrorInvalidUserToken + return "The provided user token is invalid." case .networkError: return kErrorNetworkError case .keychainError: diff --git a/FirebaseAuth/Tests/Unit/AuthTests.swift b/FirebaseAuth/Tests/Unit/AuthTests.swift index fe7be777cc9..54d1b896278 100644 --- a/FirebaseAuth/Tests/Unit/AuthTests.swift +++ b/FirebaseAuth/Tests/Unit/AuthTests.swift @@ -2454,4 +2454,14 @@ class AuthTests: RPCBaseTests { XCTAssertTrue(user.isAnonymous) XCTAssertEqual(user.providerData.count, 0) } + func testRetrieveUserWithInvalidToken() async throws { + let auth = try XCTUnwrap(self.auth) + do { + _ = try await User.retrieveUser(withAuth: auth, accessToken: nil, accessTokenExpirationDate: nil, refreshToken: nil, anonymous: false) + XCTFail("Expected an error to be thrown") + } catch let error as NSError { + XCTAssertEqual(error.domain, AuthErrors.domain) + XCTAssertEqual(error.code, AuthErrorCode.invalidUserToken.rawValue) + } + } } From f9dee5468a8028709cf029d8d416a22d9072dfe8 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 7 Apr 2025 16:03:51 -0700 Subject: [PATCH 2/6] fixes --- FirebaseAuth/Sources/Swift/User/User.swift | 2 +- .../Swift/Utilities/AuthErrorUtils.swift | 4 ++-- .../Sources/Swift/Utilities/AuthErrors.swift | 2 +- FirebaseAuth/Tests/Unit/AuthTests.swift | 10 ---------- FirebaseAuth/Tests/Unit/UserTests.swift | 17 +++++++++++++++++ 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/FirebaseAuth/Sources/Swift/User/User.swift b/FirebaseAuth/Sources/Swift/User/User.swift index 02f2e8f35b0..55d1f9d3c23 100644 --- a/FirebaseAuth/Sources/Swift/User/User.swift +++ b/FirebaseAuth/Sources/Swift/User/User.swift @@ -1081,7 +1081,7 @@ extension User: NSSecureCoding {} anonymous: Bool) async throws -> User { guard let accessToken = accessToken, let refreshToken = refreshToken else { - throw AuthErrorUtils.invalidUserToken + throw AuthErrorUtils.invalidUserTokenError(message: "Invalid user token") } let tokenService = SecureTokenService(withRequestConfiguration: auth.requestConfiguration, accessToken: accessToken, diff --git a/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift b/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift index 0bede23a576..01ff6449b7f 100644 --- a/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift +++ b/FirebaseAuth/Sources/Swift/Utilities/AuthErrorUtils.swift @@ -123,8 +123,8 @@ class AuthErrorUtils { error(code: .requiresRecentLogin, message: message) } - static func invalidUserTokenError() -> Error { - error(code: .invalidUserToken) + static func invalidUserTokenError(message: String?) -> Error { + error(code: .invalidUserToken, message: message) } static func invalidEmailError(message: String?) -> Error { diff --git a/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift b/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift index 9b873846b1d..4e97f492866 100644 --- a/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift +++ b/FirebaseAuth/Sources/Swift/Utilities/AuthErrors.swift @@ -380,7 +380,7 @@ import Foundation case .noSuchProvider: return kErrorNoSuchProvider case .invalidUserToken: - return "The provided user token is invalid." + return kErrorInvalidUserToken case .networkError: return kErrorNetworkError case .keychainError: diff --git a/FirebaseAuth/Tests/Unit/AuthTests.swift b/FirebaseAuth/Tests/Unit/AuthTests.swift index 54d1b896278..fe7be777cc9 100644 --- a/FirebaseAuth/Tests/Unit/AuthTests.swift +++ b/FirebaseAuth/Tests/Unit/AuthTests.swift @@ -2454,14 +2454,4 @@ class AuthTests: RPCBaseTests { XCTAssertTrue(user.isAnonymous) XCTAssertEqual(user.providerData.count, 0) } - func testRetrieveUserWithInvalidToken() async throws { - let auth = try XCTUnwrap(self.auth) - do { - _ = try await User.retrieveUser(withAuth: auth, accessToken: nil, accessTokenExpirationDate: nil, refreshToken: nil, anonymous: false) - XCTFail("Expected an error to be thrown") - } catch let error as NSError { - XCTAssertEqual(error.domain, AuthErrors.domain) - XCTAssertEqual(error.code, AuthErrorCode.invalidUserToken.rawValue) - } - } } diff --git a/FirebaseAuth/Tests/Unit/UserTests.swift b/FirebaseAuth/Tests/Unit/UserTests.swift index ba11eb2ee47..093b59caf95 100644 --- a/FirebaseAuth/Tests/Unit/UserTests.swift +++ b/FirebaseAuth/Tests/Unit/UserTests.swift @@ -1554,6 +1554,23 @@ class UserTests: RPCBaseTests { } #endif + func testRetrieveUserWithInvalidToken() async throws { + let auth = try XCTUnwrap(self.auth) + do { + _ = try await User.retrieveUser( + withAuth: auth, + accessToken: nil, + accessTokenExpirationDate: nil, + refreshToken: nil, + anonymous: false + ) + XCTFail("Expected an error to be thrown") + } catch let error as NSError { + XCTAssertEqual(error.domain, AuthErrors.domain) + XCTAssertEqual(error.code, AuthErrorCode.invalidUserToken.rawValue) + } + } + // MARK: Private helper functions private func expectVerifyPhoneNumberRequest(isLink: Bool = false) { From 709ca50a65732d51d73d4ab23094186c7685cc54 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 7 Apr 2025 16:07:29 -0700 Subject: [PATCH 3/6] changelog --- FirebaseAuth/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FirebaseAuth/CHANGELOG.md b/FirebaseAuth/CHANGELOG.md index 01349d8f334..fe6bce0fb37 100644 --- a/FirebaseAuth/CHANGELOG.md +++ b/FirebaseAuth/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased +- [fixed] Fix a `fatalError` unenrolling from MFA. An invalid user token now throws an + `invalidUserToken` error instead of crashing. (#14663) + # 11.9.0 - [changed] Using reCAPTCHA Enterprise and Firebase Auth requires reCAPTCHA Enterprise 18.7.0 or later. From d2bf2f36eef9e6231099a5881b53033283f24b8e Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 7 Apr 2025 16:22:35 -0700 Subject: [PATCH 4/6] Update FirebaseAuth/Sources/Swift/User/User.swift Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- FirebaseAuth/Sources/Swift/User/User.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FirebaseAuth/Sources/Swift/User/User.swift b/FirebaseAuth/Sources/Swift/User/User.swift index 55d1f9d3c23..7817c8cbcda 100644 --- a/FirebaseAuth/Sources/Swift/User/User.swift +++ b/FirebaseAuth/Sources/Swift/User/User.swift @@ -1081,7 +1081,7 @@ extension User: NSSecureCoding {} anonymous: Bool) async throws -> User { guard let accessToken = accessToken, let refreshToken = refreshToken else { - throw AuthErrorUtils.invalidUserTokenError(message: "Invalid user token") + throw AuthErrorUtils.invalidUserTokenError(message: "Invalid user token: accessToken or refreshToken is nil") } let tokenService = SecureTokenService(withRequestConfiguration: auth.requestConfiguration, accessToken: accessToken, From 14a7ad6251a0d1c9449337d5a41e43000fe3671d Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 7 Apr 2025 16:22:42 -0700 Subject: [PATCH 5/6] Update FirebaseAuth/Tests/Unit/UserTests.swift Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- FirebaseAuth/Tests/Unit/UserTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FirebaseAuth/Tests/Unit/UserTests.swift b/FirebaseAuth/Tests/Unit/UserTests.swift index 093b59caf95..e7440b6a674 100644 --- a/FirebaseAuth/Tests/Unit/UserTests.swift +++ b/FirebaseAuth/Tests/Unit/UserTests.swift @@ -1560,10 +1560,11 @@ class UserTests: RPCBaseTests { _ = try await User.retrieveUser( withAuth: auth, accessToken: nil, - accessTokenExpirationDate: nil, + accessTokenExpirationDate: Date(), refreshToken: nil, anonymous: false ) + ) XCTFail("Expected an error to be thrown") } catch let error as NSError { XCTAssertEqual(error.domain, AuthErrors.domain) From cf07b8fd1f96da4b98fdfdd1b0acf4e7101fa9ae Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Mon, 7 Apr 2025 16:24:25 -0700 Subject: [PATCH 6/6] Delete extra paren added by gemini --- FirebaseAuth/Tests/Unit/UserTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/FirebaseAuth/Tests/Unit/UserTests.swift b/FirebaseAuth/Tests/Unit/UserTests.swift index e7440b6a674..0462c2306e3 100644 --- a/FirebaseAuth/Tests/Unit/UserTests.swift +++ b/FirebaseAuth/Tests/Unit/UserTests.swift @@ -1564,7 +1564,6 @@ class UserTests: RPCBaseTests { refreshToken: nil, anonymous: false ) - ) XCTFail("Expected an error to be thrown") } catch let error as NSError { XCTAssertEqual(error.domain, AuthErrors.domain)