UserTests.swift 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855
  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 testGetIDTokenResultForcingRefreshSuccess
  670. @brief Tests the flow successful @c getIDTokenResultForcingRefresh:completion: calls.
  671. */
  672. func testGetIDTokenResultForcingRefreshSuccess() {
  673. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength415)
  674. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength416)
  675. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenLength523,
  676. emailMatch: "aunitestuser4@gmail.com")
  677. }
  678. /** @fn testGetIDTokenResultSuccessWithBase64EncodedURL
  679. @brief Tests the flow of a successful @c getIDTokenResultWithCompletion: call using a base64 url
  680. encoded string.
  681. */
  682. func testGetIDTokenResultSuccessWithBase64EncodedURL() {
  683. internalGetIDTokenResult(token: RPCBaseTests.kFakeAccessTokenWithBase64,
  684. emailMatch: ">>>>>>>>????????@gmail.com",
  685. audMatch: "??????????>>>>>>>>>>")
  686. }
  687. /** @fn testGetIDTokenResultForcingRefreshFailure
  688. @brief Tests the flow of a failed @c getIDTokenResultForcingRefresh:completion: call.
  689. */
  690. func testGetIDTokenResultForcingRefreshFailure() {
  691. setFakeGetAccountProvider()
  692. let expectation = self.expectation(description: #function)
  693. signInWithEmailPasswordReturnFakeUser(fakeAccessToken: RPCBaseTests.kFakeAccessToken) { user in
  694. let underlying = NSError(domain: "Test Error", code: 1)
  695. self.rpcIssuer?.secureTokenNetworkError =
  696. AuthErrorUtils.networkError(underlyingError: underlying) as NSError
  697. user.getIDTokenResult(forcingRefresh: true) { tokenResult, rawError in
  698. do {
  699. XCTAssertTrue(Thread.isMainThread)
  700. XCTAssertNil(tokenResult)
  701. let error = try XCTUnwrap(rawError)
  702. XCTAssertEqual((error as NSError).code, AuthErrorCode.networkError.rawValue)
  703. } catch {
  704. XCTFail("Caught an error in \(#function): \(error)")
  705. }
  706. expectation.fulfill()
  707. }
  708. }
  709. waitForExpectations(timeout: 5)
  710. }
  711. /** @fn testReloadSuccess
  712. @brief Tests the flow of a successful @c reloadWithCompletion: call.
  713. */
  714. func testReloadSuccess() {
  715. setFakeGetAccountProvider()
  716. let expectation = self.expectation(description: #function)
  717. signInWithEmailPasswordReturnFakeUser { user in
  718. user.reload { error in
  719. XCTAssertTrue(Thread.isMainThread)
  720. XCTAssertNil(error)
  721. XCTAssertEqual(user.displayName, self.kDisplayName)
  722. XCTAssertEqual(user.email, self.kEmail)
  723. expectation.fulfill()
  724. }
  725. }
  726. waitForExpectations(timeout: 5)
  727. }
  728. /** @fn testReloadFailure
  729. @brief Tests the flow of a failed @c reloadWithCompletion: call.
  730. */
  731. func testReloadFailure() {
  732. setFakeGetAccountProvider()
  733. let expectation = self.expectation(description: #function)
  734. signInWithEmailPasswordReturnFakeUser { user in
  735. do {
  736. self.rpcIssuer.respondBlock = {
  737. try self.rpcIssuer?.respond(serverErrorMessage: "QUOTA_EXCEEDED")
  738. }
  739. // Clear fake so we can inject error
  740. self.rpcIssuer?.fakeGetAccountProviderJSON = nil
  741. user.reload { rawError in
  742. XCTAssertTrue(Thread.isMainThread)
  743. let error = try! XCTUnwrap(rawError)
  744. XCTAssertEqual((error as NSError).code, AuthErrorCode.quotaExceeded.rawValue)
  745. // User is still signed in.
  746. XCTAssertEqual(UserTests.auth?.currentUser, user)
  747. expectation.fulfill()
  748. }
  749. }
  750. }
  751. waitForExpectations(timeout: 5)
  752. }
  753. /** @fn testReloadFailureAutoSignOut
  754. @brief Tests the flow of a failed @c reloadWithCompletion: call that automtatically signs out.
  755. */
  756. func testReloadFailureAutoSignOut() {
  757. setFakeGetAccountProvider()
  758. let expectation = self.expectation(description: #function)
  759. signInWithEmailPasswordReturnFakeUser { user in
  760. do {
  761. self.rpcIssuer.respondBlock = {
  762. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  763. }
  764. // Clear fake so we can inject error
  765. self.rpcIssuer?.fakeGetAccountProviderJSON = nil
  766. user.reload { rawError in
  767. XCTAssertTrue(Thread.isMainThread)
  768. let error = try! XCTUnwrap(rawError)
  769. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  770. // User is no longer signed in.
  771. XCTAssertNil(UserTests.auth?.currentUser)
  772. expectation.fulfill()
  773. }
  774. }
  775. }
  776. waitForExpectations(timeout: 5)
  777. }
  778. /** @fn testReauthenticateSuccess
  779. @brief Tests the flow of a successful @c reauthenticateWithCredential:completion: call.
  780. */
  781. func testReauthenticateSuccess() {
  782. setFakeGetAccountProvider()
  783. let expectation = self.expectation(description: #function)
  784. signInWithEmailPasswordReturnFakeUser { user in
  785. do {
  786. self.rpcIssuer.respondBlock = {
  787. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  788. "refreshToken": self.kRefreshToken])
  789. }
  790. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  791. password: self.kFakePassword)
  792. user.reauthenticate(with: emailCredential) { rawResult, error in
  793. XCTAssertTrue(Thread.isMainThread)
  794. XCTAssertNil(error)
  795. let result = try! XCTUnwrap(rawResult)
  796. XCTAssertEqual(result.user.uid, user.uid)
  797. XCTAssertEqual(result.user.email, user.email)
  798. XCTAssertEqual(result.additionalUserInfo?.isNewUser, false)
  799. // User is still signed in.
  800. XCTAssertEqual(UserTests.auth?.currentUser, user)
  801. expectation.fulfill()
  802. }
  803. }
  804. }
  805. waitForExpectations(timeout: 5)
  806. }
  807. /** @fn testReauthenticateWithCredentialSuccess
  808. @brief Tests the flow of a successful @c reauthenticateWithCredential call.
  809. */
  810. func testReauthenticateWithCredentialSuccess() throws {
  811. let expectation = self.expectation(description: #function)
  812. signInWithGoogleCredential { user in
  813. do {
  814. self.rpcIssuer.respondBlock = {
  815. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  816. "refreshToken": self.kRefreshToken,
  817. "federatedId": self.kGoogleID,
  818. "providerId": GoogleAuthProvider.id,
  819. "localId": self.kLocalID,
  820. "displayName": self.kGoogleDisplayName,
  821. "rawUserInfo": self.kGoogleProfile,
  822. "username": self.kUserName])
  823. }
  824. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  825. accessToken: self.kGoogleAccessToken)
  826. user.reauthenticate(with: googleCredential) { reauthenticatedAuthResult, error in
  827. XCTAssertTrue(Thread.isMainThread)
  828. do {
  829. try self.assertUserGoogle(reauthenticatedAuthResult?.user)
  830. } catch {
  831. XCTFail("\(error)")
  832. }
  833. XCTAssertNil(error)
  834. // Verify that the current user is unchanged.
  835. XCTAssertEqual(UserTests.auth?.currentUser, user)
  836. // Verify that the current user and reauthenticated user are not same pointers.
  837. XCTAssertNotEqual(user, reauthenticatedAuthResult?.user)
  838. // Verify that anyway the current user and reauthenticated user have same IDs.
  839. XCTAssertEqual(reauthenticatedAuthResult?.user.uid, user.uid)
  840. XCTAssertEqual(reauthenticatedAuthResult?.user.email, user.email)
  841. XCTAssertEqual(reauthenticatedAuthResult?.user.displayName, user.displayName)
  842. XCTAssertEqual(reauthenticatedAuthResult?.additionalUserInfo?.username, self.kUserName)
  843. XCTAssertEqual(reauthenticatedAuthResult?.additionalUserInfo?.providerID,
  844. GoogleAuthProvider.id)
  845. XCTAssertEqual(
  846. reauthenticatedAuthResult?.additionalUserInfo?.profile as? [String: String],
  847. self.kGoogleProfile
  848. )
  849. expectation.fulfill()
  850. }
  851. }
  852. }
  853. waitForExpectations(timeout: 5)
  854. try assertUserGoogle(UserTests.auth?.currentUser)
  855. }
  856. /** @fn testReauthenticateFailure
  857. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call.
  858. */
  859. func testReauthenticateFailure() {
  860. setFakeGetAccountProvider()
  861. let expectation = self.expectation(description: #function)
  862. signInWithEmailPasswordReturnFakeUser { user in
  863. do {
  864. self.rpcIssuer.respondBlock = {
  865. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  866. "refreshToken": self.kRefreshToken])
  867. }
  868. self.setFakeGetAccountProvider(withLocalID: "A different Local ID")
  869. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  870. password: self.kFakePassword)
  871. user.reauthenticate(with: emailCredential) { reauthenticatedAuthResult, rawError in
  872. XCTAssertTrue(Thread.isMainThread)
  873. let error = try! XCTUnwrap(rawError)
  874. XCTAssertEqual((error as NSError).code, AuthErrorCode.userMismatch.rawValue)
  875. // Email should not have changed on the client side.
  876. XCTAssertEqual(user.email, self.kEmail)
  877. // User is still signed in.
  878. XCTAssertEqual(UserTests.auth?.currentUser, user)
  879. expectation.fulfill()
  880. }
  881. }
  882. }
  883. waitForExpectations(timeout: 5)
  884. }
  885. /** @fn testReauthenticateUserMismatchFailure
  886. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call due to trying
  887. to reauthenticate a user that does not exist.
  888. */
  889. func testReauthenticateUserMismatchFailure() {
  890. setFakeGetAccountProvider()
  891. let expectation = self.expectation(description: #function)
  892. signInWithEmailPasswordReturnFakeUser { user in
  893. do {
  894. self.rpcIssuer.respondBlock = {
  895. try self.rpcIssuer?.respond(serverErrorMessage: "USER_NOT_FOUND")
  896. }
  897. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  898. accessToken: self.kGoogleAccessToken)
  899. user.reauthenticate(with: googleCredential) { reauthenticatedAuthResult, rawError in
  900. XCTAssertTrue(Thread.isMainThread)
  901. let error = try! XCTUnwrap(rawError)
  902. XCTAssertEqual((error as NSError).code, AuthErrorCode.userMismatch.rawValue)
  903. // Email should not have changed on the client side.
  904. XCTAssertEqual(user.email, self.kEmail)
  905. // User is still signed in.
  906. XCTAssertEqual(UserTests.auth?.currentUser, user)
  907. expectation.fulfill()
  908. }
  909. }
  910. }
  911. waitForExpectations(timeout: 5)
  912. }
  913. /** @fn testLinkAndRetrieveDataSuccess (and old testLinkCredentialSuccess)
  914. @brief Tests the flow of a successful @c linkWithCredential call.
  915. */
  916. func testLinkAndRetrieveDataSuccess() throws {
  917. setFakeGetAccountProvider()
  918. let expectation = self.expectation(description: #function)
  919. let auth = try XCTUnwrap(UserTests.auth)
  920. signInWithFacebookCredential { user in
  921. XCTAssertNotNil(user)
  922. do {
  923. self.setFakeGoogleGetAccountProvider()
  924. self.rpcIssuer.respondBlock = {
  925. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  926. "refreshToken": self.kRefreshToken,
  927. "federatedId": self.kGoogleID,
  928. "providerId": GoogleAuthProvider.id,
  929. "localId": self.kLocalID,
  930. "displayName": self.kGoogleDisplayName,
  931. "rawUserInfo": self.kGoogleProfile,
  932. "username": self.kUserName])
  933. }
  934. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  935. accessToken: self.kGoogleAccessToken)
  936. user.link(with: googleCredential) { linkAuthResult, error in
  937. XCTAssertTrue(Thread.isMainThread)
  938. XCTAssertNil(error)
  939. // Verify that the current user is unchanged.
  940. XCTAssertEqual(auth.currentUser, user)
  941. // Verify that the current user and reauthenticated user are the same pointers.
  942. XCTAssertEqual(user, linkAuthResult?.user)
  943. // Verify that anyway the current user and reauthenticated user have same IDs.
  944. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  945. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  946. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  947. XCTAssertEqual(linkAuthResult?.additionalUserInfo?.username, self.kUserName)
  948. XCTAssertEqual(linkAuthResult?.additionalUserInfo?.providerID,
  949. GoogleAuthProvider.id)
  950. XCTAssertEqual(
  951. linkAuthResult?.additionalUserInfo?.profile as? [String: String],
  952. self.kGoogleProfile
  953. )
  954. XCTAssertEqual(linkAuthResult?.user.providerData.first?.providerID, GoogleAuthProvider.id)
  955. expectation.fulfill()
  956. }
  957. }
  958. }
  959. waitForExpectations(timeout: 5)
  960. try assertUserGoogle(auth.currentUser)
  961. }
  962. /** @fn testLinkAndRetrieveDataError
  963. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  964. call with an error from the backend.
  965. */
  966. func testLinkAndRetrieveDataError() throws {
  967. setFakeGetAccountProvider()
  968. let expectation = self.expectation(description: #function)
  969. signInWithFacebookCredential { user in
  970. XCTAssertNotNil(user)
  971. do {
  972. self.setFakeGetAccountProvider()
  973. self.rpcIssuer.respondBlock = {
  974. try self.rpcIssuer?.respond(serverErrorMessage: "CREDENTIAL_TOO_OLD_LOGIN_AGAIN")
  975. }
  976. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  977. accessToken: self.kGoogleAccessToken)
  978. user.link(with: googleCredential) { linkAuthResult, rawError in
  979. XCTAssertTrue(Thread.isMainThread)
  980. XCTAssertNil(linkAuthResult)
  981. let error = try! XCTUnwrap(rawError)
  982. XCTAssertEqual((error as NSError).code, AuthErrorCode.requiresRecentLogin.rawValue)
  983. // Email should not have changed on the client side.
  984. XCTAssertEqual(user.email, self.kFacebookEmail)
  985. // User is still signed in.
  986. XCTAssertEqual(UserTests.auth?.currentUser, user)
  987. expectation.fulfill()
  988. }
  989. }
  990. }
  991. waitForExpectations(timeout: 5)
  992. }
  993. /** @fn testLinkAndRetrieveDataProviderAlreadyLinked and old testLinkCredentialProviderAlreadyLinkedError
  994. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  995. call with FIRAuthErrorCodeProviderAlreadyLinked, which is a client side error.
  996. */
  997. func testLinkAndRetrieveDataProviderAlreadyLinked() throws {
  998. setFakeGetAccountProvider()
  999. let expectation = self.expectation(description: #function)
  1000. signInWithFacebookCredential { user in
  1001. XCTAssertNotNil(user)
  1002. do {
  1003. self.setFakeGetAccountProvider()
  1004. let facebookCredential =
  1005. FacebookAuthProvider.credential(withAccessToken: self.kFacebookAccessToken)
  1006. user.link(with: facebookCredential) { linkAuthResult, rawError in
  1007. XCTAssertTrue(Thread.isMainThread)
  1008. XCTAssertNil(linkAuthResult)
  1009. do {
  1010. let error = try XCTUnwrap(rawError)
  1011. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1012. } catch {
  1013. XCTFail("Expected to throw providerAlreadyLinked error.")
  1014. }
  1015. // User is still signed in.
  1016. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1017. expectation.fulfill()
  1018. }
  1019. }
  1020. }
  1021. waitForExpectations(timeout: 5)
  1022. }
  1023. /** @fn testLinkAndRetrieveDataErrorAutoSignOut (and old testLinkCredentialError)
  1024. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1025. call that automatically signs out.
  1026. */
  1027. func testLinkAndRetrieveDataErrorAutoSignOut() throws {
  1028. setFakeGetAccountProvider()
  1029. let expectation = self.expectation(description: #function)
  1030. signInWithFacebookCredential { user in
  1031. XCTAssertNotNil(user)
  1032. do {
  1033. self.setFakeGetAccountProvider()
  1034. self.rpcIssuer.respondBlock = {
  1035. try self.rpcIssuer?.respond(serverErrorMessage: "USER_DISABLED")
  1036. }
  1037. let googleCredential = GoogleAuthProvider.credential(withIDToken: self.kGoogleIDToken,
  1038. accessToken: self.kGoogleAccessToken)
  1039. user.link(with: googleCredential) { linkAuthResult, rawError in
  1040. XCTAssertTrue(Thread.isMainThread)
  1041. XCTAssertNil(linkAuthResult)
  1042. let error = try! XCTUnwrap(rawError)
  1043. XCTAssertEqual((error as NSError).code, AuthErrorCode.userDisabled.rawValue)
  1044. // User is signed out.
  1045. XCTAssertNil(UserTests.auth?.currentUser)
  1046. expectation.fulfill()
  1047. }
  1048. }
  1049. }
  1050. waitForExpectations(timeout: 5)
  1051. }
  1052. /** @fn testLinkEmailAndRetrieveDataSuccess
  1053. @brief Tests the flow of a successful @c linkWithCredential:completion:
  1054. invocation for email credential.
  1055. */
  1056. func testLinkEmailAndRetrieveDataSuccess() throws {
  1057. setFakeGetAccountProvider()
  1058. let expectation = self.expectation(description: #function)
  1059. let auth = try XCTUnwrap(UserTests.auth)
  1060. signInWithFacebookCredential { user in
  1061. XCTAssertNotNil(user)
  1062. do {
  1063. self.rpcIssuer.respondBlock = {
  1064. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1065. XCTAssertNotNil(request)
  1066. XCTAssertEqual(request?.email, self.kEmail)
  1067. XCTAssertEqual(request?.password, self.kFakePassword)
  1068. XCTAssertNil(request?.displayName)
  1069. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1070. "refreshToken": self.kRefreshToken])
  1071. self.setFakeGetAccountProvider(withProviderID: EmailAuthProvider.id)
  1072. }
  1073. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1074. password: self.kFakePassword)
  1075. user.link(with: emailCredential) { linkAuthResult, error in
  1076. XCTAssertTrue(Thread.isMainThread)
  1077. XCTAssertNil(error)
  1078. // Verify that the current user is unchanged.
  1079. XCTAssertEqual(auth.currentUser, user)
  1080. // Verify that the current user and reauthenticated user are the same pointers.
  1081. XCTAssertEqual(user, linkAuthResult?.user)
  1082. // Verify that anyway the current user and reauthenticated user have same IDs.
  1083. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1084. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1085. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1086. expectation.fulfill()
  1087. }
  1088. }
  1089. }
  1090. waitForExpectations(timeout: 5)
  1091. }
  1092. /** @fn tesLlinkEmailProviderAlreadyLinkedError
  1093. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1094. invocation for email credential and FIRAuthErrorCodeProviderAlreadyLinked which is a client
  1095. side error.
  1096. */
  1097. func testLinkEmailProviderAlreadyLinkedError() throws {
  1098. setFakeGetAccountProvider()
  1099. let expectation = self.expectation(description: #function)
  1100. signInWithFacebookCredential { user in
  1101. XCTAssertNotNil(user)
  1102. do {
  1103. self.rpcIssuer.respondBlock = {
  1104. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1105. XCTAssertNotNil(request)
  1106. XCTAssertEqual(request?.email, self.kEmail)
  1107. XCTAssertEqual(request?.password, self.kFakePassword)
  1108. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1109. "refreshToken": self.kRefreshToken])
  1110. self.setFakeGetAccountProvider(withProviderID: EmailAuthProvider.id)
  1111. }
  1112. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1113. password: self.kFakePassword)
  1114. user.link(with: emailCredential) { linkAuthResult, error in
  1115. XCTAssertEqual(user, linkAuthResult?.user)
  1116. linkAuthResult?.user.link(with: emailCredential) { linkLinkAuthResult, rawError in
  1117. XCTAssertTrue(Thread.isMainThread)
  1118. XCTAssertNil(linkLinkAuthResult)
  1119. do {
  1120. let error = try XCTUnwrap(rawError)
  1121. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1122. } catch {
  1123. XCTFail("Expected to throw providerAlreadyLinked error.")
  1124. }
  1125. // User is still signed in.
  1126. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1127. expectation.fulfill()
  1128. }
  1129. }
  1130. }
  1131. }
  1132. waitForExpectations(timeout: 5)
  1133. }
  1134. /** @fn testLinkEmailAndRetrieveDataError
  1135. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1136. invocation for email credential and an error from the backend.
  1137. */
  1138. func testLinkEmailAndRetrieveDataError() throws {
  1139. setFakeGetAccountProvider()
  1140. let expectation = self.expectation(description: #function)
  1141. signInWithFacebookCredential { user in
  1142. XCTAssertNotNil(user)
  1143. do {
  1144. self.rpcIssuer.respondBlock = {
  1145. let request = self.rpcIssuer?.request as? SignUpNewUserRequest
  1146. XCTAssertNotNil(request)
  1147. XCTAssertEqual(request?.email, self.kEmail)
  1148. XCTAssertEqual(request?.password, self.kFakePassword)
  1149. try self.rpcIssuer?.respond(serverErrorMessage: "TOO_MANY_ATTEMPTS_TRY_LATER")
  1150. }
  1151. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1152. password: self.kFakePassword)
  1153. user.link(with: emailCredential) { linkAuthResult, rawError in
  1154. XCTAssertTrue(Thread.isMainThread)
  1155. XCTAssertNil(linkAuthResult)
  1156. let error = try! XCTUnwrap(rawError)
  1157. XCTAssertEqual((error as NSError).code, AuthErrorCode.tooManyRequests.rawValue)
  1158. // User is still signed in.
  1159. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1160. expectation.fulfill()
  1161. }
  1162. }
  1163. }
  1164. waitForExpectations(timeout: 5)
  1165. }
  1166. /** @fn testLinkEmailAndRetrieveDataErrorAutoSignOut
  1167. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion:
  1168. invocation that automatically signs out.
  1169. */
  1170. func testLinkEmailAndRetrieveDataErrorAutoSignOut() throws {
  1171. setFakeGetAccountProvider()
  1172. let expectation = self.expectation(description: #function)
  1173. signInWithFacebookCredential { user in
  1174. XCTAssertNotNil(user)
  1175. do {
  1176. self.rpcIssuer.respondBlock = {
  1177. XCTAssertNotNil(self.rpcIssuer?.request as? SignUpNewUserRequest)
  1178. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1179. }
  1180. let emailCredential = EmailAuthProvider.credential(withEmail: self.kEmail,
  1181. password: self.kFakePassword)
  1182. user.link(with: emailCredential) { linkAuthResult, rawError in
  1183. XCTAssertTrue(Thread.isMainThread)
  1184. XCTAssertNil(linkAuthResult)
  1185. let error = try! XCTUnwrap(rawError)
  1186. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1187. // User is signed out.
  1188. XCTAssertNil(UserTests.auth?.currentUser)
  1189. expectation.fulfill()
  1190. }
  1191. }
  1192. }
  1193. waitForExpectations(timeout: 5)
  1194. }
  1195. #if os(iOS)
  1196. private class FakeOAuthProvider: OAuthProvider {
  1197. override func getCredentialWith(_ UIDelegate: AuthUIDelegate?,
  1198. completion: ((AuthCredential?, Error?) -> Void)? = nil) {
  1199. if let completion {
  1200. let credential = OAuthCredential(
  1201. withProviderID: GoogleAuthProvider.id,
  1202. sessionID: UserTests.kOAuthSessionID,
  1203. OAuthResponseURLString: UserTests.kOAuthRequestURI
  1204. )
  1205. completion(credential, nil)
  1206. }
  1207. }
  1208. }
  1209. /** @fn testLinkProviderFailure
  1210. @brief Tests the flow of a failed @c linkWithProvider:completion:
  1211. call.
  1212. */
  1213. func testLinkProviderFailure() throws {
  1214. setFakeGetAccountProvider()
  1215. let expectation = self.expectation(description: #function)
  1216. let auth = try XCTUnwrap(UserTests.auth)
  1217. signInWithFacebookCredential { user in
  1218. XCTAssertNotNil(user)
  1219. do {
  1220. self.setFakeGetAccountProvider()
  1221. self.rpcIssuer.respondBlock = {
  1222. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1223. }
  1224. user.link(with: FakeOAuthProvider(providerID: "foo", auth: auth),
  1225. uiDelegate: nil) { linkAuthResult, rawError in
  1226. XCTAssertTrue(Thread.isMainThread)
  1227. XCTAssertNil(linkAuthResult)
  1228. let error = try! XCTUnwrap(rawError)
  1229. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1230. // User is signed out.
  1231. XCTAssertNil(UserTests.auth?.currentUser)
  1232. expectation.fulfill()
  1233. }
  1234. }
  1235. }
  1236. waitForExpectations(timeout: 5)
  1237. }
  1238. /** @fn testReauthenticateWithProviderFailure
  1239. @brief Tests the flow of a failed @c reauthenticateWithProvider:completion: call.
  1240. */
  1241. func testReauthenticateWithProviderFailure() throws {
  1242. setFakeGetAccountProvider()
  1243. let expectation = self.expectation(description: #function)
  1244. let auth = try XCTUnwrap(UserTests.auth)
  1245. signInWithFacebookCredential { user in
  1246. XCTAssertNotNil(user)
  1247. do {
  1248. self.setFakeGetAccountProvider()
  1249. self.rpcIssuer.respondBlock = {
  1250. try self.rpcIssuer?.respond(serverErrorMessage: "TOKEN_EXPIRED")
  1251. }
  1252. user.reauthenticate(with: FakeOAuthProvider(providerID: "foo", auth: auth),
  1253. uiDelegate: nil) { linkAuthResult, rawError in
  1254. XCTAssertTrue(Thread.isMainThread)
  1255. XCTAssertNil(linkAuthResult)
  1256. let error = try! XCTUnwrap(rawError)
  1257. XCTAssertEqual((error as NSError).code, AuthErrorCode.userTokenExpired.rawValue)
  1258. // User is still signed in.
  1259. XCTAssertEqual(UserTests.auth?.currentUser, user)
  1260. expectation.fulfill()
  1261. }
  1262. }
  1263. }
  1264. waitForExpectations(timeout: 5)
  1265. }
  1266. /** @fn testLinkPhoneAuthCredentialSuccess
  1267. @brief Tests the flow of a successful @c linkWithCredential call using a phoneAuthCredential.
  1268. */
  1269. func testLinkPhoneAuthCredentialSuccess() throws {
  1270. setFakeGetAccountProvider()
  1271. let expectation = self.expectation(description: #function)
  1272. let auth = try XCTUnwrap(UserTests.auth)
  1273. signInWithEmailPasswordReturnFakeUser { user in
  1274. XCTAssertNotNil(user)
  1275. self.expectVerifyPhoneNumberRequest(isLink: true)
  1276. do {
  1277. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1278. self.rpcIssuer.respondBlock = {
  1279. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1280. "refreshToken": self.kRefreshToken])
  1281. }
  1282. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1283. withVerificationID: self.kVerificationID,
  1284. verificationCode: self.kVerificationCode
  1285. )
  1286. user.link(with: credential) { linkAuthResult, error in
  1287. XCTAssertTrue(Thread.isMainThread)
  1288. XCTAssertNil(error)
  1289. // Verify that the current user is unchanged.
  1290. XCTAssertEqual(auth.currentUser, user)
  1291. // Verify that the current user and reauthenticated user are the same pointers.
  1292. XCTAssertEqual(user, linkAuthResult?.user)
  1293. // Verify that anyway the current user and reauthenticated user have same IDs.
  1294. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1295. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1296. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1297. XCTAssertEqual(auth.currentUser?.providerData.first?.providerID, PhoneAuthProvider.id)
  1298. XCTAssertEqual(
  1299. linkAuthResult?.user.providerData.first?.providerID,
  1300. PhoneAuthProvider.id
  1301. )
  1302. XCTAssertEqual(auth.currentUser?.phoneNumber, self.kTestPhoneNumber)
  1303. expectation.fulfill()
  1304. }
  1305. }
  1306. }
  1307. waitForExpectations(timeout: 5)
  1308. }
  1309. /** @fn testUnlinkPhoneAuthCredentialSuccess
  1310. @brief Tests the flow of a successful @c unlinkFromProvider:completion: call using a
  1311. @c FIRPhoneAuthProvider.
  1312. */
  1313. func testUnlinkPhoneAuthCredentialSuccess() throws {
  1314. setFakeGetAccountProvider()
  1315. let expectation = self.expectation(description: #function)
  1316. let auth = try XCTUnwrap(UserTests.auth)
  1317. signInWithEmailPasswordReturnFakeUser { user in
  1318. XCTAssertNotNil(user)
  1319. self.expectVerifyPhoneNumberRequest(isLink: true)
  1320. do {
  1321. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1322. self.rpcIssuer.respondBlock = {
  1323. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1324. "refreshToken": self.kRefreshToken])
  1325. }
  1326. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1327. withVerificationID: self.kVerificationID,
  1328. verificationCode: self.kVerificationCode
  1329. )
  1330. user.link(with: credential) { linkAuthResult, error in
  1331. XCTAssertTrue(Thread.isMainThread)
  1332. XCTAssertNil(error)
  1333. // Verify that the current user is unchanged.
  1334. XCTAssertEqual(auth.currentUser, user)
  1335. // Verify that the current user and reauthenticated user are the same pointers.
  1336. XCTAssertEqual(user, linkAuthResult?.user)
  1337. // Verify that anyway the current user and reauthenticated user have same IDs.
  1338. XCTAssertEqual(linkAuthResult?.user.uid, user.uid)
  1339. XCTAssertEqual(linkAuthResult?.user.email, user.email)
  1340. XCTAssertEqual(linkAuthResult?.user.displayName, user.displayName)
  1341. XCTAssertEqual(auth.currentUser?.providerData.first?.providerID, PhoneAuthProvider.id)
  1342. XCTAssertEqual(
  1343. linkAuthResult?.user.providerData.first?.providerID,
  1344. PhoneAuthProvider.id
  1345. )
  1346. XCTAssertEqual(auth.currentUser?.phoneNumber, self.kTestPhoneNumber)
  1347. // Immediately unlink the phone auth provider.
  1348. self.rpcIssuer.respondBlock = {
  1349. let request = try XCTUnwrap(self.rpcIssuer?.request as? SetAccountInfoRequest)
  1350. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1351. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1352. XCTAssertNil(request.email)
  1353. XCTAssertNil(request.password)
  1354. XCTAssertNil(request.localID)
  1355. XCTAssertNil(request.displayName)
  1356. XCTAssertNil(request.photoURL)
  1357. XCTAssertNil(request.providers)
  1358. XCTAssertNil(request.deleteAttributes)
  1359. XCTAssertEqual(try XCTUnwrap(request.deleteProviders?.first), PhoneAuthProvider.id)
  1360. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1361. "refreshToken": self.kRefreshToken])
  1362. }
  1363. user.unlink(fromProvider: PhoneAuthProvider.id) { user, error in
  1364. XCTAssertNil(error)
  1365. XCTAssertEqual(auth.currentUser, user)
  1366. XCTAssertNil(auth.currentUser?.phoneNumber)
  1367. expectation.fulfill()
  1368. }
  1369. }
  1370. }
  1371. }
  1372. waitForExpectations(timeout: 5)
  1373. }
  1374. /** @fn testlinkPhoneAuthCredentialFailure
  1375. @brief Tests the flow of a failed call to @c linkWithCredential:completion: due
  1376. to a phone provider already being linked.
  1377. */
  1378. func testlinkPhoneAuthCredentialFailure() throws {
  1379. setFakeGetAccountProvider(withPasswordHash: kFakePassword)
  1380. let expectation = self.expectation(description: #function)
  1381. signInWithEmailPasswordReturnFakeUser { user in
  1382. XCTAssertNotNil(user)
  1383. self.expectVerifyPhoneNumberRequest(isLink: true)
  1384. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1385. let credential = EmailAuthCredential(withEmail: self.kEmail, password: self.kFakePassword)
  1386. user.link(with: credential) { linkAuthResult, rawError in
  1387. XCTAssertTrue(Thread.isMainThread)
  1388. XCTAssertNil(linkAuthResult)
  1389. if let error = try? XCTUnwrap(rawError) {
  1390. XCTAssertEqual((error as NSError).code, AuthErrorCode.providerAlreadyLinked.rawValue)
  1391. } else {
  1392. XCTFail("Did not throw expected error")
  1393. }
  1394. expectation.fulfill()
  1395. }
  1396. }
  1397. waitForExpectations(timeout: 5)
  1398. }
  1399. /** @fn testlinkPhoneCredentialAlreadyExistsError
  1400. @brief Tests the flow of @c linkWithCredential:completion:
  1401. call using a phoneAuthCredential and a credential already exists error. In this case we
  1402. should get a AuthCredential in the error object.
  1403. */
  1404. func testlinkPhoneCredentialAlreadyExistsError() throws {
  1405. setFakeGetAccountProvider()
  1406. let expectation = self.expectation(description: #function)
  1407. let auth = try XCTUnwrap(UserTests.auth)
  1408. signInWithEmailPasswordReturnFakeUser { user in
  1409. XCTAssertNotNil(user)
  1410. self.expectVerifyPhoneNumberRequest(isLink: true)
  1411. do {
  1412. self.setFakeGetAccountProvider(withProviderID: PhoneAuthProvider.id)
  1413. self.rpcIssuer.respondBlock = {
  1414. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1415. "refreshToken": self.kRefreshToken,
  1416. "phoneNumber": self.kTestPhoneNumber,
  1417. "temporaryProof": "Fake Temporary Proof"])
  1418. }
  1419. let credential = PhoneAuthProvider.provider(auth: auth).credential(
  1420. withVerificationID: self.kVerificationID,
  1421. verificationCode: self.kVerificationCode
  1422. )
  1423. user.link(with: credential) { linkAuthResult, rawError in
  1424. XCTAssertTrue(Thread.isMainThread)
  1425. XCTAssertNil(linkAuthResult)
  1426. do {
  1427. let error = try XCTUnwrap(rawError)
  1428. XCTAssertEqual((error as NSError).code, AuthErrorCode.credentialAlreadyInUse.rawValue)
  1429. let credential = try XCTUnwrap((error as NSError)
  1430. .userInfo[AuthErrors.userInfoUpdatedCredentialKey] as? PhoneAuthCredential)
  1431. switch credential.credentialKind {
  1432. case let .phoneNumber(phoneNumber, temporaryProof):
  1433. XCTAssertEqual(temporaryProof, "Fake Temporary Proof")
  1434. XCTAssertEqual(phoneNumber, self.kTestPhoneNumber)
  1435. case .verification: XCTFail("Should be phoneNumber case")
  1436. }
  1437. } catch {
  1438. XCTFail("Did not throw expected error \(error)")
  1439. }
  1440. expectation.fulfill()
  1441. }
  1442. }
  1443. }
  1444. waitForExpectations(timeout: 5)
  1445. }
  1446. #endif
  1447. // MARK: Private helper functions
  1448. private func expectVerifyPhoneNumberRequest(isLink: Bool = false) {
  1449. rpcIssuer?.verifyPhoneNumberRequester = { request in
  1450. XCTAssertEqual(request.verificationID, self.kVerificationID)
  1451. XCTAssertEqual(request.verificationCode, self.kVerificationCode)
  1452. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1453. if isLink {
  1454. XCTAssertEqual(request.operation, AuthOperationType.link)
  1455. } else {
  1456. XCTAssertEqual(request.operation, AuthOperationType.update)
  1457. }
  1458. }
  1459. }
  1460. private func internalGetIDTokenResult(token: String, forceRefresh: Bool = true,
  1461. emailMatch: String = "aunitestuser@gmail.com",
  1462. audMatch: String = "test_aud") {
  1463. setFakeGetAccountProvider()
  1464. let expectation = self.expectation(description: #function)
  1465. signInWithEmailPasswordReturnFakeUser(fakeAccessToken: token) { user in
  1466. user.getIDTokenResult(forcingRefresh: forceRefresh) { rawTokenResult, error in
  1467. XCTAssertTrue(Thread.isMainThread)
  1468. XCTAssertNil(error)
  1469. XCTAssertEqual(user.displayName, self.kDisplayName)
  1470. XCTAssertEqual(user.email, self.kEmail)
  1471. let tokenResult = try! XCTUnwrap(rawTokenResult)
  1472. XCTAssertEqual(tokenResult.token, token)
  1473. XCTAssertNotNil(tokenResult.issuedAtDate)
  1474. XCTAssertNotNil(tokenResult.authDate)
  1475. XCTAssertNotNil(tokenResult.expirationDate)
  1476. XCTAssertNotNil(tokenResult.signInProvider)
  1477. // The lowercased is for the base64 test which seems to be an erroneously uppercased
  1478. // "Password"?
  1479. XCTAssertEqual(tokenResult.signInProvider.lowercased(), EmailAuthProvider.id)
  1480. XCTAssertEqual(tokenResult.claims["email"] as! String, emailMatch)
  1481. XCTAssertEqual(tokenResult.claims["aud"] as! String, audMatch)
  1482. XCTAssertEqual(tokenResult.signInSecondFactor, "")
  1483. expectation.fulfill()
  1484. }
  1485. }
  1486. waitForExpectations(timeout: 5)
  1487. }
  1488. private func changeUserEmail(user: User, changeEmail: Bool = false,
  1489. expectation: XCTestExpectation) {
  1490. do {
  1491. XCTAssertEqual(user.providerID, "Firebase")
  1492. XCTAssertEqual(user.uid, kLocalID)
  1493. XCTAssertEqual(user.displayName, kDisplayName)
  1494. XCTAssertEqual(user.photoURL, URL(string: kTestPhotoURL))
  1495. XCTAssertEqual(user.email, kEmail)
  1496. // Pretend that the display name on the server has been changed since the original signin.
  1497. setFakeGetAccountProvider(withNewDisplayName: kNewDisplayName)
  1498. rpcIssuer.respondBlock = {
  1499. let request = try XCTUnwrap(self.rpcIssuer?.request as? SetAccountInfoRequest)
  1500. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1501. XCTAssertEqual(request.accessToken, RPCBaseTests.kFakeAccessToken)
  1502. if changeEmail {
  1503. XCTAssertEqual(request.email, self.kNewEmail)
  1504. XCTAssertNil(request.password)
  1505. } else {
  1506. XCTAssertEqual(request.password, self.kNewPassword)
  1507. XCTAssertNil(request.email)
  1508. }
  1509. XCTAssertNil(request.localID)
  1510. XCTAssertNil(request.displayName)
  1511. XCTAssertNil(request.photoURL)
  1512. XCTAssertNil(request.providers)
  1513. XCTAssertNil(request.deleteAttributes)
  1514. XCTAssertNil(request.deleteProviders)
  1515. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1516. "email": self.kNewEmail,
  1517. "refreshToken": self.kRefreshToken])
  1518. }
  1519. if changeEmail {
  1520. user.updateEmail(to: kNewEmail) { error in
  1521. XCTAssertNil(error)
  1522. XCTAssertEqual(user.email, self.kNewEmail)
  1523. XCTAssertEqual(user.displayName, self.kNewDisplayName)
  1524. XCTAssertFalse(user.isAnonymous)
  1525. expectation.fulfill()
  1526. }
  1527. } else {
  1528. user.updatePassword(to: kNewPassword) { error in
  1529. XCTAssertNil(error)
  1530. XCTAssertEqual(user.displayName, self.kNewDisplayName)
  1531. XCTAssertFalse(user.isAnonymous)
  1532. expectation.fulfill()
  1533. }
  1534. }
  1535. }
  1536. }
  1537. private func signInWithEmailPasswordReturnFakeUser(fakeAccessToken: String = RPCBaseTests
  1538. .kFakeAccessToken,
  1539. completion: @escaping (User) -> Void) {
  1540. let kRefreshToken = "fakeRefreshToken"
  1541. setFakeSecureTokenService(fakeAccessToken: fakeAccessToken)
  1542. rpcIssuer?.verifyPasswordRequester = { request in
  1543. // 2. Validate the created Request instance.
  1544. XCTAssertEqual(request.email, self.kEmail)
  1545. XCTAssertEqual(request.password, self.kFakePassword)
  1546. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1547. XCTAssertTrue(request.returnSecureToken)
  1548. do {
  1549. // 3. Send the response from the fake backend.
  1550. try self.rpcIssuer?.respond(withJSON: ["idToken": fakeAccessToken,
  1551. "isNewUser": true,
  1552. "refreshToken": kRefreshToken])
  1553. } catch {
  1554. XCTFail("Failure sending response: \(error)")
  1555. }
  1556. }
  1557. // 1. After setting up fakes, sign out and sign in.
  1558. do {
  1559. try UserTests.auth?.signOut()
  1560. } catch {
  1561. XCTFail("Sign out failed: \(error)")
  1562. return
  1563. }
  1564. UserTests.auth?.signIn(withEmail: kEmail, password: kFakePassword) { authResult, error in
  1565. // 4. After the response triggers the callback, verify the returned result.
  1566. XCTAssertTrue(Thread.isMainThread)
  1567. guard let user = authResult?.user else {
  1568. XCTFail("authResult.user is missing")
  1569. return
  1570. }
  1571. XCTAssertEqual(user.refreshToken, kRefreshToken)
  1572. XCTAssertFalse(user.isAnonymous)
  1573. XCTAssertEqual(user.email, self.kEmail)
  1574. guard let additionalUserInfo = authResult?.additionalUserInfo else {
  1575. XCTFail("authResult.additionalUserInfo is missing")
  1576. return
  1577. }
  1578. XCTAssertFalse(additionalUserInfo.isNewUser)
  1579. XCTAssertEqual(additionalUserInfo.providerID, EmailAuthProvider.id)
  1580. XCTAssertNil(error)
  1581. // Clear the password Requester to avoid being called again by reauthenticate tests.
  1582. self.rpcIssuer?.verifyPasswordRequester = nil
  1583. completion(user)
  1584. }
  1585. }
  1586. private func signInWithGoogleCredential(completion: @escaping (User) -> Void) {
  1587. setFakeSecureTokenService(fakeAccessToken: RPCBaseTests.kFakeAccessToken)
  1588. setFakeGoogleGetAccountProvider()
  1589. rpcIssuer.respondBlock = {
  1590. try self.verifyGoogleAssertionRequest(
  1591. XCTUnwrap(self.rpcIssuer?.request as? VerifyAssertionRequest)
  1592. )
  1593. // 3. Send the response from the fake backend.
  1594. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1595. "providerId": GoogleAuthProvider.id,
  1596. "refreshToken": self.kRefreshToken,
  1597. "localId": self.kLocalID,
  1598. "displayName": self.kDisplayName,
  1599. "rawUserInfo": self.kGoogleProfile,
  1600. "username": self.kUserName])
  1601. }
  1602. do {
  1603. try UserTests.auth?.signOut()
  1604. let googleCredential = GoogleAuthProvider.credential(withIDToken: kGoogleIDToken,
  1605. accessToken: kGoogleAccessToken)
  1606. UserTests.auth?.signIn(with: googleCredential) { authResult, error in
  1607. // 4. After the response triggers the callback, verify the returned result.
  1608. XCTAssertTrue(Thread.isMainThread)
  1609. guard let user = authResult?.user else {
  1610. XCTFail("authResult.user is missing")
  1611. return
  1612. }
  1613. XCTAssertEqual(user.refreshToken, self.kRefreshToken)
  1614. XCTAssertFalse(user.isAnonymous)
  1615. XCTAssertEqual(user.email, self.kGoogleEmail)
  1616. guard let additionalUserInfo = authResult?.additionalUserInfo,
  1617. let profile = additionalUserInfo.profile as? [String: String] else {
  1618. XCTFail("authResult.additionalUserInfo and/or profile is missing")
  1619. return
  1620. }
  1621. XCTAssertEqual(profile, self.kGoogleProfile)
  1622. XCTAssertFalse(additionalUserInfo.isNewUser)
  1623. XCTAssertEqual(additionalUserInfo.providerID, GoogleAuthProvider.id)
  1624. XCTAssertEqual(additionalUserInfo.username, self.kUserName)
  1625. XCTAssertNil(error)
  1626. completion(user)
  1627. }
  1628. } catch {
  1629. XCTFail("Throw in \(#function): \(error)")
  1630. }
  1631. }
  1632. private func verifyGoogleAssertionRequest(_ request: VerifyAssertionRequest) {
  1633. XCTAssertEqual(request.providerID, GoogleAuthProvider.id)
  1634. XCTAssertEqual(request.providerIDToken, kGoogleIDToken)
  1635. XCTAssertEqual(request.providerAccessToken, kGoogleAccessToken)
  1636. XCTAssertTrue(request.returnSecureToken)
  1637. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1638. XCTAssertTrue(request.returnSecureToken)
  1639. }
  1640. private func signInWithFacebookCredential(completion: @escaping (User) -> Void) {
  1641. setFakeSecureTokenService(fakeAccessToken: RPCBaseTests.kFakeAccessToken)
  1642. setFakeGetAccountProvider(withNewDisplayName: kFacebookDisplayName,
  1643. withProviderID: FacebookAuthProvider.id,
  1644. withFederatedID: kFacebookID,
  1645. withEmail: kFacebookEmail)
  1646. rpcIssuer.respondBlock = {
  1647. let request = try XCTUnwrap(self.rpcIssuer?.request as? VerifyAssertionRequest)
  1648. XCTAssertEqual(request.providerID, FacebookAuthProvider.id)
  1649. XCTAssertEqual(request.providerIDToken, self.kFacebookIDToken)
  1650. XCTAssertEqual(request.providerAccessToken, self.kFacebookAccessToken)
  1651. XCTAssertTrue(request.returnSecureToken)
  1652. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1653. XCTAssertTrue(request.returnSecureToken)
  1654. // 3. Send the response from the fake backend.
  1655. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1656. "refreshToken": self.kRefreshToken,
  1657. "federatedId": self.kFacebookID,
  1658. "providerId": FacebookAuthProvider.id,
  1659. "localId": self.kLocalID,
  1660. "displayName": self.kDisplayName,
  1661. "rawUserInfo": self.kGoogleProfile,
  1662. "username": self.kUserName])
  1663. }
  1664. do {
  1665. try UserTests.auth?.signOut()
  1666. let facebookCredential = FacebookAuthProvider
  1667. .credential(withAccessToken: kFacebookAccessToken)
  1668. UserTests.auth?.signIn(with: facebookCredential) { authResult, error in
  1669. // 4. After the response triggers the callback, verify the returned result.
  1670. XCTAssertTrue(Thread.isMainThread)
  1671. guard let user = authResult?.user else {
  1672. XCTFail("authResult.user is missing")
  1673. return
  1674. }
  1675. XCTAssertEqual(user.refreshToken, self.kRefreshToken)
  1676. XCTAssertFalse(user.isAnonymous)
  1677. XCTAssertEqual(user.email, self.kFacebookEmail)
  1678. XCTAssertEqual(user.displayName, self.kFacebookDisplayName)
  1679. XCTAssertEqual(user.providerData.count, 1)
  1680. guard let additionalUserInfo = authResult?.additionalUserInfo,
  1681. let facebookUserInfo = user.providerData.first,
  1682. let profile = additionalUserInfo.profile as? [String: String] else {
  1683. XCTFail("authResult.additionalUserInfo and/or profile is missing")
  1684. return
  1685. }
  1686. XCTAssertEqual(facebookUserInfo.providerID, FacebookAuthProvider.id)
  1687. XCTAssertEqual(facebookUserInfo.uid, self.kFacebookID)
  1688. XCTAssertEqual(facebookUserInfo.displayName, self.kFacebookDisplayName)
  1689. XCTAssertEqual(facebookUserInfo.email, self.kFacebookEmail)
  1690. XCTAssertEqual(profile, self.kGoogleProfile)
  1691. XCTAssertFalse(additionalUserInfo.isNewUser)
  1692. XCTAssertEqual(additionalUserInfo.providerID, FacebookAuthProvider.id)
  1693. XCTAssertEqual(additionalUserInfo.username, self.kUserName)
  1694. XCTAssertNil(error)
  1695. completion(user)
  1696. }
  1697. } catch {
  1698. XCTFail("Throw in \(#function): \(error)")
  1699. }
  1700. }
  1701. private func signInWithEmailPasswordReturnFakeUserLink(completion: @escaping (User) -> Void) {
  1702. let kRefreshToken = "fakeRefreshToken"
  1703. setFakeSecureTokenService()
  1704. rpcIssuer.respondBlock = {
  1705. let request = try XCTUnwrap(self.rpcIssuer?.request as? EmailLinkSignInRequest)
  1706. XCTAssertEqual(request.email, self.kEmail)
  1707. XCTAssertEqual(request.apiKey, UserTests.kFakeAPIKey)
  1708. XCTAssertEqual(request.oobCode, "aCode")
  1709. XCTAssertNil(request.idToken)
  1710. // Send the response from the fake backend.
  1711. try self.rpcIssuer?.respond(withJSON: ["idToken": RPCBaseTests.kFakeAccessToken,
  1712. "isNewUser": true,
  1713. "refreshToken": kRefreshToken])
  1714. }
  1715. do {
  1716. try UserTests.auth?.signOut()
  1717. UserTests.auth?.signIn(
  1718. withEmail: kEmail,
  1719. link: "https://www.google.com?oobCode=aCode&mode=signIn"
  1720. ) { authResult, error in
  1721. // 4. After the response triggers the callback, verify the returned result.
  1722. XCTAssertTrue(Thread.isMainThread)
  1723. guard let user = authResult?.user else {
  1724. XCTFail("authResult.user is missing")
  1725. return
  1726. }
  1727. XCTAssertEqual(user.refreshToken, kRefreshToken)
  1728. XCTAssertFalse(user.isAnonymous)
  1729. XCTAssertEqual(user.email, self.kEmail)
  1730. guard let additionalUserInfo = authResult?.additionalUserInfo else {
  1731. XCTFail("authResult.additionalUserInfo is missing")
  1732. return
  1733. }
  1734. XCTAssertTrue(additionalUserInfo.isNewUser)
  1735. XCTAssertEqual(additionalUserInfo.providerID, EmailAuthProvider.id)
  1736. XCTAssertNil(error)
  1737. completion(user)
  1738. }
  1739. } catch {
  1740. XCTFail("Throw in \(#function): \(error)")
  1741. }
  1742. }
  1743. }