UserTests.swift 80 KB

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