MultiFactorResolver.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. #if os(iOS)
  16. /** @class FIRPhoneMultiFactorAssertion
  17. @brief The subclass of base class FIRMultiFactorAssertion, used to assert ownership of a phone
  18. second factor.
  19. This class is available on iOS only.
  20. */
  21. @objc(FIRMultiFactorResolver)
  22. public class MultiFactorResolver: NSObject {
  23. /**
  24. @brief The opaque session identifier for the current sign-in flow.
  25. */
  26. @objc public let session: MultiFactorSession
  27. /**
  28. @brief The list of hints for the second factors needed to complete the sign-in for the current
  29. session.
  30. */
  31. @objc public let hints: [MultiFactorInfo]
  32. /**
  33. @brief The Auth reference for the current FIRMultiResolver.
  34. */
  35. @objc public let auth: Auth
  36. /** @fn resolveSignInWithAssertion:completion:
  37. @brief A helper function to help users complete sign in with a second factor using an
  38. FIRMultiFactorAssertion confirming the user successfully completed the second factor
  39. challenge.
  40. @param completion The block invoked when the request is complete, or fails.
  41. */
  42. @objc(resolveSignInWithAssertion:completion:)
  43. public func resolveSignIn(with assertion: MultiFactorAssertion,
  44. completion: ((AuthDataResult?, Error?) -> Void)? = nil) {
  45. let phoneAssertion = assertion as? PhoneMultiFactorAssertion
  46. let finalizeMFAPhoneRequestInfo = AuthProtoFinalizeMFAPhoneRequestInfo(
  47. sessionInfo: phoneAssertion?.authCredential?.verificationID,
  48. verificationCode: phoneAssertion?.authCredential?.verificationCode
  49. )
  50. let request = FinalizeMFASignInRequest(
  51. mfaPendingCredential: mfaPendingCredential,
  52. verificationInfo: finalizeMFAPhoneRequestInfo,
  53. requestConfiguration: auth.requestConfiguration
  54. )
  55. AuthBackend.post(withRequest: request) { rawResponse, error in
  56. if let error {
  57. if let completion {
  58. completion(nil, error)
  59. }
  60. } else if let response = rawResponse as? FinalizeMFAEnrollmentResponse {
  61. self.auth.completeSignIn(withAccessToken: response.idToken,
  62. accessTokenExpirationDate: nil,
  63. refreshToken: response.refreshToken,
  64. anonymous: false) { user, error in
  65. guard let user else {
  66. fatalError("Internal Auth Error: completeSignIn didn't pass back a user")
  67. }
  68. let result = AuthDataResult(withUser: user, additionalUserInfo: nil)
  69. let decoratedCallback = self.auth
  70. .signInFlowAuthDataResultCallback(byDecorating: completion)
  71. decoratedCallback(result, nil)
  72. }
  73. }
  74. }
  75. }
  76. /** @fn resolveSignInWithAssertion:completion:
  77. @brief A helper function to help users complete sign in with a second factor using an
  78. FIRMultiFactorAssertion confirming the user successfully completed the second factor
  79. challenge.
  80. @param completion The block invoked when the request is complete, or fails.
  81. */
  82. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
  83. public func resolveSignIn(with assertion: MultiFactorAssertion) async throws -> AuthDataResult {
  84. return try await withCheckedThrowingContinuation { continuation in
  85. self.resolveSignIn(with: assertion) { result, error in
  86. if let result {
  87. continuation.resume(returning: result)
  88. } else {
  89. continuation.resume(throwing: error!)
  90. }
  91. }
  92. }
  93. }
  94. let mfaPendingCredential: String?
  95. init(with mfaPendingCredential: String?, hints: [MultiFactorInfo], auth: Auth) {
  96. self.mfaPendingCredential = mfaPendingCredential
  97. self.hints = hints
  98. self.auth = auth
  99. session = MultiFactorSession()
  100. session.mfaPendingCredential = mfaPendingCredential
  101. }
  102. }
  103. #endif