Auth+Combine.swift 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. // Copyright 2020 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. #if canImport(Combine) && swift(>=5.0)
  15. import Combine
  16. import FirebaseAuth
  17. // Make this class discoverable from Objective-C. Don't instantiate directly.
  18. @objc(FIRCombineAuthLibrary) private class __CombineAuthLibrary: NSObject {}
  19. @available(swift 5.0)
  20. @available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)
  21. public extension Auth {
  22. // MARK: - Authentication State Management
  23. /// Registers a publisher that publishes authentication state changes.
  24. ///
  25. /// The publisher emits values when:
  26. ///
  27. /// - It is registered,
  28. /// - a user with a different UID from the current user has signed in, or
  29. /// - the current user has signed out.
  30. ///
  31. /// The publisher will emit events on the **main** thread.
  32. ///
  33. /// - Returns: A publisher emitting a `User` instance (if the user has signed in) or `nil` (if the user has signed out).
  34. /// The publisher will emit on the *main* thread.
  35. func authStateDidChangePublisher() -> AnyPublisher<User?, Never> {
  36. let subject = PassthroughSubject<User?, Never>()
  37. let handle = addStateDidChangeListener { auth, user in
  38. subject.send(user)
  39. }
  40. return subject
  41. .handleEvents(receiveCancel: {
  42. self.removeStateDidChangeListener(handle)
  43. })
  44. .eraseToAnyPublisher()
  45. }
  46. /// Registers a publisher that publishes ID token state changes.
  47. ///
  48. /// The publisher emits values when:
  49. ///
  50. /// - It is registered,
  51. /// - a user with a different UID from the current user has signed in,
  52. /// - the ID token of the current user has been refreshed, or
  53. /// - the current user has signed out.
  54. ///
  55. /// The publisher will emit events on the **main** thread.
  56. ///
  57. /// - Returns: A publisher emitting a `User` instance (if a different user is signed in or
  58. /// the ID token of the current user has changed) or `nil` (if the user has signed out).
  59. /// The publisher will emit on the *main* thread.
  60. func idTokenDidChangePublisher() -> AnyPublisher<User?, Never> {
  61. let subject = PassthroughSubject<User?, Never>()
  62. let handle = addIDTokenDidChangeListener { auth, user in
  63. subject.send(user)
  64. }
  65. return subject
  66. .handleEvents(receiveCancel: {
  67. self.removeIDTokenDidChangeListener(handle)
  68. })
  69. .eraseToAnyPublisher()
  70. }
  71. /// Sets the `currentUser` on the calling Auth instance to the provided `user` object.
  72. ///
  73. /// The publisher will emit events on the **main** thread.
  74. ///
  75. /// - Parameter user: The user object to be set as the current user of the calling Auth instance.
  76. /// - Returns: A publisher that emits when the user of the calling Auth instance has been updated or
  77. /// an error was encountered. The publisher will emit on the **main** thread.
  78. @discardableResult
  79. func updateCurrentUser(_ user: User) -> Future<Void, Error> {
  80. Future<Void, Error> { promise in
  81. self.updateCurrentUser(user) { error in
  82. if let error = error {
  83. promise(.failure(error))
  84. } else {
  85. promise(.success(()))
  86. }
  87. }
  88. }
  89. }
  90. // MARK: - Anonymous Authentication
  91. /// Asynchronously creates an anonymous user and assigns it as the calling Auth instance's current user.
  92. ///
  93. /// If there is already an anonymous user signed in, that user will be returned instead.
  94. /// If there is any other existing user signed in, that user will be signed out.
  95. ///
  96. /// The publisher will emit events on the **main** thread.
  97. ///
  98. /// - Returns: A publisher that emits the result of the sign in flow. The publisher will emit on the *main* thread.
  99. /// - Remark:
  100. /// Possible error codes:
  101. /// - `AuthErrorCodeOperationNotAllowed` - Indicates that anonymous accounts are
  102. /// not enabled. Enable them in the Auth section of the Firebase console.
  103. ///
  104. /// See `AuthErrors` for a list of error codes that are common to all API methods
  105. @discardableResult
  106. func signInAnonymously() -> Future<AuthDataResult, Error> {
  107. Future<AuthDataResult, Error> { promise in
  108. self.signInAnonymously { authDataResult, error in
  109. if let error = error {
  110. promise(.failure(error))
  111. } else if let authDataResult = authDataResult {
  112. promise(.success(authDataResult))
  113. }
  114. }
  115. }
  116. }
  117. // MARK: - Email/Password Authentication
  118. /// Creates and, on success, signs in a user with the given email address and password.
  119. ///
  120. /// The publisher will emit events on the **main** thread.
  121. ///
  122. /// - Parameters:
  123. /// - email: The user's email address.
  124. /// - password: The user's desired password.
  125. /// - Returns: A publisher that emits the result of the sign in flow. The publisher will emit on the *main* thread.
  126. /// - Remark:
  127. /// Possible error codes:
  128. /// - `AuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  129. /// - `AuthErrorCodeEmailAlreadyInUse` - Indicates the email used to attempt sign up
  130. /// already exists. Call fetchProvidersForEmail to check which sign-in mechanisms the user
  131. /// used, and prompt the user to sign in with one of those.
  132. /// - `AuthErrorCodeOperationNotAllowed` - Indicates that email and password accounts
  133. /// are not enabled. Enable them in the Auth section of the Firebase console.
  134. /// - `AuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is
  135. /// considered too weak. The NSLocalizedFailureReasonErrorKey field in the NSError.userInfo
  136. /// dictionary object will contain more detailed explanation that can be shown to the user.
  137. ///
  138. /// See `AuthErrors` for a list of error codes that are common to all API methods
  139. @discardableResult
  140. func createUser(withEmail email: String,
  141. password: String) -> Future<AuthDataResult, Error> {
  142. Future<AuthDataResult, Error> { promise in
  143. self.createUser(withEmail: email, password: password) { authDataResult, error in
  144. if let error = error {
  145. promise(.failure(error))
  146. } else if let authDataResult = authDataResult {
  147. promise(.success(authDataResult))
  148. }
  149. }
  150. }
  151. }
  152. /// Signs in a user with the given email address and password.
  153. ///
  154. /// The publisher will emit events on the **main** thread.
  155. ///
  156. /// - Parameters:
  157. /// - email: The user's email address.
  158. /// - password: The user's password.
  159. /// - Returns: A publisher that emits the result of the sign in flow. The publisher will emit on the *main* thread.
  160. /// - Remark:
  161. /// Possible error codes:
  162. /// - `AuthErrorCodeOperationNotAllowed` - Indicates that email and password
  163. /// accounts are not enabled. Enable them in the Auth section of the
  164. /// Firebase console.
  165. /// - `AuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  166. /// - `AuthErrorCodeWrongPassword` - Indicates the user attempted
  167. /// sign in with an incorrect password.
  168. /// - `AuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  169. ///
  170. /// See `AuthErrors` for a list of error codes that are common to all API methods
  171. @discardableResult
  172. func signIn(withEmail email: String,
  173. password: String) -> Future<AuthDataResult, Error> {
  174. Future<AuthDataResult, Error> { promise in
  175. self.signIn(withEmail: email, password: password) { authDataResult, error in
  176. if let error = error {
  177. promise(.failure(error))
  178. } else if let authDataResult = authDataResult {
  179. promise(.success(authDataResult))
  180. }
  181. }
  182. }
  183. }
  184. // MARK: - Email/Link Authentication
  185. /// Signs in using an email address and email sign-in link.
  186. ///
  187. /// The publisher will emit events on the **main** thread.
  188. ///
  189. /// - Parameters:
  190. /// - email: The user's email address.
  191. /// - link: The email sign-in link.
  192. /// - Returns: A publisher that emits the result of the sign in flow. The publisher will emit on the *main* thread.
  193. /// - Remark:
  194. /// Possible error codes:
  195. /// - `AuthErrorCodeOperationNotAllowed` - Indicates that email and password
  196. /// accounts are not enabled. Enable them in the Auth section of the
  197. /// Firebase console.
  198. /// - `AuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  199. /// - `AuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  200. ///
  201. /// See `AuthErrors` for a list of error codes that are common to all API methods
  202. @available(watchOS, unavailable)
  203. @discardableResult
  204. func signIn(withEmail email: String,
  205. link: String) -> Future<AuthDataResult, Error> {
  206. Future<AuthDataResult, Error> { promise in
  207. self.signIn(withEmail: email, link: link) { authDataResult, error in
  208. if let error = error {
  209. promise(.failure(error))
  210. } else if let authDataResult = authDataResult {
  211. promise(.success(authDataResult))
  212. }
  213. }
  214. }
  215. }
  216. /// Sends a sign in with email link to provided email address.
  217. ///
  218. /// The publisher will emit events on the **main** thread.
  219. ///
  220. /// - Parameters:
  221. /// - email: The email address of the user.
  222. /// - actionCodeSettings: An `ActionCodeSettings` object containing settings related to
  223. /// handling action codes.
  224. /// - Returns: A publisher that emits whether the call was successful or not. The publisher will emit on the *main* thread.
  225. @available(watchOS, unavailable)
  226. @discardableResult
  227. func sendSignInLink(toEmail email: String,
  228. actionCodeSettings: ActionCodeSettings) -> Future<Void, Error> {
  229. Future<Void, Error> { promise in
  230. self.sendSignInLink(toEmail: email, actionCodeSettings: actionCodeSettings) { error in
  231. if let error = error {
  232. promise(.failure(error))
  233. } else {
  234. promise(.success(()))
  235. }
  236. }
  237. }
  238. }
  239. // MARK: - Email-based Authentication Helpers
  240. /// Fetches the list of all sign-in methods previously used for the provided email address.
  241. ///
  242. /// The publisher will emit events on the **main** thread.
  243. ///
  244. /// - Parameter email: The email address for which to obtain a list of sign-in methods.
  245. /// - Returns: A publisher that emits a list of sign-in methods for the specified email
  246. /// address, or an error if one occurred. The publisher will emit on the *main* thread.
  247. /// - Remark: Possible error codes:
  248. /// - `AuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  249. ///
  250. /// See `AuthErrors` for a list of error codes that are common to all API methods
  251. func fetchSignInMethods(forEmail email: String) -> Future<[String], Error> {
  252. Future<[String], Error> { promise in
  253. self.fetchSignInMethods(forEmail: email) { signInMethods, error in
  254. if let error = error {
  255. promise(.failure(error))
  256. } else if let signInMethods = signInMethods {
  257. promise(.success(signInMethods))
  258. }
  259. }
  260. }
  261. }
  262. // MARK: - Password Reset
  263. /// Resets the password given a code sent to the user outside of the app and a new password for the user.
  264. ///
  265. /// The publisher will emit events on the **main** thread.
  266. ///
  267. /// - Parameters:
  268. /// - code: Out-of-band (OOB) code given to the user outside of the app.
  269. /// - newPassword: The new password.
  270. /// - Returns: A publisher that emits whether the call was successful or not. The publisher will emit on the *main* thread.
  271. /// - Remark: Possible error codes:
  272. /// - `AuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is considered too weak.
  273. /// - `AuthErrorCodeOperationNotAllowed` - Indicates the admin disabled sign in with the specified identity provider.
  274. /// - `AuthErrorCodeExpiredActionCode` - Indicates the OOB code is expired.
  275. /// - `AuthErrorCodeInvalidActionCode` - Indicates the OOB code is invalid.
  276. ///
  277. /// See `AuthErrors` for a list of error codes that are common to all API methods
  278. @discardableResult
  279. func confirmPasswordReset(withCode code: String,
  280. newPassword: String) -> Future<Void, Error> {
  281. Future<Void, Error> { promise in
  282. self.confirmPasswordReset(withCode: code, newPassword: newPassword) { error in
  283. if let error = error {
  284. promise(.failure(error))
  285. } else {
  286. promise(.success(()))
  287. }
  288. }
  289. }
  290. }
  291. /// Checks the validity of a verify password reset code.
  292. ///
  293. /// The publisher will emit events on the **main** thread.
  294. ///
  295. /// - Parameter code: The password reset code to be verified.
  296. /// - Returns: A publisher that emits an error if the code could not be verified. If the code could be
  297. /// verified, the publisher will emit the email address of the account the code was issued for.
  298. /// The publisher will emit on the *main* thread.
  299. @discardableResult
  300. func verifyPasswordResetCode(_ code: String) -> Future<String, Error> {
  301. Future<String, Error> { promise in
  302. self.verifyPasswordResetCode(code) { email, error in
  303. if let error = error {
  304. promise(.failure(error))
  305. } else if let email = email {
  306. promise(.success(email))
  307. }
  308. }
  309. }
  310. }
  311. /// Checks the validity of an out of band code.
  312. ///
  313. /// The publisher will emit events on the **main** thread.
  314. ///
  315. /// - Parameter code: The out of band code to check validity.
  316. /// - Returns: A publisher that emits the email address of the account the code was issued for or an error if
  317. /// the code could not be verified. The publisher will emit on the *main* thread.
  318. @discardableResult
  319. func checkActionCode(code: String) -> Future<ActionCodeInfo, Error> {
  320. Future<ActionCodeInfo, Error> { promise in
  321. self.checkActionCode(code) { actionCodeInfo, error in
  322. if let error = error {
  323. promise(.failure(error))
  324. } else if let actionCodeInfo = actionCodeInfo {
  325. promise(.success(actionCodeInfo))
  326. }
  327. }
  328. }
  329. }
  330. /// Applies out of band code.
  331. ///
  332. /// The publisher will emit events on the **main** thread.
  333. ///
  334. /// - Parameter code: The out-of-band (OOB) code to be applied.
  335. /// - Returns: A publisher that emits an error if the code could not be applied. The publisher will emit on the *main* thread.
  336. /// - Remark: This method will not work for out-of-band codes which require an additional parameter,
  337. /// such as password reset codes.
  338. @discardableResult
  339. func applyActionCode(code: String) -> Future<Void, Error> {
  340. Future<Void, Error> { promise in
  341. self.applyActionCode(code) { error in
  342. if let error = error {
  343. promise(.failure(error))
  344. } else {
  345. promise(.success(()))
  346. }
  347. }
  348. }
  349. }
  350. /// Initiates a password reset for the given email address.
  351. ///
  352. /// The publisher will emit events on the **main** thread.
  353. ///
  354. /// - Parameter email: The email address of the user.
  355. /// - Returns: A publisher that emits whether the call was successful or not. The publisher will emit on the *main* thread.
  356. /// - Remark: Possible error codes:
  357. /// - `AuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was sent in the request.
  358. /// - `AuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in the console for this action.
  359. /// - `AuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for sending update email.
  360. ///
  361. /// See `AuthErrors` for a list of error codes that are common to all API methods
  362. @discardableResult
  363. func sendPasswordReset(withEmail email: String) -> Future<Void, Error> {
  364. Future<Void, Error> { promise in
  365. self.sendPasswordReset(withEmail: email) { error in
  366. if let error = error {
  367. promise(.failure(error))
  368. } else {
  369. promise(.success(()))
  370. }
  371. }
  372. }
  373. }
  374. /// Initiates a password reset for the given email address and `ActionCodeSettings`.
  375. ///
  376. /// The publisher will emit events on the **main** thread.
  377. ///
  378. /// - Parameter email: The email address of the user.
  379. /// - Parameter actionCodeSettings: An `ActionCodeSettings` object containing settings related to
  380. /// handling action codes.
  381. /// - Returns: A publisher that emits whether the call was successful or not. The publisher will emit on the *main* thread.
  382. /// - Remark: Possible error codes:
  383. /// - `AuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was sent in the request.
  384. /// - `AuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in the console for this action.
  385. /// - `AuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for sending update email.
  386. /// - `AuthErrorCodeMissingIosBundleID` - Indicates that the iOS bundle ID is missing
  387. /// when `handleCodeInApp` is set to YES.
  388. /// - `AuthErrorCodeMissingAndroidPackageName` - Indicates that the android package name is missing
  389. /// when the `androidInstallApp` flag is set to true.
  390. /// - `AuthErrorCodeUnauthorizedDomain` - Indicates that the domain specified in the continue URL is not whitelisted
  391. /// in the Firebase console.
  392. /// - `AuthErrorCodeInvalidContinueURI` - Indicates that the domain specified in the continue URI is not valid.
  393. ///
  394. /// See `AuthErrors` for a list of error codes that are common to all API methods
  395. @discardableResult
  396. func sendPasswordReset(withEmail email: String,
  397. actionCodeSettings: ActionCodeSettings) -> Future<Void, Error> {
  398. Future<Void, Error> { promise in
  399. self.sendPasswordReset(withEmail: email, actionCodeSettings: actionCodeSettings) { error in
  400. if let error = error {
  401. promise(.failure(error))
  402. } else {
  403. promise(.success(()))
  404. }
  405. }
  406. }
  407. }
  408. // MARK: - Other Authentication providers
  409. #if os(iOS) || targetEnvironment(macCatalyst)
  410. /// Signs in using the provided auth provider instance.
  411. ///
  412. /// The publisher will emit events on the **main** thread.
  413. ///
  414. /// - Parameters:
  415. /// - provider: An instance of an auth provider used to initiate the sign-in flow.
  416. /// - uiDelegate: Optionally, an instance of a class conforming to the `AuthUIDelegate`
  417. /// protocol. This is used for presenting the web context. If `nil`, a default `AuthUIDelegate`
  418. /// will be used.
  419. /// - Returns: A publisher that emits an `AuthDataResult` when the sign-in flow completed
  420. /// successfully, or an error otherwise. The publisher will emit on the *main* thread.
  421. /// - Remark: Possible error codes:
  422. /// - `AuthErrorCodeOperationNotAllowed` - Indicates that email and password accounts are not enabled.
  423. /// Enable them in the Auth section of the Firebase console.
  424. /// - `AuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  425. /// - `AuthErrorCodeWebNetworkRequestFailed` - Indicates that a network request within a
  426. /// `SFSafariViewController` or `WKWebView` failed.
  427. /// - `AuthErrorCodeWebInternalError` - Indicates that an internal error occurred within a
  428. /// `SFSafariViewController` or `WKWebView`.`
  429. /// - `AuthErrorCodeWebSignInUserInteractionFailure` - Indicates a general failure during a web sign-in flow.`
  430. /// - `AuthErrorCodeWebContextAlreadyPresented` - Indicates that an attempt was made to present a new web
  431. /// context while one was already being presented.`
  432. /// - `AuthErrorCodeWebContextCancelled` - Indicates that the URL presentation was cancelled prematurely
  433. /// by the user.`
  434. /// - `AuthErrorCodeAccountExistsWithDifferentCredential` - Indicates the email asserted by the credential
  435. /// (e.g. the email in a Facebook access token) is already in use by an existing account that cannot be
  436. /// authenticated with this sign-in method. Call `fetchProvidersForEmail` for this user’s email and then
  437. /// prompt them to sign in with any of the sign-in providers returned. This error will only be thrown if
  438. /// the "One account per email address" setting is enabled in the Firebase console, under Auth settings.
  439. ///
  440. /// See `AuthErrors` for a list of error codes that are common to all API methods
  441. @discardableResult
  442. func signIn(with provider: FederatedAuthProvider,
  443. uiDelegate: AuthUIDelegate?) -> Future<AuthDataResult, Error> {
  444. Future<AuthDataResult, Error> { promise in
  445. self.signIn(with: provider, uiDelegate: uiDelegate) { authDataResult, error in
  446. if let error = error {
  447. promise(.failure(error))
  448. } else if let authDataResult = authDataResult {
  449. promise(.success(authDataResult))
  450. }
  451. }
  452. }
  453. }
  454. #endif // os(iOS) || targetEnvironment(macCatalyst)
  455. /// Asynchronously signs in to Firebase with the given Auth token.
  456. ///
  457. /// The publisher will emit events on the **main** thread.
  458. ///
  459. /// - Parameter token: A self-signed custom auth token.
  460. /// - Returns: A publisher that emits an `AuthDataResult` when the sign-in flow completed
  461. /// successfully, or an error otherwise. The publisher will emit on the *main* thread.
  462. /// - Remark: Possible error codes:
  463. /// - `AuthErrorCodeInvalidCustomToken` - Indicates a validation error with the custom token.
  464. /// - `AuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  465. /// - `AuthErrorCodeCustomTokenMismatch` - Indicates the service account and the API key
  466. /// belong to different projects.
  467. ///
  468. /// See `AuthErrors` for a list of error codes that are common to all API methods
  469. @discardableResult
  470. func signIn(withCustomToken token: String) -> Future<AuthDataResult, Error> {
  471. Future<AuthDataResult, Error> { promise in
  472. self.signIn(withCustomToken: token) { authDataResult, error in
  473. if let error = error {
  474. promise(.failure(error))
  475. } else if let authDataResult = authDataResult {
  476. promise(.success(authDataResult))
  477. }
  478. }
  479. }
  480. }
  481. /// Asynchronously signs in to Firebase with the given 3rd-party credentials (e.g. a Facebook
  482. /// login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional
  483. /// identity provider data.
  484. ///
  485. /// The publisher will emit events on the **main** thread.
  486. ///
  487. /// - Parameter credential: The credential supplied by the IdP.
  488. /// - Returns: A publisher that emits an `AuthDataResult` when the sign-in flow completed
  489. /// successfully, or an error otherwise. The publisher will emit on the *main* thread.
  490. /// - Remark: Possible error codes:
  491. /// - `FIRAuthErrorCodeInvalidCredential` - Indicates the supplied credential is invalid.
  492. /// This could happen if it has expired or it is malformed.
  493. /// - `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts
  494. /// with the identity provider represented by the credential are not enabled.
  495. /// Enable them in the Auth section of the Firebase console.
  496. /// - `FIRAuthErrorCodeAccountExistsWithDifferentCredential` - Indicates the email asserted
  497. /// by the credential (e.g. the email in a Facebook access token) is already in use by an
  498. /// existing account, that cannot be authenticated with this sign-in method. Call
  499. /// fetchProvidersForEmail for this user’s email and then prompt them to sign in with any of
  500. /// the sign-in providers returned. This error will only be thrown if the "One account per
  501. /// email address" setting is enabled in the Firebase console, under Auth settings.
  502. /// - `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  503. /// - `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted sign in with an
  504. /// incorrect password, if credential is of the type EmailPasswordAuthCredential.
  505. /// - `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  506. /// - `FIRAuthErrorCodeMissingVerificationID` - Indicates that the phone auth credential was
  507. /// created with an empty verification ID.
  508. /// - `FIRAuthErrorCodeMissingVerificationCode` - Indicates that the phone auth credential
  509. /// was created with an empty verification code.
  510. /// - `FIRAuthErrorCodeInvalidVerificationCode` - Indicates that the phone auth credential
  511. /// was created with an invalid verification Code.
  512. /// - `FIRAuthErrorCodeInvalidVerificationID` - Indicates that the phone auth credential was
  513. /// created with an invalid verification ID.
  514. /// - `FIRAuthErrorCodeSessionExpired` - Indicates that the SMS code has expired.
  515. ///
  516. /// See `AuthErrors` for a list of error codes that are common to all API methods
  517. @discardableResult
  518. func signIn(with credential: AuthCredential) -> Future<AuthDataResult, Error> {
  519. Future<AuthDataResult, Error> { promise in
  520. self.signIn(with: credential) { authDataResult, error in
  521. if let error = error {
  522. promise(.failure(error))
  523. } else if let authDataResult = authDataResult {
  524. promise(.success(authDataResult))
  525. }
  526. }
  527. }
  528. }
  529. }
  530. #endif // canImport(Combine) && swift(>=5.0)