GetOOBConfirmationCodeTests.swift 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
  18. class GetOOBConfirmationCodeTests: RPCBaseTests {
  19. private let kRequestTypeKey = "requestType"
  20. private let kPasswordResetRequestTypeValue = "PASSWORD_RESET"
  21. private let kVerifyEmailRequestTypeValue = "VERIFY_EMAIL"
  22. private let kEmailLinkSignInTypeValue = "EMAIL_SIGNIN"
  23. private let kEmailKey = "email"
  24. private let kTestEmail = "testgmail.com"
  25. private let kAccessTokenKey = "idToken"
  26. private let kTestAccessToken = "ACCESS_TOKEN"
  27. private let kContinueURLKey = "continueUrl"
  28. private let kIosBundleIDKey = "iOSBundleId"
  29. private let kAndroidPackageNameKey = "androidPackageName"
  30. private let kAndroidInstallAppKey = "androidInstallApp"
  31. private let kAndroidMinimumVersionKey = "androidMinimumVersion"
  32. private let kCanHandleCodeInAppKey = "canHandleCodeInApp"
  33. private let kDynamicLinkDomainKey = "dynamicLinkDomain"
  34. private let kExpectedAPIURL =
  35. "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode?key=APIKey"
  36. private let kOOBCodeKey = "oobCode"
  37. private let kTestOOBCode = "OOBCode"
  38. func testOobRequests() throws {
  39. for (request, requestType) in [
  40. (getPasswordResetRequest, kPasswordResetRequestTypeValue),
  41. (getSignInWithEmailRequest, kEmailLinkSignInTypeValue),
  42. (getEmailVerificationRequest, kVerifyEmailRequestTypeValue),
  43. ] {
  44. let request = try request()
  45. let rpcIssuer = try checkRequest(
  46. request: request,
  47. expected: kExpectedAPIURL,
  48. key: "should_be_empty_dictionary",
  49. value: nil
  50. )
  51. let decodedRequest = try XCTUnwrap(rpcIssuer.decodedRequest)
  52. XCTAssertEqual(decodedRequest[kRequestTypeKey] as? String, requestType)
  53. if requestType == kVerifyEmailRequestTypeValue {
  54. XCTAssertEqual(decodedRequest[kAccessTokenKey] as? String, kTestAccessToken)
  55. } else {
  56. XCTAssertEqual(decodedRequest[kEmailKey] as? String, kTestEmail)
  57. }
  58. XCTAssertEqual(decodedRequest[kContinueURLKey] as? String, kContinueURL)
  59. XCTAssertEqual(decodedRequest[kIosBundleIDKey] as? String, kIosBundleID)
  60. XCTAssertEqual(decodedRequest[kAndroidPackageNameKey] as? String, kAndroidPackageName)
  61. XCTAssertEqual(decodedRequest[kAndroidMinimumVersionKey] as? String, kAndroidMinimumVersion)
  62. XCTAssertEqual(decodedRequest[kAndroidInstallAppKey] as? Bool, true)
  63. XCTAssertEqual(decodedRequest[kCanHandleCodeInAppKey] as? Bool, true)
  64. XCTAssertEqual(decodedRequest[kDynamicLinkDomainKey] as? String, kDynamicLinkDomain)
  65. }
  66. }
  67. func testGetOOBConfirmationCodeErrors() throws {
  68. let kEmailNotFoundMessage = "EMAIL_NOT_FOUND: fake custom message"
  69. let kMissingEmailErrorMessage = "MISSING_EMAIL"
  70. let kInvalidEmailErrorMessage = "INVALID_EMAIL:"
  71. let kInvalidMessagePayloadErrorMessage = "INVALID_MESSAGE_PAYLOAD"
  72. let kInvalidSenderErrorMessage = "INVALID_SENDER"
  73. let kMissingIosBundleIDErrorMessage = "MISSING_IOS_BUNDLE_ID"
  74. let kMissingAndroidPackageNameErrorMessage = "MISSING_ANDROID_PACKAGE_NAME"
  75. let kUnauthorizedDomainErrorMessage = "UNAUTHORIZED_DOMAIN"
  76. let kInvalidRecipientEmailErrorMessage = "INVALID_RECIPIENT_EMAIL"
  77. let kInvalidContinueURIErrorMessage = "INVALID_CONTINUE_URI"
  78. let kMissingContinueURIErrorMessage = "MISSING_CONTINUE_URI"
  79. try checkBackendError(
  80. request: getPasswordResetRequest(),
  81. message: kEmailNotFoundMessage,
  82. errorCode: AuthErrorCode.userNotFound
  83. )
  84. try checkBackendError(
  85. request: getEmailVerificationRequest(),
  86. message: kMissingEmailErrorMessage,
  87. errorCode: AuthErrorCode.missingEmail
  88. )
  89. try checkBackendError(
  90. request: getPasswordResetRequest(),
  91. message: kInvalidEmailErrorMessage,
  92. errorCode: AuthErrorCode.invalidEmail
  93. )
  94. try checkBackendError(
  95. request: getPasswordResetRequest(),
  96. message: kInvalidMessagePayloadErrorMessage,
  97. errorCode: AuthErrorCode.invalidMessagePayload
  98. )
  99. try checkBackendError(
  100. request: getPasswordResetRequest(),
  101. message: kInvalidSenderErrorMessage,
  102. errorCode: AuthErrorCode.invalidSender
  103. )
  104. try checkBackendError(
  105. request: getPasswordResetRequest(),
  106. message: kMissingIosBundleIDErrorMessage,
  107. errorCode: AuthErrorCode.missingIosBundleID
  108. )
  109. try checkBackendError(
  110. request: getPasswordResetRequest(),
  111. message: kMissingAndroidPackageNameErrorMessage,
  112. errorCode: AuthErrorCode.missingAndroidPackageName
  113. )
  114. try checkBackendError(
  115. request: getPasswordResetRequest(),
  116. message: kUnauthorizedDomainErrorMessage,
  117. errorCode: AuthErrorCode.unauthorizedDomain
  118. )
  119. try checkBackendError(
  120. request: getPasswordResetRequest(),
  121. message: kInvalidRecipientEmailErrorMessage,
  122. errorCode: AuthErrorCode.invalidRecipientEmail
  123. )
  124. try checkBackendError(
  125. request: getPasswordResetRequest(),
  126. message: kInvalidContinueURIErrorMessage,
  127. errorCode: AuthErrorCode.invalidContinueURI
  128. )
  129. try checkBackendError(
  130. request: getPasswordResetRequest(),
  131. message: kMissingContinueURIErrorMessage,
  132. errorCode: AuthErrorCode.missingContinueURI
  133. )
  134. }
  135. /** @fn testSuccessfulPasswordResetResponse
  136. @brief This test simulates a complete password reset response (with OOB Code) and makes sure
  137. it succeeds, and we get the OOB Code decoded correctly.
  138. */
  139. func testSuccessfulOOBResponse() throws {
  140. var callbackInvoked = false
  141. var rpcResponse: GetOOBConfirmationCodeResponse?
  142. var rpcError: NSError?
  143. for request in [
  144. getPasswordResetRequest,
  145. getSignInWithEmailRequest,
  146. getEmailVerificationRequest,
  147. ] {
  148. let request = try request()
  149. AuthBackend.post(with: request) { response, error in
  150. callbackInvoked = true
  151. rpcResponse = response
  152. rpcError = error as? NSError
  153. }
  154. _ = try rpcIssuer?.respond(withJSON: [kOOBCodeKey: kTestOOBCode])
  155. XCTAssert(callbackInvoked)
  156. XCTAssertNil(rpcError)
  157. let response = try XCTUnwrap(rpcResponse)
  158. XCTAssertEqual(response.OOBCode, kTestOOBCode)
  159. }
  160. }
  161. /** @fn testSuccessfulPasswordResetResponseWithoutOOBCode
  162. @brief This test simulates a password reset request where we don't receive the optional OOBCode
  163. response value. It should still succeed.
  164. */
  165. func testSuccessfulOOBResponseWithoutOOBCode() throws {
  166. var callbackInvoked = false
  167. var rpcResponse: GetOOBConfirmationCodeResponse?
  168. var rpcError: NSError?
  169. for request in [
  170. getPasswordResetRequest,
  171. getSignInWithEmailRequest,
  172. getEmailVerificationRequest,
  173. ] {
  174. let request = try request()
  175. AuthBackend.post(with: request) { response, error in
  176. callbackInvoked = true
  177. rpcResponse = response
  178. rpcError = error as? NSError
  179. }
  180. _ = try rpcIssuer?.respond(withJSON: [:])
  181. XCTAssert(callbackInvoked)
  182. XCTAssertNil(rpcError)
  183. let response = try XCTUnwrap(rpcResponse)
  184. XCTAssertNil(response.OOBCode)
  185. }
  186. }
  187. private func getPasswordResetRequest() throws -> GetOOBConfirmationCodeRequest {
  188. return try XCTUnwrap(GetOOBConfirmationCodeRequest.passwordResetRequest(email: kTestEmail,
  189. actionCodeSettings: fakeActionCodeSettings(
  190. ),
  191. requestConfiguration: makeRequestConfiguration(
  192. )))
  193. }
  194. private func getSignInWithEmailRequest() throws -> GetOOBConfirmationCodeRequest {
  195. return try XCTUnwrap(GetOOBConfirmationCodeRequest.signInWithEmailLinkRequest(kTestEmail,
  196. actionCodeSettings: fakeActionCodeSettings(
  197. ),
  198. requestConfiguration: makeRequestConfiguration(
  199. )))
  200. }
  201. private func getEmailVerificationRequest() throws -> GetOOBConfirmationCodeRequest {
  202. return try XCTUnwrap(GetOOBConfirmationCodeRequest
  203. .verifyEmailRequest(accessToken: kTestAccessToken,
  204. actionCodeSettings: fakeActionCodeSettings(),
  205. requestConfiguration: makeRequestConfiguration()))
  206. }
  207. }