Auth+Combine.swift 24 KB

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