UserTests.swift 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License")
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. import XCTest
  16. @testable import FirebaseAuth
  17. import FirebaseCore
  18. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
  19. class UserTests: RPCBaseTests {
  20. static let kFakeAPIKey = "FAKE_API_KEY"
  21. let kFacebookAccessToken = "FACEBOOK_ACCESS_TOKEN"
  22. let kFacebookID = "FACEBOOK_ID"
  23. let kFacebookEmail = "user@facebook.com"
  24. let kFacebookDisplayName = "Facebook Doe"
  25. let kFacebookIDToken: String? = nil // Facebook id Token is always nil.
  26. let kNewEmail = "newuser@company.com"
  27. let kNewPassword = "newpassword"
  28. let kNewDisplayName = "New User Doe"
  29. let kVerificationCode = "12345678"
  30. let kVerificationID = "55432"
  31. let kPhoneNumber = "555-1234"
  32. static var auth: Auth?
  33. override class func setUp() {
  34. let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
  35. gcmSenderID: "00000000000000000-00000000000-000000000")
  36. options.apiKey = kFakeAPIKey
  37. options.projectID = "myUserProjectID"
  38. FirebaseApp.configure(name: "test-UserTests", options: options)
  39. #if (os(macOS) && !FIREBASE_AUTH_TESTING_USE_MACOS_KEYCHAIN) || SWIFT_PACKAGE
  40. let keychainStorageProvider = FakeAuthKeychainStorage()
  41. #else
  42. let keychainStorageProvider = AuthKeychainStorageReal()
  43. #endif // (os(macOS) && !FIREBASE_AUTH_TESTING_USE_MACOS_KEYCHAIN) || SWIFT_PACKAGE
  44. auth = Auth(
  45. app: FirebaseApp.app(name: "test-UserTests")!,
  46. keychainStorageProvider: keychainStorageProvider
  47. )
  48. }
  49. override func tearDown() {
  50. // Verifies that no tasks are left suspended on the AuthSerialTaskQueue.
  51. try? UserTests.auth?.signOut()
  52. }
  53. /** @fn testUserPropertiesAndNSSecureCoding
  54. @brief Tests properties of the @c User instance before and after being
  55. serialized/deserialized.
  56. */
  57. func testUserPropertiesAndNSSecureCoding() throws {
  58. let kProviderUserInfoKey = "providerUserInfo"
  59. let kPhotoUrlKey = "photoUrl"
  60. let kProviderIDkey = "providerId"
  61. let kDisplayNameKey = "displayName"
  62. let kFederatedIDKey = "federatedId"
  63. let kEmailKey = "email"
  64. let kPasswordHashKey = "passwordHash"
  65. let kTestPasswordHash = "testPasswordHash"
  66. let kEmailVerifiedKey = "emailVerified"
  67. let kLocalIDKey = "localId"
  68. let kGoogleID = "GOOGLE_ID"
  69. let kGoogleDisplayName = "Google Doe"
  70. let kGoogleEmail = "user@gmail.com"
  71. let kGooglePhotoURL = "https://googleusercontents.com/user/profile"
  72. let kFacebookID = "FACEBOOK_ID"
  73. let kFacebookEmail = "user@facebook.com"
  74. let kEnrollmentID = "fakeEnrollment"
  75. let kPhoneInfo = "+15555555555"
  76. let kEnrolledAt = "2022-08-01T18:31:15.426458Z"
  77. let kEnrolledAtMatch = "2022-08-01 18:31:15 +0000"
  78. let kTwitterID = "TwitterID"
  79. let kGitHubID = "GitHubID"
  80. let kGameCenterID = "GameCenterID"
  81. var providerUserInfos = [[
  82. kProviderIDkey: EmailAuthProvider.id,
  83. kFederatedIDKey: kEmail,
  84. kEmailKey: kEmail,
  85. ],
  86. [
  87. kProviderIDkey: GoogleAuthProvider.id,
  88. kDisplayNameKey: kGoogleDisplayName,
  89. kPhotoUrlKey: kGooglePhotoURL,
  90. kFederatedIDKey: kGoogleID,
  91. kEmailKey: kGoogleEmail,
  92. ],
  93. [
  94. kProviderIDkey: FacebookAuthProvider.id,
  95. kFederatedIDKey: kFacebookID,
  96. kEmailKey: kFacebookEmail,
  97. ],
  98. [
  99. kProviderIDkey: GitHubAuthProvider.id,
  100. kFederatedIDKey: kGitHubID,
  101. kEmailKey: kGoogleEmail,
  102. ],
  103. [
  104. kProviderIDkey: TwitterAuthProvider.id,
  105. kFederatedIDKey: kTwitterID,
  106. kEmailKey: kFacebookEmail,
  107. ]]
  108. #if !os(watchOS)
  109. providerUserInfos.append([
  110. kProviderIDkey: GameCenterAuthProvider.id,
  111. kFederatedIDKey: kGameCenterID,
  112. kEmailKey: kFacebookEmail,
  113. ])
  114. #endif
  115. #if os(iOS)
  116. providerUserInfos.append([
  117. kProviderIDkey: PhoneAuthProvider.id,
  118. kFederatedIDKey: kPhoneNumber,
  119. "phoneNumber": kPhoneNumber,
  120. ])
  121. #endif
  122. rpcIssuer?.fakeGetAccountProviderJSON = [[
  123. kProviderUserInfoKey: providerUserInfos,
  124. kLocalIDKey: kLocalID,
  125. kDisplayNameKey: kDisplayName,
  126. kEmailKey: kEmail,
  127. kPhotoUrlKey: kTestPhotoURL,
  128. kEmailVerifiedKey: true,
  129. kPasswordHashKey: kTestPasswordHash,
  130. "phoneNumber": kPhoneNumber,
  131. "createdAt": String(Int(kCreationDateTimeIntervalInSeconds) * 1000), // to nanoseconds
  132. "lastLoginAt": String(Int(kLastSignInDateTimeIntervalInSeconds) * 1000),
  133. "mfaInfo": [[
  134. "phoneInfo": kPhoneInfo,
  135. "mfaEnrollmentId": kEnrollmentID,
  136. "displayName": kDisplayName,
  137. "enrolledAt": kEnrolledAt,
  138. ]],
  139. ]]
  140. let expectation = self.expectation(description: #function)
  141. signInWithEmailPasswordReturnFakeUser { user in
  142. do {
  143. XCTAssertEqual(user.providerID, "Firebase")
  144. XCTAssertEqual(user.uid, self.kLocalID)
  145. XCTAssertEqual(user.displayName, self.kDisplayName)
  146. XCTAssertEqual(user.photoURL, URL(string: self.kTestPhotoURL))
  147. XCTAssertEqual(user.email, self.kEmail)
  148. XCTAssertEqual(user.metadata.creationDate, Date(timeIntervalSince1970:
  149. self.kCreationDateTimeIntervalInSeconds))
  150. XCTAssertEqual(user.metadata.lastSignInDate,
  151. Date(timeIntervalSince1970: self.kLastSignInDateTimeIntervalInSeconds))
  152. // Verify FIRUser properties besides providerData contents.
  153. XCTAssertFalse(user.isAnonymous)
  154. XCTAssertTrue(user.isEmailVerified)
  155. XCTAssertEqual(user.refreshToken, self.kRefreshToken)
  156. XCTAssertEqual(user.providerData.count, providerUserInfos.count)
  157. let providerMap = user.providerData.reduce(into: [String: UserInfo]()) {
  158. $0[$1.providerID] = $1
  159. }
  160. // Verify FIRUserInfo properties from email/password.
  161. let passwordUserInfo = try XCTUnwrap(providerMap[EmailAuthProvider.id])
  162. XCTAssertEqual(passwordUserInfo.uid, self.kEmail)
  163. XCTAssertNil(passwordUserInfo.displayName)
  164. XCTAssertNil(passwordUserInfo.photoURL)
  165. XCTAssertEqual(passwordUserInfo.email, self.kEmail)
  166. // Verify FIRUserInfo properties from the Google auth provider.
  167. let googleUserInfo = try XCTUnwrap(providerMap[GoogleAuthProvider.id])
  168. XCTAssertEqual(googleUserInfo.uid, kGoogleID)
  169. XCTAssertEqual(googleUserInfo.displayName, kGoogleDisplayName)
  170. XCTAssertEqual(googleUserInfo.photoURL, URL(string: kGooglePhotoURL))
  171. XCTAssertEqual(googleUserInfo.email, kGoogleEmail)
  172. // Verify FIRUserInfo properties from the Facebook auth provider.
  173. let facebookUserInfo = try XCTUnwrap(providerMap[FacebookAuthProvider.id])
  174. XCTAssertEqual(facebookUserInfo.uid, kFacebookID)
  175. XCTAssertNil(facebookUserInfo.displayName)
  176. XCTAssertNil(facebookUserInfo.photoURL)
  177. XCTAssertEqual(facebookUserInfo.email, kFacebookEmail)
  178. // Verify FIRUserInfo properties from the GitHub auth provider.
  179. let gitHubUserInfo = try XCTUnwrap(providerMap[GitHubAuthProvider.id])
  180. XCTAssertEqual(gitHubUserInfo.uid, kGitHubID)
  181. XCTAssertNil(gitHubUserInfo.displayName)
  182. XCTAssertNil(gitHubUserInfo.photoURL)
  183. XCTAssertEqual(gitHubUserInfo.email, kGoogleEmail)
  184. // Verify FIRUserInfo properties from the Twitter auth provider.
  185. let twitterUserInfo = try XCTUnwrap(providerMap[TwitterAuthProvider.id])
  186. XCTAssertEqual(twitterUserInfo.uid, kTwitterID)
  187. XCTAssertNil(twitterUserInfo.displayName)
  188. XCTAssertNil(twitterUserInfo.photoURL)
  189. XCTAssertEqual(twitterUserInfo.email, kFacebookEmail)
  190. #if os(iOS)
  191. // Verify UserInfo properties from the phone auth provider.
  192. let phoneUserInfo = try XCTUnwrap(providerMap[PhoneAuthProvider.id])
  193. XCTAssertEqual(phoneUserInfo.phoneNumber, self.kPhoneNumber)
  194. #endif
  195. #if !os(watchOS)
  196. // Verify FIRUserInfo properties from the Game Center auth provider.
  197. let gameCenterUserInfo = try XCTUnwrap(providerMap[GameCenterAuthProvider.id])
  198. XCTAssertEqual(gameCenterUserInfo.uid, kGameCenterID)
  199. XCTAssertNil(gameCenterUserInfo.displayName)
  200. XCTAssertNil(gameCenterUserInfo.photoURL)
  201. XCTAssertEqual(gameCenterUserInfo.email, kFacebookEmail)
  202. #endif
  203. // Test NSSecureCoding
  204. XCTAssertTrue(User.supportsSecureCoding)
  205. let data = try NSKeyedArchiver.archivedData(
  206. withRootObject: user,
  207. requiringSecureCoding: true
  208. )
  209. var encodedClasses = [User.self, NSDictionary.self, NSURL.self, SecureTokenService.self,
  210. UserInfoImpl.self, NSDate.self, UserMetadata.self, NSString.self,
  211. NSArray.self]
  212. #if os(iOS)
  213. encodedClasses.append(MultiFactor.self)
  214. encodedClasses.append(PhoneMultiFactorInfo.self)
  215. #endif
  216. let unarchivedUser = try XCTUnwrap(NSKeyedUnarchiver.unarchivedObject(
  217. ofClasses: encodedClasses, from: data
  218. )
  219. as? User)
  220. // Verify NSSecureCoding for FIRUser
  221. XCTAssertEqual(unarchivedUser.providerID, user.providerID)
  222. XCTAssertEqual(unarchivedUser.uid, user.uid)
  223. XCTAssertEqual(unarchivedUser.email, user.email)
  224. XCTAssertEqual(unarchivedUser.photoURL, user.photoURL)
  225. XCTAssertEqual(unarchivedUser.displayName, user.displayName)
  226. // Verify NSSecureCoding properties besides providerData contents.
  227. XCTAssertEqual(unarchivedUser.isAnonymous, user.isAnonymous)
  228. XCTAssertEqual(unarchivedUser.isEmailVerified, user.isEmailVerified)
  229. XCTAssertEqual(unarchivedUser.refreshToken, user.refreshToken)
  230. XCTAssertEqual(unarchivedUser.metadata.creationDate, user.metadata.creationDate)
  231. XCTAssertEqual(unarchivedUser.metadata.lastSignInDate, user.metadata.lastSignInDate)
  232. XCTAssertEqual(unarchivedUser.providerData.count, user.providerData.count)
  233. let unarchivedProviderMap = unarchivedUser.providerData.reduce(into: [String: UserInfo]()) {
  234. $0[$1.providerID] = $1
  235. }
  236. // Verify NSSecureCoding properties for AuthDataResult
  237. let kFakeProfile = ["email": "user@mail.com", "given_name": "User", "family_name": "Doe"]
  238. let kUserName = "User Doe"
  239. let kProviderID = "PROVIDER_ID"
  240. let userInfo = AdditionalUserInfo(providerID: kProviderID,
  241. profile: kFakeProfile,
  242. username: kUserName,
  243. isNewUser: true)
  244. let authDataResult = AuthDataResult(withUser: user, additionalUserInfo: userInfo)
  245. XCTAssertTrue(AuthDataResult.supportsSecureCoding)
  246. let authDataResultData = try NSKeyedArchiver.archivedData(
  247. withRootObject: authDataResult,
  248. requiringSecureCoding: true
  249. )
  250. encodedClasses.append(AuthDataResult.self)
  251. encodedClasses.append(AdditionalUserInfo.self)
  252. let unarchivedDataResult = try XCTUnwrap(NSKeyedUnarchiver.unarchivedObject(
  253. ofClasses: encodedClasses, from: authDataResultData
  254. ) as? AuthDataResult)
  255. XCTAssertEqual(unarchivedDataResult.user.providerID, user.providerID)
  256. XCTAssertEqual(unarchivedDataResult.user.uid, user.uid)
  257. XCTAssertEqual(unarchivedDataResult.user.email, user.email)
  258. XCTAssertEqual(unarchivedDataResult.user.photoURL, user.photoURL)
  259. XCTAssertEqual(unarchivedDataResult.user.displayName, user.displayName)
  260. XCTAssertEqual(unarchivedDataResult.additionalUserInfo?.providerID, kProviderID)
  261. XCTAssertEqual(unarchivedDataResult.additionalUserInfo?.profile as? [String: String],
  262. kFakeProfile)
  263. XCTAssertEqual(unarchivedDataResult.additionalUserInfo?.username, kUserName)
  264. // Verify NSSecureCoding properties from email/password.
  265. let unarchivedPasswordUserInfo = try XCTUnwrap(unarchivedProviderMap[EmailAuthProvider.id])
  266. XCTAssertEqual(unarchivedPasswordUserInfo.uid, passwordUserInfo.uid)
  267. XCTAssertEqual(unarchivedPasswordUserInfo.displayName, passwordUserInfo.displayName)
  268. XCTAssertEqual(unarchivedPasswordUserInfo.photoURL, passwordUserInfo.photoURL)
  269. XCTAssertEqual(unarchivedPasswordUserInfo.email, passwordUserInfo.email)
  270. // Verify NSSecureCoding properties from the Google auth provider.
  271. let unarchivedGoogleUserInfo = try XCTUnwrap(unarchivedProviderMap[GoogleAuthProvider.id])
  272. XCTAssertEqual(unarchivedGoogleUserInfo.uid, googleUserInfo.uid)
  273. XCTAssertEqual(unarchivedGoogleUserInfo.displayName, googleUserInfo.displayName)
  274. XCTAssertEqual(unarchivedGoogleUserInfo.photoURL, googleUserInfo.photoURL)
  275. XCTAssertEqual(unarchivedGoogleUserInfo.email, googleUserInfo.email)
  276. // Verify NSSecureCoding properties from the Facebook auth provider.
  277. let unarchivedFacebookUserInfo =
  278. try XCTUnwrap(unarchivedProviderMap[FacebookAuthProvider.id])
  279. XCTAssertEqual(unarchivedFacebookUserInfo.uid, facebookUserInfo.uid)
  280. XCTAssertEqual(unarchivedFacebookUserInfo.displayName, facebookUserInfo.displayName)
  281. XCTAssertEqual(unarchivedFacebookUserInfo.photoURL, facebookUserInfo.photoURL)
  282. XCTAssertEqual(unarchivedFacebookUserInfo.email, facebookUserInfo.email)
  283. #if !os(watchOS)
  284. // Verify NSSecureCoding properties from the GameCenter auth provider.
  285. let unarchivedGameCenterUserInfo =
  286. try XCTUnwrap(unarchivedProviderMap[GameCenterAuthProvider.id])
  287. XCTAssertEqual(unarchivedGameCenterUserInfo.uid, gameCenterUserInfo.uid)
  288. XCTAssertEqual(unarchivedGameCenterUserInfo.displayName, gameCenterUserInfo.displayName)
  289. XCTAssertEqual(unarchivedGameCenterUserInfo.photoURL, gameCenterUserInfo.photoURL)
  290. XCTAssertEqual(unarchivedGameCenterUserInfo.email, gameCenterUserInfo.email)
  291. #endif
  292. // Verify NSSecureCoding properties from the GitHub auth provider.
  293. let unarchivedGitHubUserInfo =
  294. try XCTUnwrap(unarchivedProviderMap[GitHubAuthProvider.id])
  295. XCTAssertEqual(unarchivedGitHubUserInfo.uid, gitHubUserInfo.uid)
  296. XCTAssertEqual(unarchivedGitHubUserInfo.displayName, gitHubUserInfo.displayName)
  297. XCTAssertEqual(unarchivedGitHubUserInfo.photoURL, gitHubUserInfo.photoURL)
  298. XCTAssertEqual(unarchivedGitHubUserInfo.email, gitHubUserInfo.email)
  299. // Verify NSSecureCoding properties from the Twitter auth provider.
  300. let unarchivedTwitterUserInfo =
  301. try XCTUnwrap(unarchivedProviderMap[TwitterAuthProvider.id])
  302. XCTAssertEqual(unarchivedTwitterUserInfo.uid, twitterUserInfo.uid)
  303. XCTAssertEqual(unarchivedTwitterUserInfo.displayName, twitterUserInfo.displayName)
  304. XCTAssertEqual(unarchivedTwitterUserInfo.photoURL, twitterUserInfo.photoURL)
  305. XCTAssertEqual(unarchivedTwitterUserInfo.email, twitterUserInfo.email)
  306. #if os(iOS)
  307. // Verify NSSecureCoding properties from the phone auth provider.
  308. let unarchivedPhoneUserInfo = try XCTUnwrap(unarchivedProviderMap[PhoneAuthProvider.id])
  309. XCTAssertEqual(unarchivedPhoneUserInfo.phoneNumber, phoneUserInfo.phoneNumber)
  310. // Verify MultiFactorInfo properties.
  311. let enrolledFactors = try XCTUnwrap(user.multiFactor.enrolledFactors)
  312. XCTAssertEqual(enrolledFactors[0].factorID, PhoneMultiFactorInfo.PhoneMultiFactorID)
  313. XCTAssertEqual(enrolledFactors[0].uid, kEnrollmentID)
  314. XCTAssertEqual(enrolledFactors[0].displayName, self.kDisplayName)
  315. let date = try XCTUnwrap(enrolledFactors[0].enrollmentDate)
  316. XCTAssertEqual("\(date)", kEnrolledAtMatch)
  317. #endif
  318. } catch {
  319. XCTFail("Caught an error in \(#function): \(error)")
  320. }
  321. expectation.fulfill()
  322. }
  323. waitForExpectations(timeout: 5)
  324. }
  325. /** @fn testUpdateEmailSuccess
  326. @brief Tests the flow of a successful @c updateEmail:completion: call.
  327. */
  328. func testUpdateEmailSuccess() {
  329. setFakeGetAccountProvider(withPasswordHash: kFakePassword)
  330. let expectation = self.expectation(description: #function)
  331. signInWithEmailPasswordReturnFakeUser { user in
  332. self.changeUserEmail(user: user, changeEmail: true, expectation: expectation)
  333. }
  334. waitForExpectations(timeout: 5)
  335. }
  336. /** @fn testUpdateEmailWithAuthLinkAccountSuccess
  337. @brief Tests a successful @c updateEmail:completion: call updates provider info.
  338. */
  339. func testUpdateEmailWithAuthLinkAccountSuccess() {
  340. setFakeGetAccountProvider()
  341. let expectation = self.expectation(description: #function)
  342. signInWithEmailPasswordReturnFakeUserLink { user in
  343. self.changeUserEmail(user: user, expectation: expectation)
  344. }
  345. waitForExpectations(timeout: 5)
  346. }
  347. /** @fn testUpdateEmailFailure
  348. @brief Tests the flow of a failed @c updateEmail:completion: call.
  349. */
  350. func testUpdateEmailFailure() {
  351. setFakeGetAccountProvider()
  352. let expectation = self.expectation(description: #function)
  353. signInWithEmailPasswordReturnFakeUser { user in
  354. do {
  355. self.rpcIssuer.respondBlock = {
  356. try self.rpcIssuer?.respond(serverErrorMessage: "INVALID_EMAIL")
  357. }
  358. user.updateEmail(to: self.kNewEmail) { rawError in
  359. XCTAssertTrue(Thread.isMainThread)
  360. let error = try! XCTUnwrap(rawError)
  361. XCTAssertEqual((error as NSError).code, AuthErrorCode.invalidEmail.rawValue)
  362. // Email should not have changed on the client side.
  363. XCTAssertEqual(user.email, self.kEmail)
  364. // User is still signed in.
  365. XCTAssertEqual(UserTests.auth?.currentUser, user)
  366. expectation.fulfill()
  367. }
  368. }
  369. }
  370. waitForExpectations(timeout: 5)
  371. }
  372. /** @fn testUpdateEmailAutoSignOut
  373. @brief Tests the flow of a failed @c updateEmail:completion: call that automatically signs out.
  374. */
  375. func testUpdateEmailAutoSignOut() {
  376. setFakeGetAccountProvider()
  377. let expectation = self.expectation(description: #function)
  378. signInWithEmailPasswordReturnFakeUser { user in
  379. do {
  380. self.rpcIssuer.respondBlock = {
  381. try self.rpcIssuer?.respond(serverErrorMessage: "INVALID_ID_TOKEN")
  382. }
  383. user.updateEmail(to: self.kNewEmail) { rawError in
  384. XCTAssertTrue(Thread.isMainThread)
  385. let error = try! XCTUnwrap(rawError)
  386. XCTAssertEqual((error as NSError).code, AuthErrorCode.invalidUserToken.rawValue)
  387. // Email should not have changed on the client side.
  388. XCTAssertEqual(user.email, self.kEmail)
  389. // User is no longer signed in..
  390. XCTAssertNil(UserTests.auth?.currentUser)
  391. expectation.fulfill()
  392. }
  393. }
  394. }
  395. waitForExpectations(timeout: 5)
  396. }
  397. #if os(iOS)
  398. /** @fn testUpdatePhoneSuccess
  399. @brief Tests the flow of a successful @c updatePhoneNumberCredential:completion: call.
  400. */
  401. func testUpdatePhoneSuccess() throws {
  402. setFakeGetAccountProvider()
  403. let expectation = self.expectation(description: #function)
  404. let auth = try XCTUnwrap(UserTests.auth)
  405. signInWithEmailPasswordReturnFakeUser { user in
  406. do {
  407. self.rpcIssuer.respondBlock = {
  408. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  409. "refreshToken": self.kRefreshToken])
  410. }
  411. self.expectVerifyPhoneNumberRequest()
  412. self.rpcIssuer?.fakeGetAccountProviderJSON = [[
  413. "phoneNumber": self.kPhoneNumber,
  414. ]]
  415. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  416. withVerificationID: self.kVerificationID,
  417. verificationCode: self.kVerificationCode
  418. )
  419. user.updatePhoneNumber(credential) { error in
  420. XCTAssertTrue(Thread.isMainThread)
  421. XCTAssertNil(error)
  422. XCTAssertEqual(auth.currentUser?.phoneNumber, self.kPhoneNumber)
  423. expectation.fulfill()
  424. }
  425. }
  426. }
  427. waitForExpectations(timeout: 5)
  428. }
  429. /** @fn testUpdatePhoneNumberFailure
  430. @brief Tests the flow of a failed @c updatePhoneNumberCredential:completion: call.
  431. */
  432. func testUpdatePhoneNumberFailure() throws {
  433. setFakeGetAccountProvider()
  434. let expectation = self.expectation(description: #function)
  435. let auth = try XCTUnwrap(UserTests.auth)
  436. signInWithEmailPasswordReturnFakeUser { user in
  437. do {
  438. self.rpcIssuer.respondBlock = {
  439. try self.rpcIssuer?.respond(serverErrorMessage: "INVALID_PHONE_NUMBER")
  440. }
  441. self.expectVerifyPhoneNumberRequest()
  442. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  443. withVerificationID: self.kVerificationID,
  444. verificationCode: self.kVerificationCode
  445. )
  446. user.updatePhoneNumber(credential) { rawError in
  447. XCTAssertTrue(Thread.isMainThread)
  448. let error = try! XCTUnwrap(rawError)
  449. XCTAssertEqual((error as NSError).code, AuthErrorCode.invalidPhoneNumber.rawValue)
  450. XCTAssertEqual(auth.currentUser, user)
  451. expectation.fulfill()
  452. }
  453. }
  454. }
  455. waitForExpectations(timeout: 5)
  456. }
  457. /** @fn testUpdatePhoneNumberFailureAutoSignOut
  458. @brief Tests the flow of a failed @c updatePhoneNumberCredential:completion: call that
  459. automatically signs out.
  460. */
  461. func testUpdatePhoneNumberFailureAutoSignOut() throws {
  462. setFakeGetAccountProvider()
  463. let expectation = self.expectation(description: #function)
  464. let auth = try XCTUnwrap(UserTests.auth)
  465. signInWithEmailPasswordReturnFakeUser { user in
  466. do {
  467. self.rpcIssuer.respondBlock = {
  468. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  469. }
  470. self.expectVerifyPhoneNumberRequest()
  471. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  472. withVerificationID: self.kVerificationID,
  473. verificationCode: self.kVerificationCode
  474. )
  475. user.updatePhoneNumber(credential) { rawError in
  476. XCTAssertTrue(Thread.isMainThread)
  477. let error = try! XCTUnwrap(rawError)
  478. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  479. // User is no longer signed in.
  480. XCTAssertNil(UserTests.auth?.currentUser)
  481. expectation.fulfill()
  482. }
  483. }
  484. }
  485. waitForExpectations(timeout: 5)
  486. }
  487. #endif
  488. /** @fn testUpdatePasswordSuccess
  489. @brief Tests the flow of a successful @c updatePassword:completion: call.
  490. */
  491. func testUpdatePasswordSuccess() {
  492. setFakeGetAccountProvider()
  493. let expectation = self.expectation(description: #function)
  494. signInWithEmailPasswordReturnFakeUser { user in
  495. self.changeUserEmail(user: user, expectation: expectation)
  496. }
  497. waitForExpectations(timeout: 5)
  498. }
  499. /** @fn testUpdatePasswordFailure
  500. @brief Tests the flow of a failed @c updatePassword:completion: call.
  501. */
  502. func testUpdatePasswordFailure() {
  503. setFakeGetAccountProvider()
  504. let expectation = self.expectation(description: #function)
  505. signInWithEmailPasswordReturnFakeUser { user in
  506. do {
  507. self.rpcIssuer.respondBlock = {
  508. try self.rpcIssuer?.respond(serverErrorMessage: "CREDENTIAL_TOO_OLD_LOGIN_AGAIN")
  509. }
  510. user.updatePassword(to: self.kNewPassword) { rawError in
  511. XCTAssertTrue(Thread.isMainThread)
  512. let error = try! XCTUnwrap(rawError)
  513. XCTAssertEqual((error as NSError).code, AuthErrorCode.requiresRecentLogin.rawValue)
  514. // Email should not have changed on the client side.
  515. XCTAssertEqual(user.email, self.kEmail)
  516. // User is still signed in.
  517. XCTAssertEqual(UserTests.auth?.currentUser, user)
  518. expectation.fulfill()
  519. }
  520. }
  521. }
  522. waitForExpectations(timeout: 5)
  523. }
  524. /** @fn testUpdateEmptyPasswordFailure
  525. @brief Tests the flow of a failed @c updatePassword:completion: call due to an empty password.
  526. */
  527. func testUpdateEmptyPasswordFailure() {
  528. setFakeGetAccountProvider()
  529. let expectation = self.expectation(description: #function)
  530. signInWithEmailPasswordReturnFakeUser { user in
  531. do {
  532. self.rpcIssuer.respondBlock = {
  533. try self.rpcIssuer?.respond(serverErrorMessage: "WEAK_PASSWORD")
  534. }
  535. user.updatePassword(to: self.kNewPassword) { rawError in
  536. XCTAssertTrue(Thread.isMainThread)
  537. let error = try! XCTUnwrap(rawError)
  538. XCTAssertEqual((error as NSError).code, AuthErrorCode.weakPassword.rawValue)
  539. // Email should not have changed on the client side.
  540. XCTAssertEqual(user.email, self.kEmail)
  541. // User is still signed in.
  542. XCTAssertEqual(UserTests.auth?.currentUser, user)
  543. expectation.fulfill()
  544. }
  545. }
  546. }
  547. waitForExpectations(timeout: 5)
  548. }
  549. /** @fn testUpdatePasswordFailureAutoSignOut
  550. @brief Tests the flow of a failed @c updatePassword:completion: call that automatically signs
  551. out.
  552. */
  553. func testUpdatePasswordFailureAutoSignOut() {
  554. setFakeGetAccountProvider()
  555. let expectation = self.expectation(description: #function)
  556. signInWithEmailPasswordReturnFakeUser { user in
  557. do {
  558. self.rpcIssuer.respondBlock = {
  559. try self.rpcIssuer?.respond(serverErrorMessage: "USER_DISABLED")
  560. }
  561. user.updatePassword(to: self.kNewPassword) { rawError in
  562. XCTAssertTrue(Thread.isMainThread)
  563. let error = try! XCTUnwrap(rawError)
  564. XCTAssertEqual((error as NSError).code, AuthErrorCode.userDisabled.rawValue)
  565. // Email should not have changed on the client side.
  566. XCTAssertEqual(user.email, self.kEmail)
  567. // User is signed out.
  568. XCTAssertNil(UserTests.auth?.currentUser)
  569. expectation.fulfill()
  570. }
  571. }
  572. }
  573. waitForExpectations(timeout: 5)
  574. }
  575. /** @fn testChangeProfileSuccess
  576. @brief Tests a successful user profile change flow.
  577. */
  578. func testChangeProfileSuccess() {
  579. setFakeGetAccountProvider()
  580. let expectation = self.expectation(description: #function)
  581. signInWithEmailPasswordReturnFakeUser { user in
  582. do {
  583. self.rpcIssuer.respondBlock = {
  584. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  585. "refreshToken": self.kRefreshToken])
  586. }
  587. let profileChange = user.createProfileChangeRequest()
  588. profileChange.photoURL = URL(string: self.kTestPhotoURL)
  589. profileChange.displayName = self.kNewDisplayName
  590. profileChange.commitChanges { error in
  591. XCTAssertTrue(Thread.isMainThread)
  592. XCTAssertNil(error)
  593. XCTAssertEqual(user.displayName, self.kNewDisplayName)
  594. XCTAssertEqual(user.photoURL, URL(string: self.kTestPhotoURL))
  595. expectation.fulfill()
  596. }
  597. }
  598. }
  599. waitForExpectations(timeout: 5)
  600. }
  601. /** @fn testChangeProfileFailure
  602. @brief Tests a failed user profile change flow.
  603. */
  604. func testChangeProfileFailure() {
  605. setFakeGetAccountProvider()
  606. let expectation = self.expectation(description: #function)
  607. signInWithEmailPasswordReturnFakeUser { user in
  608. do {
  609. self.rpcIssuer.respondBlock = {
  610. try self.rpcIssuer?.respond(serverErrorMessage: "TOO_MANY_ATTEMPTS_TRY_LATER")
  611. }
  612. let profileChange = user.createProfileChangeRequest()
  613. profileChange.displayName = self.kNewDisplayName
  614. profileChange.commitChanges { rawError in
  615. XCTAssertTrue(Thread.isMainThread)
  616. let error = try! XCTUnwrap(rawError)
  617. XCTAssertEqual((error as NSError).code, AuthErrorCode.tooManyRequests.rawValue)
  618. // Email should not have changed on the client side.
  619. XCTAssertEqual(user.email, self.kEmail)
  620. XCTAssertEqual(user.displayName, self.kDisplayName)
  621. // User is still signed in.
  622. XCTAssertEqual(UserTests.auth?.currentUser, user)
  623. expectation.fulfill()
  624. }
  625. }
  626. }
  627. waitForExpectations(timeout: 5)
  628. }
  629. /** @fn testChangeProfileFailureAutoSignOut
  630. @brief Tests a failed user profile change flow that automatically signs out.
  631. */
  632. func testChangeProfileFailureAutoSignOut() {
  633. setFakeGetAccountProvider()
  634. let expectation = self.expectation(description: #function)
  635. signInWithEmailPasswordReturnFakeUser { user in
  636. do {
  637. self.rpcIssuer.respondBlock = {
  638. try self.rpcIssuer?.respond(serverErrorMessage: "USER_NOT_FOUND")
  639. }
  640. let profileChange = user.createProfileChangeRequest()
  641. profileChange.displayName = self.kNewDisplayName
  642. profileChange.commitChanges { rawError in
  643. XCTAssertTrue(Thread.isMainThread)
  644. let error = try! XCTUnwrap(rawError)
  645. XCTAssertEqual((error as NSError).code, AuthErrorCode.userNotFound.rawValue)
  646. // Email should not have changed on the client side.
  647. XCTAssertEqual(user.email, self.kEmail)
  648. // User is signed out.
  649. XCTAssertNil(UserTests.auth?.currentUser)
  650. expectation.fulfill()
  651. }
  652. }
  653. }
  654. waitForExpectations(timeout: 5)
  655. }
  656. /** @fn testGetIDTokenResultSuccess
  657. @brief Tests the flow of a successful @c getIDTokenResultWithCompletion: call.
  658. */
  659. func testGetIDTokenResultSuccess() {
  660. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessToken, forceRefresh: false)
  661. }
  662. /** @fn testGetIDTokenResultForcingRefreshSameAccessTokenSuccess
  663. @brief Tests the flow of a successful @c getIDTokenResultForcingRefresh:completion: call when
  664. the returned access token is the same as the stored access token.
  665. */
  666. func testGetIDTokenResultForcingRefreshSameAccessTokenSuccess() {
  667. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessToken)
  668. }
  669. /** @fn testGetIDTokenResultForcingRefreshSameAccessTokenSuccess
  670. @brief Tests the flow of a successful @c getIDTokenResultForcingRefresh:completion: call when
  671. the returned access token is the same as the stored access token.
  672. */
  673. func testGetIDTokenResultForcingRefreshSameAccessTokenSuccessAsync() async throws {
  674. try await internalGetIDTokenResultAsync(token: RPCBaseTests.kFakeAccessToken)
  675. }
  676. /** @fn testGetIDTokenResultForcingRefreshSuccess
  677. @brief Tests the flow successful @c getIDTokenResultForcingRefresh:completion: calls.
  678. */
  679. func testGetIDTokenResultForcingRefreshSuccess() {
  680. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength415)
  681. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength416)
  682. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength523,
  683. emailMatch: "aunitestuser4@gmail.com")
  684. }
  685. /** @fn testGetIDTokenResultSuccessWithBase64EncodedURL
  686. @brief Tests the flow of a successful @c getIDTokenResultWithCompletion: call using a base64 url
  687. encoded string.
  688. */
  689. func testGetIDTokenResultSuccessWithBase64EncodedURL() {
  690. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenWithBase64,
  691. emailMatch: ">>>>>>>>????????@gmail.com",
  692. audMatch: "??????????>>>>>>>>>>")
  693. }
  694. /** @fn testGetIDTokenResultForcingRefreshFailure
  695. @brief Tests the flow of a failed @c getIDTokenResultForcingRefresh:completion: call.
  696. */
  697. func testGetIDTokenResultForcingRefreshFailure() {
  698. setFakeGetAccountProvider()
  699. let expectation = self.expectation(description: #function)
  700. signInWithEmailPasswordReturnFakeUser(fakeAccessToken: RPCBaseTests.kFakeAccessToken) { user in
  701. let underlying = NSError(domain: "Test Error", code: 1)
  702. self.rpcIssuer?.secureTokenNetworkError =
  703. AuthErrorUtils.networkError(underlyingError: underlying) as NSError
  704. user.getIDTokenResult(forcingRefresh: true) { tokenResult, rawError in
  705. do {
  706. XCTAssertTrue(Thread.isMainThread)
  707. XCTAssertNil(tokenResult)
  708. let error = try XCTUnwrap(rawError)
  709. XCTAssertEqual((error as NSError).code, AuthErrorCode.networkError.rawValue)
  710. } catch {
  711. XCTFail("Caught an error in \(#function): \(error)")
  712. }
  713. expectation.fulfill()
  714. }
  715. }
  716. waitForExpectations(timeout: 5)
  717. }
  718. /** @fn testReloadSuccess
  719. @brief Tests the flow of a successful @c reloadWithCompletion: call.
  720. */
  721. func testReloadSuccess() {
  722. setFakeGetAccountProvider()
  723. let expectation = self.expectation(description: #function)
  724. signInWithEmailPasswordReturnFakeUser { user in
  725. user.reload { error in
  726. XCTAssertTrue(Thread.isMainThread)
  727. XCTAssertNil(error)
  728. XCTAssertEqual(user.displayName, self.kDisplayName)
  729. XCTAssertEqual(user.email, self.kEmail)
  730. expectation.fulfill()
  731. }
  732. }
  733. waitForExpectations(timeout: 5)
  734. }
  735. /** @fn testReloadFailure
  736. @brief Tests the flow of a failed @c reloadWithCompletion: call.
  737. */
  738. func testReloadFailure() {
  739. setFakeGetAccountProvider()
  740. let expectation = self.expectation(description: #function)
  741. signInWithEmailPasswordReturnFakeUser { user in
  742. do {
  743. self.rpcIssuer.respondBlock = {
  744. try self.rpcIssuer?.respond(serverErrorMessage: "QUOTA_EXCEEDED")
  745. }
  746. // Clear fake so we can inject error
  747. self.rpcIssuer?.fakeGetAccountProviderJSON = nil
  748. user.reload { rawError in
  749. XCTAssertTrue(Thread.isMainThread)
  750. let error = try! XCTUnwrap(rawError)
  751. XCTAssertEqual((error as NSError).code, AuthErrorCode.quotaExceeded.rawValue)
  752. // User is still signed in.
  753. XCTAssertEqual(UserTests.auth?.currentUser, user)
  754. expectation.fulfill()
  755. }
  756. }
  757. }
  758. waitForExpectations(timeout: 5)
  759. }
  760. /** @fn testReloadFailureAutoSignOut
  761. @brief Tests the flow of a failed @c reloadWithCompletion: call that automtatically signs out.
  762. */
  763. func testReloadFailureAutoSignOut() {
  764. setFakeGetAccountProvider()
  765. let expectation = self.expectation(description: #function)
  766. signInWithEmailPasswordReturnFakeUser { user in
  767. do {
  768. self.rpcIssuer.respondBlock = {
  769. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  770. }
  771. // Clear fake so we can inject error
  772. self.rpcIssuer?.fakeGetAccountProviderJSON = nil
  773. user.reload { rawError in
  774. XCTAssertTrue(Thread.isMainThread)
  775. let error = try! XCTUnwrap(rawError)
  776. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  777. // User is no longer signed in.
  778. XCTAssertNil(UserTests.auth?.currentUser)
  779. expectation.fulfill()
  780. }
  781. }
  782. }
  783. waitForExpectations(timeout: 5)
  784. }
  785. /** @fn testReauthenticateSuccess
  786. @brief Tests the flow of a successful @c reauthenticateWithCredential:completion: call.
  787. */
  788. func testReauthenticateSuccess() {
  789. setFakeGetAccountProvider()
  790. let expectation = self.expectation(description: #function)
  791. signInWithEmailPasswordReturnFakeUser { user in
  792. do {
  793. self.rpcIssuer.respondBlock = {
  794. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  795. "refreshToken": self.kRefreshToken])
  796. }
  797. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  798. password: self.kFakePassword)
  799. user.reauthenticate(with: emailCredential) { rawResult, error in
  800. XCTAssertTrue(Thread.isMainThread)
  801. XCTAssertNil(error)
  802. let result = try! XCTUnwrap(rawResult)
  803. XCTAssertEqual(result.user.uid, user.uid)
  804. XCTAssertEqual(result.user.email, user.email)
  805. XCTAssertEqual(result.additionalUserInfo?.isNewUser, false)
  806. // User is still signed in.
  807. XCTAssertEqual(UserTests.auth?.currentUser, user)
  808. expectation.fulfill()
  809. }
  810. }
  811. }
  812. waitForExpectations(timeout: 5)
  813. }
  814. /** @fn testReauthenticateWithCredentialSuccess
  815. @brief Tests the flow of a successful @c reauthenticateWithCredential call.
  816. */
  817. func testReauthenticateWithCredentialSuccess() throws {
  818. let expectation = self.expectation(description: #function)
  819. signInWithGoogleCredential { user in
  820. do {
  821. self.rpcIssuer.respondBlock = {
  822. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  823. "refreshToken": self.kRefreshToken,
  824. "federatedId": self.kGoogleID,
  825. "providerId": GoogleAuthProvider.id,
  826. "localId": self.kLocalID,
  827. "displayName": self.kGoogleDisplayName,
  828. "rawUserInfo": self.kGoogleProfile,
  829. "username": self.kUserName])
  830. }
  831. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  832. accessToken: self.kGoogleAccessToken)
  833. user.reauthenticate(with: googleCredential) { reauthenticatedAuthResult, error in
  834. XCTAssertTrue(Thread.isMainThread)
  835. do {
  836. try self.assertUserGoogle(reauthenticatedAuthResult?.user)
  837. } catch {
  838. XCTFail("\(error)")
  839. }
  840. XCTAssertNil(error)
  841. // Verify that the current user is unchanged.
  842. XCTAssertEqual(UserTests.auth?.currentUser, user)
  843. // Verify that the current user and reauthenticated user are not same pointers.
  844. XCTAssertNotEqual(user, reauthenticatedAuthResult?.user)
  845. // Verify that anyway the current user and reauthenticated user have same IDs.
  846. XCTAssertEqual(reauthenticatedAuthResult?.user.uid, user.uid)
  847. XCTAssertEqual(reauthenticatedAuthResult?.user.email, user.email)
  848. XCTAssertEqual(reauthenticatedAuthResult?.user.displayName, user.displayName)
  849. XCTAssertEqual(reauthenticatedAuthResult?.additionalUserInfo?.username, self.kUserName)
  850. XCTAssertEqual(reauthenticatedAuthResult?.additionalUserInfo?.providerID,
  851. GoogleAuthProvider.id)
  852. XCTAssertEqual(
  853. reauthenticatedAuthResult?.additionalUserInfo?.profile as? [String: String],
  854. self.kGoogleProfile
  855. )
  856. expectation.fulfill()
  857. }
  858. }
  859. }
  860. waitForExpectations(timeout: 5)
  861. try assertUserGoogle(UserTests.auth?.currentUser)
  862. }
  863. /** @fn testReauthenticateFailure
  864. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call.
  865. */
  866. func testReauthenticateFailure() {
  867. setFakeGetAccountProvider()
  868. let expectation = self.expectation(description: #function)
  869. signInWithEmailPasswordReturnFakeUser { user in
  870. do {
  871. self.rpcIssuer.respondBlock = {
  872. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  873. "refreshToken": self.kRefreshToken])
  874. }
  875. self.setFakeGetAccountProvider(withLocalID: "A different Local ID")
  876. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  877. password: self.kFakePassword)
  878. user.reauthenticate(with: emailCredential) { reauthenticatedAuthResult, rawError in
  879. XCTAssertTrue(Thread.isMainThread)
  880. let error = try! XCTUnwrap(rawError)
  881. XCTAssertEqual((error as NSError).code, AuthErrorCode.userMismatch.rawValue)
  882. // Email should not have changed on the client side.
  883. XCTAssertEqual(user.email, self.kEmail)
  884. // User is still signed in.
  885. XCTAssertEqual(UserTests.auth?.currentUser, user)
  886. expectation.fulfill()
  887. }
  888. }
  889. }
  890. waitForExpectations(timeout: 5)
  891. }
  892. /** @fn testReauthenticateUserMismatchFailure
  893. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call due to trying
  894. to reauthenticate a user that does not exist.
  895. */
  896. func testReauthenticateUserMismatchFailure() {
  897. setFakeGetAccountProvider()
  898. let expectation = self.expectation(description: #function)
  899. signInWithEmailPasswordReturnFakeUser { user in
  900. do {
  901. self.rpcIssuer.respondBlock = {
  902. try self.rpcIssuer?.respond(serverErrorMessage: "USER_NOT_FOUND")
  903. }
  904. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  905. accessToken: self.kGoogleAccessToken)
  906. user.reauthenticate(with: googleCredential) { reauthenticatedAuthResult, rawError in
  907. XCTAssertTrue(Thread.isMainThread)
  908. let error = try! XCTUnwrap(rawError)
  909. XCTAssertEqual((error as NSError).code, AuthErrorCode.userMismatch.rawValue)
  910. // Email should not have changed on the client side.
  911. XCTAssertEqual(user.email, self.kEmail)
  912. // User is still signed in.
  913. XCTAssertEqual(UserTests.auth?.currentUser, user)
  914. expectation.fulfill()
  915. }
  916. }
  917. }
  918. waitForExpectations(timeout: 5)
  919. }
  920. /** @fn testLinkAndRetrieveDataSuccess (and old testLinkCredentialSuccess)
  921. @brief Tests the flow of a successful @c linkWithCredential call.
  922. */
  923. func testLinkAndRetrieveDataSuccess() throws {
  924. setFakeGetAccountProvider()
  925. let expectation = self.expectation(description: #function)
  926. let auth = try XCTUnwrap(UserTests.auth)
  927. signInWithFacebookCredential { user in
  928. XCTAssertNotNil(user)
  929. do {
  930. self.setFakeGoogleGetAccountProvider()
  931. self.rpcIssuer.respondBlock = {
  932. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  933. "refreshToken": self.kRefreshToken,
  934. "federatedId": self.kGoogleID,
  935. "providerId": GoogleAuthProvider.id,
  936. "localId": self.kLocalID,
  937. "displayName": self.kGoogleDisplayName,
  938. "rawUserInfo": self.kGoogleProfile,
  939. "username": self.kUserName])
  940. }
  941. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  942. accessToken: self.kGoogleAccessToken)
  943. user.link(with: googleCredential) { linkAuthResult, error in
  944. XCTAssertTrue(Thread.isMainThread)
  945. XCTAssertNil(error)
  946. // Verify that the current user is unchanged.
  947. XCTAssertEqual(auth.currentUser, user)
  948. // Verify that the current user and reauthenticated user are the same pointers.
  949. XCTAssertEqual(user, linkAuthResult?.user)
  950. // Verify that anyway the current user and reauthenticated user have same IDs.
  951. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  952. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  953. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  954. XCTAssertEqual(linkAuthResult?.additionalUserInfo?.username, self.kUserName)
  955. XCTAssertEqual(linkAuthResult?.additionalUserInfo?.providerID,
  956. GoogleAuthProvider.id)
  957. XCTAssertEqual(
  958. linkAuthResult?.additionalUserInfo?.profile as? [String: String],
  959. self.kGoogleProfile
  960. )
  961. XCTAssertEqual(linkAuthResult?.user.providerData.first?.providerID, GoogleAuthProvider.id)
  962. expectation.fulfill()
  963. }
  964. }
  965. }
  966. waitForExpectations(timeout: 5)
  967. try assertUserGoogle(auth.currentUser)
  968. }
  969. /** @fn testLinkAndRetrieveDataError
  970. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  971. call with an error from the backend.
  972. */
  973. func testLinkAndRetrieveDataError() throws {
  974. setFakeGetAccountProvider()
  975. let expectation = self.expectation(description: #function)
  976. signInWithFacebookCredential { user in
  977. XCTAssertNotNil(user)
  978. do {
  979. self.setFakeGetAccountProvider()
  980. self.rpcIssuer.respondBlock = {
  981. try self.rpcIssuer?.respond(serverErrorMessage: "CREDENTIAL_TOO_OLD_LOGIN_AGAIN")
  982. }
  983. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  984. accessToken: self.kGoogleAccessToken)
  985. user.link(with: googleCredential) { linkAuthResult, rawError in
  986. XCTAssertTrue(Thread.isMainThread)
  987. XCTAssertNil(linkAuthResult)
  988. let error = try! XCTUnwrap(rawError)
  989. XCTAssertEqual((error as NSError).code, AuthErrorCode.requiresRecentLogin.rawValue)
  990. // Email should not have changed on the client side.
  991. XCTAssertEqual(user.email, self.kFacebookEmail)
  992. // User is still signed in.
  993. XCTAssertEqual(UserTests.auth?.currentUser, user)
  994. expectation.fulfill()
  995. }
  996. }
  997. }
  998. waitForExpectations(timeout: 5)
  999. }
  1000. /** @fn testLinkAndRetrieveDataProviderAlreadyLinked and old testLinkCredentialProviderAlreadyLinkedError
  1001. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1002. call with FIRAuthErrorCodeProviderAlreadyLinked, which is a client side error.
  1003. */
  1004. func testLinkAndRetrieveDataProviderAlreadyLinked() throws {
  1005. setFakeGetAccountProvider()
  1006. let expectation = self.expectation(description: #function)
  1007. signInWithFacebookCredential { user in
  1008. XCTAssertNotNil(user)
  1009. do {
  1010. self.setFakeGetAccountProvider()
  1011. let facebookCredential =
  1012. FacebookAuthProvider.credential(withAccessToken: self.kFacebookAccessToken)
  1013. user.link(with: facebookCredential) { linkAuthResult, rawError in
  1014. XCTAssertTrue(Thread.isMainThread)
  1015. XCTAssertNil(linkAuthResult)
  1016. do {
  1017. let error = try XCTUnwrap(rawError)
  1018. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1019. } catch {
  1020. XCTFail("Expected to throw providerAlreadyLinked error.")
  1021. }
  1022. // User is still signed in.
  1023. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1024. expectation.fulfill()
  1025. }
  1026. }
  1027. }
  1028. waitForExpectations(timeout: 5)
  1029. }
  1030. /** @fn testLinkAndRetrieveDataErrorAutoSignOut (and old testLinkCredentialError)
  1031. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1032. call that automatically signs out.
  1033. */
  1034. func testLinkAndRetrieveDataErrorAutoSignOut() throws {
  1035. setFakeGetAccountProvider()
  1036. let expectation = self.expectation(description: #function)
  1037. signInWithFacebookCredential { user in
  1038. XCTAssertNotNil(user)
  1039. do {
  1040. self.setFakeGetAccountProvider()
  1041. self.rpcIssuer.respondBlock = {
  1042. try self.rpcIssuer?.respond(serverErrorMessage: "USER_DISABLED")
  1043. }
  1044. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  1045. accessToken: self.kGoogleAccessToken)
  1046. user.link(with: googleCredential) { linkAuthResult, rawError in
  1047. XCTAssertTrue(Thread.isMainThread)
  1048. XCTAssertNil(linkAuthResult)
  1049. let error = try! XCTUnwrap(rawError)
  1050. XCTAssertEqual((error as NSError).code, AuthErrorCode.userDisabled.rawValue)
  1051. // User is signed out.
  1052. XCTAssertNil(UserTests.auth?.currentUser)
  1053. expectation.fulfill()
  1054. }
  1055. }
  1056. }
  1057. waitForExpectations(timeout: 5)
  1058. }
  1059. /** @fn testLinkEmailAndRetrieveDataSuccess
  1060. @brief Tests the flow of a successful @c linkWithCredential:completion:
  1061. invocation for email credential.
  1062. */
  1063. func testLinkEmailAndRetrieveDataSuccess() throws {
  1064. setFakeGetAccountProvider()
  1065. let expectation = self.expectation(description: #function)
  1066. let auth = try XCTUnwrap(UserTests.auth)
  1067. signInWithFacebookCredential { user in
  1068. XCTAssertNotNil(user)
  1069. do {
  1070. self.rpcIssuer.respondBlock = {
  1071. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1072. XCTAssertNotNil(request)
  1073. XCTAssertEqual(request?.email, self.kEmail)
  1074. XCTAssertEqual(request?.password, self.kFakePassword)
  1075. XCTAssertNil(request?.displayName)
  1076. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1077. "refreshToken": self.kRefreshToken])
  1078. self.setFakeGetAccountProvider(withProviderID: EmailAuthProvider.id)
  1079. }
  1080. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1081. password: self.kFakePassword)
  1082. user.link(with: emailCredential) { linkAuthResult, error in
  1083. XCTAssertTrue(Thread.isMainThread)
  1084. XCTAssertNil(error)
  1085. // Verify that the current user is unchanged.
  1086. XCTAssertEqual(auth.currentUser, user)
  1087. // Verify that the current user and reauthenticated user are the same pointers.
  1088. XCTAssertEqual(user, linkAuthResult?.user)
  1089. // Verify that anyway the current user and reauthenticated user have same IDs.
  1090. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1091. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1092. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1093. expectation.fulfill()
  1094. }
  1095. }
  1096. }
  1097. waitForExpectations(timeout: 5)
  1098. }
  1099. /** @fn tesLlinkEmailProviderAlreadyLinkedError
  1100. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1101. invocation for email credential and FIRAuthErrorCodeProviderAlreadyLinked which is a client
  1102. side error.
  1103. */
  1104. func testLinkEmailProviderAlreadyLinkedError() throws {
  1105. setFakeGetAccountProvider()
  1106. let expectation = self.expectation(description: #function)
  1107. signInWithFacebookCredential { user in
  1108. XCTAssertNotNil(user)
  1109. do {
  1110. self.rpcIssuer.respondBlock = {
  1111. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1112. XCTAssertNotNil(request)
  1113. XCTAssertEqual(request?.email, self.kEmail)
  1114. XCTAssertEqual(request?.password, self.kFakePassword)
  1115. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1116. "refreshToken": self.kRefreshToken])
  1117. self.setFakeGetAccountProvider(withProviderID: EmailAuthProvider.id)
  1118. }
  1119. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1120. password: self.kFakePassword)
  1121. user.link(with: emailCredential) { linkAuthResult, error in
  1122. XCTAssertEqual(user, linkAuthResult?.user)
  1123. linkAuthResult?.user.link(with: emailCredential) { linkLinkAuthResult, rawError in
  1124. XCTAssertTrue(Thread.isMainThread)
  1125. XCTAssertNil(linkLinkAuthResult)
  1126. do {
  1127. let error = try XCTUnwrap(rawError)
  1128. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1129. } catch {
  1130. XCTFail("Expected to throw providerAlreadyLinked error.")
  1131. }
  1132. // User is still signed in.
  1133. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1134. expectation.fulfill()
  1135. }
  1136. }
  1137. }
  1138. }
  1139. waitForExpectations(timeout: 5)
  1140. }
  1141. /** @fn testLinkEmailAndRetrieveDataError
  1142. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1143. invocation for email credential and an error from the backend.
  1144. */
  1145. func testLinkEmailAndRetrieveDataError() throws {
  1146. setFakeGetAccountProvider()
  1147. let expectation = self.expectation(description: #function)
  1148. signInWithFacebookCredential { user in
  1149. XCTAssertNotNil(user)
  1150. do {
  1151. self.rpcIssuer.respondBlock = {
  1152. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1153. XCTAssertNotNil(request)
  1154. XCTAssertEqual(request?.email, self.kEmail)
  1155. XCTAssertEqual(request?.password, self.kFakePassword)
  1156. try self.rpcIssuer?.respond(serverErrorMessage: "TOO_MANY_ATTEMPTS_TRY_LATER")
  1157. }
  1158. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1159. password: self.kFakePassword)
  1160. user.link(with: emailCredential) { linkAuthResult, rawError in
  1161. XCTAssertTrue(Thread.isMainThread)
  1162. XCTAssertNil(linkAuthResult)
  1163. let error = try! XCTUnwrap(rawError)
  1164. XCTAssertEqual((error as NSError).code, AuthErrorCode.tooManyRequests.rawValue)
  1165. // User is still signed in.
  1166. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1167. expectation.fulfill()
  1168. }
  1169. }
  1170. }
  1171. waitForExpectations(timeout: 5)
  1172. }
  1173. /** @fn testLinkEmailAndRetrieveDataErrorAutoSignOut
  1174. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1175. invocation that automatically signs out.
  1176. */
  1177. func testLinkEmailAndRetrieveDataErrorAutoSignOut() throws {
  1178. setFakeGetAccountProvider()
  1179. let expectation = self.expectation(description: #function)
  1180. signInWithFacebookCredential { user in
  1181. XCTAssertNotNil(user)
  1182. do {
  1183. self.rpcIssuer.respondBlock = {
  1184. XCTAssertNotNil(self.rpcIssuer?.request as? SignUpNewUserRequest)
  1185. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1186. }
  1187. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1188. password: self.kFakePassword)
  1189. user.link(with: emailCredential) { linkAuthResult, rawError in
  1190. XCTAssertTrue(Thread.isMainThread)
  1191. XCTAssertNil(linkAuthResult)
  1192. let error = try! XCTUnwrap(rawError)
  1193. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1194. // User is signed out.
  1195. XCTAssertNil(UserTests.auth?.currentUser)
  1196. expectation.fulfill()
  1197. }
  1198. }
  1199. }
  1200. waitForExpectations(timeout: 5)
  1201. }
  1202. #if os(iOS)
  1203. private class FakeOAuthProvider: OAuthProvider {
  1204. override func getCredentialWith(_ UIDelegate: AuthUIDelegate?,
  1205. completion: ((AuthCredential?, Error?) -> Void)? = nil) {
  1206. if let completion {
  1207. let credential = OAuthCredential(
  1208. withProviderID: GoogleAuthProvider.id,
  1209. sessionID: UserTests.kOAuthSessionID,
  1210. OAuthResponseURLString: UserTests.kOAuthRequestURI
  1211. )
  1212. completion(credential, nil)
  1213. }
  1214. }
  1215. }
  1216. /** @fn testLinkProviderFailure
  1217. @brief Tests the flow of a failed @c linkWithProvider:completion:
  1218. call.
  1219. */
  1220. func testLinkProviderFailure() throws {
  1221. setFakeGetAccountProvider()
  1222. let expectation = self.expectation(description: #function)
  1223. let auth = try XCTUnwrap(UserTests.auth)
  1224. signInWithFacebookCredential { user in
  1225. XCTAssertNotNil(user)
  1226. do {
  1227. self.setFakeGetAccountProvider()
  1228. self.rpcIssuer.respondBlock = {
  1229. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1230. }
  1231. user.link(with: FakeOAuthProvider(providerID: "foo", auth: auth),
  1232. uiDelegate: nil) { linkAuthResult, rawError in
  1233. XCTAssertTrue(Thread.isMainThread)
  1234. XCTAssertNil(linkAuthResult)
  1235. let error = try! XCTUnwrap(rawError)
  1236. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1237. // User is signed out.
  1238. XCTAssertNil(UserTests.auth?.currentUser)
  1239. expectation.fulfill()
  1240. }
  1241. }
  1242. }
  1243. waitForExpectations(timeout: 5)
  1244. }
  1245. /** @fn testReauthenticateWithProviderFailure
  1246. @brief Tests the flow of a failed @c reauthenticateWithProvider:completion: call.
  1247. */
  1248. func testReauthenticateWithProviderFailure() throws {
  1249. setFakeGetAccountProvider()
  1250. let expectation = self.expectation(description: #function)
  1251. let auth = try XCTUnwrap(UserTests.auth)
  1252. signInWithFacebookCredential { user in
  1253. XCTAssertNotNil(user)
  1254. do {
  1255. self.setFakeGetAccountProvider()
  1256. self.rpcIssuer.respondBlock = {
  1257. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1258. }
  1259. user.reauthenticate(with: FakeOAuthProvider(providerID: "foo", auth: auth),
  1260. uiDelegate: nil) { linkAuthResult, rawError in
  1261. XCTAssertTrue(Thread.isMainThread)
  1262. XCTAssertNil(linkAuthResult)
  1263. let error = try! XCTUnwrap(rawError)
  1264. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1265. // User is still signed in.
  1266. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1267. expectation.fulfill()
  1268. }
  1269. }
  1270. }
  1271. waitForExpectations(timeout: 5)
  1272. }
  1273. /** @fn testLinkPhoneAuthCredentialSuccess
  1274. @brief Tests the flow of a successful @c linkWithCredential call using a phoneAuthCredential.
  1275. */
  1276. func testLinkPhoneAuthCredentialSuccess() throws {
  1277. setFakeGetAccountProvider()
  1278. let expectation = self.expectation(description: #function)
  1279. let auth = try XCTUnwrap(UserTests.auth)
  1280. signInWithEmailPasswordReturnFakeUser { user in
  1281. XCTAssertNotNil(user)
  1282. self.expectVerifyPhoneNumberRequest(isLink: true)
  1283. do {
  1284. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1285. self.rpcIssuer.respondBlock = {
  1286. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1287. "refreshToken": self.kRefreshToken])
  1288. }
  1289. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1290. withVerificationID: self.kVerificationID,
  1291. verificationCode: self.kVerificationCode
  1292. )
  1293. user.link(with: credential) { linkAuthResult, error in
  1294. XCTAssertTrue(Thread.isMainThread)
  1295. XCTAssertNil(error)
  1296. // Verify that the current user is unchanged.
  1297. XCTAssertEqual(auth.currentUser, user)
  1298. // Verify that the current user and reauthenticated user are the same pointers.
  1299. XCTAssertEqual(user, linkAuthResult?.user)
  1300. // Verify that anyway the current user and reauthenticated user have same IDs.
  1301. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1302. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1303. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1304. XCTAssertEqual(auth.currentUser?.providerData.first?.providerID, PhoneAuthProvider.id)
  1305. XCTAssertEqual(
  1306. linkAuthResult?.user.providerData.first?.providerID,
  1307. PhoneAuthProvider.id
  1308. )
  1309. XCTAssertEqual(auth.currentUser?.phoneNumber, self.kTestPhoneNumber)
  1310. expectation.fulfill()
  1311. }
  1312. }
  1313. }
  1314. waitForExpectations(timeout: 5)
  1315. }
  1316. /** @fn testUnlinkPhoneAuthCredentialSuccess
  1317. @brief Tests the flow of a successful @c unlinkFromProvider:completion: call using a
  1318. @c FIRPhoneAuthProvider.
  1319. */
  1320. func testUnlinkPhoneAuthCredentialSuccess() throws {
  1321. setFakeGetAccountProvider()
  1322. let expectation = self.expectation(description: #function)
  1323. let auth = try XCTUnwrap(UserTests.auth)
  1324. signInWithEmailPasswordReturnFakeUser { user in
  1325. XCTAssertNotNil(user)
  1326. self.expectVerifyPhoneNumberRequest(isLink: true)
  1327. do {
  1328. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1329. self.rpcIssuer.respondBlock = {
  1330. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1331. "refreshToken": self.kRefreshToken])
  1332. }
  1333. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1334. withVerificationID: self.kVerificationID,
  1335. verificationCode: self.kVerificationCode
  1336. )
  1337. user.link(with: credential) { linkAuthResult, error in
  1338. XCTAssertTrue(Thread.isMainThread)
  1339. XCTAssertNil(error)
  1340. // Verify that the current user is unchanged.
  1341. XCTAssertEqual(auth.currentUser, user)
  1342. // Verify that the current user and reauthenticated user are the same pointers.
  1343. XCTAssertEqual(user, linkAuthResult?.user)
  1344. // Verify that anyway the current user and reauthenticated user have same IDs.
  1345. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1346. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1347. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1348. XCTAssertEqual(auth.currentUser?.providerData.first?.providerID, PhoneAuthProvider.id)
  1349. XCTAssertEqual(
  1350. linkAuthResult?.user.providerData.first?.providerID,
  1351. PhoneAuthProvider.id
  1352. )
  1353. XCTAssertEqual(auth.currentUser?.phoneNumber, self.kTestPhoneNumber)
  1354. // Immediately unlink the phone auth provider.
  1355. self.rpcIssuer.respondBlock = {
  1356. let request = try XCTUnwrap(self.rpcIssuer?.request as? SetAccountInfoRequest)
  1357. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1358. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1359. XCTAssertNil(request.email)
  1360. XCTAssertNil(request.password)
  1361. XCTAssertNil(request.localID)
  1362. XCTAssertNil(request.displayName)
  1363. XCTAssertNil(request.photoURL)
  1364. XCTAssertNil(request.providers)
  1365. XCTAssertNil(request.deleteAttributes)
  1366. XCTAssertEqual(try XCTUnwrap(request.deleteProviders?.first), PhoneAuthProvider.id)
  1367. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1368. "refreshToken": self.kRefreshToken])
  1369. }
  1370. user.unlink(fromProvider: PhoneAuthProvider.id) { user, error in
  1371. XCTAssertNil(error)
  1372. XCTAssertEqual(auth.currentUser, user)
  1373. XCTAssertNil(auth.currentUser?.phoneNumber)
  1374. expectation.fulfill()
  1375. }
  1376. }
  1377. }
  1378. }
  1379. waitForExpectations(timeout: 5)
  1380. }
  1381. /** @fn testlinkPhoneAuthCredentialFailure
  1382. @brief Tests the flow of a failed call to @c linkWithCredential:completion: due
  1383. to a phone provider already being linked.
  1384. */
  1385. func testlinkPhoneAuthCredentialFailure() throws {
  1386. setFakeGetAccountProvider(withPasswordHash: kFakePassword)
  1387. let expectation = self.expectation(description: #function)
  1388. signInWithEmailPasswordReturnFakeUser { user in
  1389. XCTAssertNotNil(user)
  1390. self.expectVerifyPhoneNumberRequest(isLink: true)
  1391. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1392. let credential = EmailAuthCredential(withEmail: self.kEmail, password: self.kFakePassword)
  1393. user.link(with: credential) { linkAuthResult, rawError in
  1394. XCTAssertTrue(Thread.isMainThread)
  1395. XCTAssertNil(linkAuthResult)
  1396. if let error = try? XCTUnwrap(rawError) {
  1397. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1398. } else {
  1399. XCTFail("Did not throw expected error")
  1400. }
  1401. expectation.fulfill()
  1402. }
  1403. }
  1404. waitForExpectations(timeout: 5)
  1405. }
  1406. /** @fn testlinkPhoneCredentialAlreadyExistsError
  1407. @brief Tests the flow of @c linkWithCredential:completion:
  1408. call using a phoneAuthCredential and a credential already exists error. In this case we
  1409. should get a AuthCredential in the error object.
  1410. */
  1411. func testlinkPhoneCredentialAlreadyExistsError() throws {
  1412. setFakeGetAccountProvider()
  1413. let expectation = self.expectation(description: #function)
  1414. let auth = try XCTUnwrap(UserTests.auth)
  1415. signInWithEmailPasswordReturnFakeUser { user in
  1416. XCTAssertNotNil(user)
  1417. self.expectVerifyPhoneNumberRequest(isLink: true)
  1418. do {
  1419. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1420. self.rpcIssuer.respondBlock = {
  1421. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1422. "refreshToken": self.kRefreshToken,
  1423. "phoneNumber": self.kTestPhoneNumber,
  1424. "temporaryProof": "Fake Temporary Proof"])
  1425. }
  1426. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1427. withVerificationID: self.kVerificationID,
  1428. verificationCode: self.kVerificationCode
  1429. )
  1430. user.link(with: credential) { linkAuthResult, rawError in
  1431. XCTAssertTrue(Thread.isMainThread)
  1432. XCTAssertNil(linkAuthResult)
  1433. do {
  1434. let error = try XCTUnwrap(rawError)
  1435. XCTAssertEqual((error as NSError).code, AuthErrorCode.credentialAlreadyInUse.rawValue)
  1436. let credential = try XCTUnwrap((error as NSError)
  1437. .userInfo[AuthErrors.userInfoUpdatedCredentialKey] as? PhoneAuthCredential)
  1438. switch credential.credentialKind {
  1439. case let .phoneNumber(phoneNumber, temporaryProof):
  1440. XCTAssertEqual(temporaryProof, "Fake Temporary Proof")
  1441. XCTAssertEqual(phoneNumber, self.kTestPhoneNumber)
  1442. case .verification: XCTFail("Should be phoneNumber case")
  1443. }
  1444. } catch {
  1445. XCTFail("Did not throw expected error \(error)")
  1446. }
  1447. expectation.fulfill()
  1448. }
  1449. }
  1450. }
  1451. waitForExpectations(timeout: 5)
  1452. }
  1453. #endif
  1454. // MARK: Private helper functions
  1455. private func expectVerifyPhoneNumberRequest(isLink: Bool = false) {
  1456. rpcIssuer?.verifyPhoneNumberRequester = { request in
  1457. XCTAssertEqual(request.verificationID, self.kVerificationID)
  1458. XCTAssertEqual(request.verificationCode, self.kVerificationCode)
  1459. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1460. if isLink {
  1461. XCTAssertEqual(request.operation, AuthOperationType.link)
  1462. } else {
  1463. XCTAssertEqual(request.operation, AuthOperationType.update)
  1464. }
  1465. }
  1466. }
  1467. private func internalGetIDTokenResult(token: String, forceRefresh: Bool = true,
  1468. emailMatch: String = "aunitestuser@gmail.com",
  1469. audMatch: String = "test_aud") {
  1470. setFakeGetAccountProvider()
  1471. let expectation = self.expectation(description: #function)
  1472. signInWithEmailPasswordReturnFakeUser(fakeAccessToken: token) { user in
  1473. user.getIDTokenResult(forcingRefresh: forceRefresh) { rawTokenResult, error in
  1474. XCTAssertTrue(Thread.isMainThread)
  1475. XCTAssertNil(error)
  1476. XCTAssertEqual(user.displayName, self.kDisplayName)
  1477. XCTAssertEqual(user.email, self.kEmail)
  1478. let tokenResult = try! XCTUnwrap(rawTokenResult)
  1479. XCTAssertEqual(tokenResult.token, token)
  1480. XCTAssertNotNil(tokenResult.issuedAtDate)
  1481. XCTAssertNotNil(tokenResult.authDate)
  1482. XCTAssertNotNil(tokenResult.expirationDate)
  1483. XCTAssertNotNil(tokenResult.signInProvider)
  1484. // The lowercased is for the base64 test which seems to be an erroneously uppercased
  1485. // "Password"?
  1486. XCTAssertEqual(tokenResult.signInProvider.lowercased(), EmailAuthProvider.id)
  1487. XCTAssertEqual(tokenResult.claims["email"] as! String, emailMatch)
  1488. XCTAssertEqual(tokenResult.claims["aud"] as! String, audMatch)
  1489. XCTAssertEqual(tokenResult.signInSecondFactor, "")
  1490. expectation.fulfill()
  1491. }
  1492. }
  1493. waitForExpectations(timeout: 5)
  1494. }
  1495. private func internalGetIDTokenResultAsync(token: String, forceRefresh: Bool = true,
  1496. emailMatch: String = "aunitestuser@gmail.com",
  1497. audMatch: String = "test_aud") async throws {
  1498. setFakeGetAccountProvider()
  1499. let user = try await signInWithEmailPasswordReturnFakeUserAsync(fakeAccessToken: token)
  1500. let tokenResult = try await user.getIDTokenResult(forcingRefresh: forceRefresh)
  1501. XCTAssertEqual(user.displayName, kDisplayName)
  1502. XCTAssertEqual(user.email, kEmail)
  1503. XCTAssertEqual(tokenResult.token, token)
  1504. XCTAssertNotNil(tokenResult.issuedAtDate)
  1505. XCTAssertNotNil(tokenResult.authDate)
  1506. XCTAssertNotNil(tokenResult.expirationDate)
  1507. XCTAssertNotNil(tokenResult.signInProvider)
  1508. // The lowercased is for the base64 test which seems to be an erroneously uppercased
  1509. // "Password"?
  1510. XCTAssertEqual(tokenResult.signInProvider.lowercased(), EmailAuthProvider.id)
  1511. XCTAssertEqual(tokenResult.claims["email"] as! String, emailMatch)
  1512. XCTAssertEqual(tokenResult.claims["aud"] as! String, audMatch)
  1513. XCTAssertEqual(tokenResult.signInSecondFactor, "")
  1514. }
  1515. private func changeUserEmail(user: User, changeEmail: Bool = false,
  1516. expectation: XCTestExpectation) {
  1517. do {
  1518. XCTAssertEqual(user.providerID, "Firebase")
  1519. XCTAssertEqual(user.uid, kLocalID)
  1520. XCTAssertEqual(user.displayName, kDisplayName)
  1521. XCTAssertEqual(user.photoURL, URL(string: kTestPhotoURL))
  1522. XCTAssertEqual(user.email, kEmail)
  1523. // Pretend that the display name on the server has been changed since the original signin.
  1524. setFakeGetAccountProvider(withNewDisplayName: kNewDisplayName)
  1525. rpcIssuer.respondBlock = {
  1526. let request = try XCTUnwrap(self.rpcIssuer?.request as? SetAccountInfoRequest)
  1527. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1528. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1529. if changeEmail {
  1530. XCTAssertEqual(request.email, self.kNewEmail)
  1531. XCTAssertNil(request.password)
  1532. } else {
  1533. XCTAssertEqual(request.password, self.kNewPassword)
  1534. XCTAssertNil(request.email)
  1535. }
  1536. XCTAssertNil(request.localID)
  1537. XCTAssertNil(request.displayName)
  1538. XCTAssertNil(request.photoURL)
  1539. XCTAssertNil(request.providers)
  1540. XCTAssertNil(request.deleteAttributes)
  1541. XCTAssertNil(request.deleteProviders)
  1542. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1543. "email": self.kNewEmail,
  1544. "refreshToken": self.kRefreshToken])
  1545. }
  1546. if changeEmail {
  1547. user.updateEmail(to: kNewEmail) { error in
  1548. XCTAssertNil(error)
  1549. XCTAssertEqual(user.email, self.kNewEmail)
  1550. XCTAssertEqual(user.displayName, self.kNewDisplayName)
  1551. XCTAssertFalse(user.isAnonymous)
  1552. expectation.fulfill()
  1553. }
  1554. } else {
  1555. user.updatePassword(to: kNewPassword) { error in
  1556. XCTAssertNil(error)
  1557. XCTAssertEqual(user.displayName, self.kNewDisplayName)
  1558. XCTAssertFalse(user.isAnonymous)
  1559. expectation.fulfill()
  1560. }
  1561. }
  1562. }
  1563. }
  1564. private func signInWithEmailPasswordReturnFakeUser(fakeAccessToken: String = RPCBaseTests
  1565. .kFakeAccessToken,
  1566. completion: @escaping (User) -> Void) {
  1567. let kRefreshToken = "fakeRefreshToken"
  1568. setFakeSecureTokenService(fakeAccessToken: fakeAccessToken)
  1569. rpcIssuer?.verifyPasswordRequester = { request in
  1570. // 2. Validate the created Request instance.
  1571. XCTAssertEqual(request.email, self.kEmail)
  1572. XCTAssertEqual(request.password, self.kFakePassword)
  1573. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1574. XCTAssertTrue(request.returnSecureToken)
  1575. do {
  1576. // 3. Send the response from the fake backend.
  1577. try self.rpcIssuer?.respond(withJSON: ["idToken": fakeAccessToken,
  1578. "isNewUser": true,
  1579. "refreshToken": kRefreshToken])
  1580. } catch {
  1581. XCTFail("Failure sending response: \(error)")
  1582. }
  1583. }
  1584. // 1. After setting up fakes, sign out and sign in.
  1585. do {
  1586. try UserTests.auth?.signOut()
  1587. } catch {
  1588. XCTFail("Sign out failed: \(error)")
  1589. return
  1590. }
  1591. UserTests.auth?.signIn(withEmail: kEmail, password: kFakePassword) { authResult, error in
  1592. // 4. After the response triggers the callback, verify the returned result.
  1593. XCTAssertTrue(Thread.isMainThread)
  1594. guard let user = authResult?.user else {
  1595. XCTFail("authResult.user is missing")
  1596. return
  1597. }
  1598. XCTAssertEqual(user.refreshToken, kRefreshToken)
  1599. XCTAssertFalse(user.isAnonymous)
  1600. XCTAssertEqual(user.email, self.kEmail)
  1601. guard let additionalUserInfo = authResult?.additionalUserInfo else {
  1602. XCTFail("authResult.additionalUserInfo is missing")
  1603. return
  1604. }
  1605. XCTAssertFalse(additionalUserInfo.isNewUser)
  1606. XCTAssertEqual(additionalUserInfo.providerID, EmailAuthProvider.id)
  1607. XCTAssertNil(error)
  1608. // Clear the password Requester to avoid being called again by reauthenticate tests.
  1609. self.rpcIssuer?.verifyPasswordRequester = nil
  1610. completion(user)
  1611. }
  1612. }
  1613. private func signInWithEmailPasswordReturnFakeUserAsync(fakeAccessToken: String = RPCBaseTests
  1614. .kFakeAccessToken) async throws -> User {
  1615. let kRefreshToken = "fakeRefreshToken"
  1616. setFakeSecureTokenService(fakeAccessToken: fakeAccessToken)
  1617. rpcIssuer?.verifyPasswordRequester = { request in
  1618. // 2. Validate the created Request instance.
  1619. XCTAssertEqual(request.email, self.kEmail)
  1620. XCTAssertEqual(request.password, self.kFakePassword)
  1621. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1622. XCTAssertTrue(request.returnSecureToken)
  1623. do {
  1624. // 3. Send the response from the fake backend.
  1625. try self.rpcIssuer?.respond(withJSON: ["idToken": fakeAccessToken,
  1626. "isNewUser": true,
  1627. "refreshToken": kRefreshToken])
  1628. } catch {
  1629. XCTFail("Failure sending response: \(error)")
  1630. }
  1631. }
  1632. try await UserTests.auth?.signOut()
  1633. let authResult = try await UserTests.auth?.signIn(withEmail: kEmail, password: kFakePassword)
  1634. let user = try XCTUnwrap(authResult?.user)
  1635. XCTAssertEqual(user.refreshToken, kRefreshToken)
  1636. XCTAssertFalse(user.isAnonymous)
  1637. XCTAssertEqual(user.email, kEmail)
  1638. let additionalUserInfo = try XCTUnwrap(authResult?.additionalUserInfo)
  1639. XCTAssertFalse(additionalUserInfo.isNewUser)
  1640. XCTAssertEqual(additionalUserInfo.providerID, EmailAuthProvider.id)
  1641. // Clear the password Requester to avoid being called again by reauthenticate tests.
  1642. rpcIssuer?.verifyPasswordRequester = nil
  1643. return user
  1644. }
  1645. private func signInWithGoogleCredential(completion: @escaping (User) -> Void) {
  1646. setFakeSecureTokenService(fakeAccessToken: RPCBaseTests.kFakeAccessToken)
  1647. setFakeGoogleGetAccountProvider()
  1648. rpcIssuer.respondBlock = {
  1649. try self.verifyGoogleAssertionRequest(
  1650. XCTUnwrap(self.rpcIssuer?.request as? VerifyAssertionRequest)
  1651. )
  1652. // 3. Send the response from the fake backend.
  1653. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1654. "providerId": GoogleAuthProvider.id,
  1655. "refreshToken": self.kRefreshToken,
  1656. "localId": self.kLocalID,
  1657. "displayName": self.kDisplayName,
  1658. "rawUserInfo": self.kGoogleProfile,
  1659. "username": self.kUserName])
  1660. }
  1661. do {
  1662. try UserTests.auth?.signOut()
  1663. let googleCredential = GoogleAuthProvider.credential(withIDToken: kGoogleIDToken,
  1664. accessToken: kGoogleAccessToken)
  1665. UserTests.auth?.signIn(with: googleCredential) { authResult, error in
  1666. // 4. After the response triggers the callback, verify the returned result.
  1667. XCTAssertTrue(Thread.isMainThread)
  1668. guard let user = authResult?.user else {
  1669. XCTFail("authResult.user is missing")
  1670. return
  1671. }
  1672. XCTAssertEqual(user.refreshToken, self.kRefreshToken)
  1673. XCTAssertFalse(user.isAnonymous)
  1674. XCTAssertEqual(user.email, self.kGoogleEmail)
  1675. guard let additionalUserInfo = authResult?.additionalUserInfo,
  1676. let profile = additionalUserInfo.profile as? [String: String] else {
  1677. XCTFail("authResult.additionalUserInfo and/or profile is missing")
  1678. return
  1679. }
  1680. XCTAssertEqual(profile, self.kGoogleProfile)
  1681. XCTAssertFalse(additionalUserInfo.isNewUser)
  1682. XCTAssertEqual(additionalUserInfo.providerID, GoogleAuthProvider.id)
  1683. XCTAssertEqual(additionalUserInfo.username, self.kUserName)
  1684. XCTAssertNil(error)
  1685. completion(user)
  1686. }
  1687. } catch {
  1688. XCTFail("Throw in \(#function): \(error)")
  1689. }
  1690. }
  1691. private func verifyGoogleAssertionRequest(_ request: VerifyAssertionRequest) {
  1692. XCTAssertEqual(request.providerID, GoogleAuthProvider.id)
  1693. XCTAssertEqual(request.providerIDToken, kGoogleIDToken)
  1694. XCTAssertEqual(request.providerAccessToken, kGoogleAccessToken)
  1695. XCTAssertTrue(request.returnSecureToken)
  1696. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1697. XCTAssertTrue(request.returnSecureToken)
  1698. }
  1699. private func signInWithFacebookCredential(completion: @escaping (User) -> Void) {
  1700. setFakeSecureTokenService(fakeAccessToken: RPCBaseTests.kFakeAccessToken)
  1701. setFakeGetAccountProvider(withNewDisplayName: kFacebookDisplayName,
  1702. withProviderID: FacebookAuthProvider.id,
  1703. withFederatedID: kFacebookID,
  1704. withEmail: kFacebookEmail)
  1705. rpcIssuer.respondBlock = {
  1706. let request = try XCTUnwrap(self.rpcIssuer?.request as? VerifyAssertionRequest)
  1707. XCTAssertEqual(request.providerID, FacebookAuthProvider.id)
  1708. XCTAssertEqual(request.providerIDToken, self.kFacebookIDToken)
  1709. XCTAssertEqual(request.providerAccessToken, self.kFacebookAccessToken)
  1710. XCTAssertTrue(request.returnSecureToken)
  1711. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1712. XCTAssertTrue(request.returnSecureToken)
  1713. // 3. Send the response from the fake backend.
  1714. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1715. "refreshToken": self.kRefreshToken,
  1716. "federatedId": self.kFacebookID,
  1717. "providerId": FacebookAuthProvider.id,
  1718. "localId": self.kLocalID,
  1719. "displayName": self.kDisplayName,
  1720. "rawUserInfo": self.kGoogleProfile,
  1721. "username": self.kUserName])
  1722. }
  1723. do {
  1724. try UserTests.auth?.signOut()
  1725. let facebookCredential = FacebookAuthProvider
  1726. .credential(withAccessToken: kFacebookAccessToken)
  1727. UserTests.auth?.signIn(with: facebookCredential) { authResult, error in
  1728. // 4. After the response triggers the callback, verify the returned result.
  1729. XCTAssertTrue(Thread.isMainThread)
  1730. guard let user = authResult?.user else {
  1731. XCTFail("authResult.user is missing")
  1732. return
  1733. }
  1734. XCTAssertEqual(user.refreshToken, self.kRefreshToken)
  1735. XCTAssertFalse(user.isAnonymous)
  1736. XCTAssertEqual(user.email, self.kFacebookEmail)
  1737. XCTAssertEqual(user.displayName, self.kFacebookDisplayName)
  1738. XCTAssertEqual(user.providerData.count, 1)
  1739. guard let additionalUserInfo = authResult?.additionalUserInfo,
  1740. let facebookUserInfo = user.providerData.first,
  1741. let profile = additionalUserInfo.profile as? [String: String] else {
  1742. XCTFail("authResult.additionalUserInfo and/or profile is missing")
  1743. return
  1744. }
  1745. XCTAssertEqual(facebookUserInfo.providerID, FacebookAuthProvider.id)
  1746. XCTAssertEqual(facebookUserInfo.uid, self.kFacebookID)
  1747. XCTAssertEqual(facebookUserInfo.displayName, self.kFacebookDisplayName)
  1748. XCTAssertEqual(facebookUserInfo.email, self.kFacebookEmail)
  1749. XCTAssertEqual(profile, self.kGoogleProfile)
  1750. XCTAssertFalse(additionalUserInfo.isNewUser)
  1751. XCTAssertEqual(additionalUserInfo.providerID, FacebookAuthProvider.id)
  1752. XCTAssertEqual(additionalUserInfo.username, self.kUserName)
  1753. XCTAssertNil(error)
  1754. completion(user)
  1755. }
  1756. } catch {
  1757. XCTFail("Throw in \(#function): \(error)")
  1758. }
  1759. }
  1760. private func signInWithEmailPasswordReturnFakeUserLink(completion: @escaping (User) -> Void) {
  1761. let kRefreshToken = "fakeRefreshToken"
  1762. setFakeSecureTokenService()
  1763. rpcIssuer.respondBlock = {
  1764. let request = try XCTUnwrap(self.rpcIssuer?.request as? EmailLinkSignInRequest)
  1765. XCTAssertEqual(request.email, self.kEmail)
  1766. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1767. XCTAssertEqual(request.oobCode, "aCode")
  1768. XCTAssertNil(request.idToken)
  1769. // Send the response from the fake backend.
  1770. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1771. "isNewUser": true,
  1772. "refreshToken": kRefreshToken])
  1773. }
  1774. do {
  1775. try UserTests.auth?.signOut()
  1776. UserTests.auth?.signIn(
  1777. withEmail: kEmail,
  1778. link: "https://www.google.com?oobCode=aCode&mode=signIn"
  1779. ) { authResult, error in
  1780. // 4. After the response triggers the callback, verify the returned result.
  1781. XCTAssertTrue(Thread.isMainThread)
  1782. guard let user = authResult?.user else {
  1783. XCTFail("authResult.user is missing")
  1784. return
  1785. }
  1786. XCTAssertEqual(user.refreshToken, kRefreshToken)
  1787. XCTAssertFalse(user.isAnonymous)
  1788. XCTAssertEqual(user.email, self.kEmail)
  1789. guard let additionalUserInfo = authResult?.additionalUserInfo else {
  1790. XCTFail("authResult.additionalUserInfo is missing")
  1791. return
  1792. }
  1793. XCTAssertTrue(additionalUserInfo.isNewUser)
  1794. XCTAssertEqual(additionalUserInfo.providerID, EmailAuthProvider.id)
  1795. XCTAssertNil(error)
  1796. completion(user)
  1797. }
  1798. } catch {
  1799. XCTFail("Throw in \(#function): \(error)")
  1800. }
  1801. }
  1802. }