VerifyPasswordTests.swift 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 VerifyPasswordTests: RPCBaseTests {
  19. let kTestOOBCode = "OOBCode"
  20. let kTestEmail = "testEmail."
  21. let kTestPassword = "testPassword"
  22. func testVerifyPasswordRequest() throws {
  23. let kEmailKey = "email"
  24. let kPasswordKey = "password"
  25. let kCaptchaChallengeKey = "captchaChallenge"
  26. let kCaptchaResponseKey = "captchaResponse"
  27. let kSecureTokenKey = "returnSecureToken"
  28. let kExpectedAPIURL =
  29. "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=APIKey"
  30. let issuer = try checkRequest(
  31. request: makeVerifyPasswordRequest(),
  32. expected: kExpectedAPIURL,
  33. key: kEmailKey,
  34. value: kTestEmail
  35. )
  36. let requestDictionary = try XCTUnwrap(issuer.decodedRequest as? [String: AnyHashable])
  37. XCTAssertEqual(requestDictionary[kPasswordKey], kTestPassword)
  38. XCTAssertNil(requestDictionary[kCaptchaChallengeKey])
  39. XCTAssertNil(requestDictionary[kCaptchaResponseKey])
  40. XCTAssertTrue(try XCTUnwrap(requestDictionary[kSecureTokenKey] as? Bool))
  41. }
  42. func testVerifyPasswordRequestOptionalFields() throws {
  43. let kEmailKey = "email"
  44. let kPasswordKey = "password"
  45. let kCaptchaChallengeKey = "captchaChallenge"
  46. let kTestCaptchaChallenge = "testCaptchaChallenge"
  47. let kCaptchaResponseKey = "captchaResponse"
  48. let kTestCaptchaResponse = "captchaResponse"
  49. let kSecureTokenKey = "returnSecureToken"
  50. let kTestPendingToken = "testPendingToken"
  51. let kExpectedAPIURL =
  52. "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=APIKey"
  53. let request = makeVerifyPasswordRequest()
  54. request.pendingIDToken = kTestPendingToken
  55. request.captchaChallenge = kTestCaptchaChallenge
  56. request.captchaResponse = kTestCaptchaResponse
  57. let issuer = try checkRequest(
  58. request: request,
  59. expected: kExpectedAPIURL,
  60. key: kEmailKey,
  61. value: kTestEmail
  62. )
  63. let requestDictionary = try XCTUnwrap(issuer.decodedRequest as? [String: AnyHashable])
  64. XCTAssertEqual(requestDictionary[kPasswordKey], kTestPassword)
  65. XCTAssertEqual(requestDictionary[kCaptchaChallengeKey], kTestCaptchaChallenge)
  66. XCTAssertEqual(requestDictionary[kCaptchaResponseKey], kTestCaptchaResponse)
  67. XCTAssertTrue(try XCTUnwrap(requestDictionary[kSecureTokenKey] as? Bool))
  68. }
  69. func testVerifyPasswordRequestErrors() throws {
  70. let kUserDisabledErrorMessage = "USER_DISABLED"
  71. let kOperationNotAllowedErrorMessage = "OPERATION_NOT_ALLOWED"
  72. let kEmailNotFoundErrorMessage = "EMAIL_NOT_FOUND"
  73. let kWrongPasswordErrorMessage = "INVALID_PASSWORD"
  74. let kInvalidEmailErrorMessage = "INVALID_EMAIL"
  75. let kBadRequestErrorMessage = "Bad Request"
  76. let kInvalidKeyReasonValue = "keyInvalid"
  77. let kAppNotAuthorizedReasonValue = "ipRefererBlocked"
  78. let kTooManyAttemptsErrorMessage = "TOO_MANY_ATTEMPTS_TRY_LATER:"
  79. let kPasswordLoginDisabledErrorMessage = "PASSWORD_LOGIN_DISABLED"
  80. try checkBackendError(
  81. request: makeVerifyPasswordRequest(),
  82. message: kUserDisabledErrorMessage,
  83. errorCode: AuthErrorCode.userDisabled
  84. )
  85. try checkBackendError(
  86. request: makeVerifyPasswordRequest(),
  87. message: kEmailNotFoundErrorMessage,
  88. errorCode: AuthErrorCode.userNotFound
  89. )
  90. try checkBackendError(
  91. request: makeVerifyPasswordRequest(),
  92. message: kWrongPasswordErrorMessage,
  93. errorCode: AuthErrorCode.wrongPassword
  94. )
  95. try checkBackendError(
  96. request: makeVerifyPasswordRequest(),
  97. message: kInvalidEmailErrorMessage,
  98. errorCode: AuthErrorCode.invalidEmail
  99. )
  100. try checkBackendError(
  101. request: makeVerifyPasswordRequest(),
  102. message: kTooManyAttemptsErrorMessage,
  103. errorCode: AuthErrorCode.tooManyRequests
  104. )
  105. try checkBackendError(
  106. request: makeVerifyPasswordRequest(),
  107. message: kBadRequestErrorMessage,
  108. reason: kInvalidKeyReasonValue,
  109. errorCode: AuthErrorCode.invalidAPIKey
  110. )
  111. try checkBackendError(
  112. request: makeVerifyPasswordRequest(),
  113. message: kOperationNotAllowedErrorMessage,
  114. errorCode: AuthErrorCode.operationNotAllowed
  115. )
  116. try checkBackendError(
  117. request: makeVerifyPasswordRequest(),
  118. message: kPasswordLoginDisabledErrorMessage,
  119. errorCode: AuthErrorCode.operationNotAllowed
  120. )
  121. try checkBackendError(
  122. request: makeVerifyPasswordRequest(),
  123. message: kBadRequestErrorMessage,
  124. reason: kAppNotAuthorizedReasonValue,
  125. errorCode: AuthErrorCode.appNotAuthorized
  126. )
  127. }
  128. /** @fn testSuccessfulVerifyPasswordResponse
  129. @brief Tests a successful attempt of the verify password flow.
  130. */
  131. func testSuccessfulVerifyPasswordResponse() throws {
  132. let kLocalIDKey = "localId"
  133. let kTestLocalID = "testLocalId"
  134. let kEmailKey = "email"
  135. let kTestEmail = "testgmail.com"
  136. let kDisplayNameKey = "displayName"
  137. let kTestDisplayName = "testDisplayName"
  138. let kIDTokenKey = "idToken"
  139. let kTestIDToken = "ID_TOKEN"
  140. let kExpiresInKey = "expiresIn"
  141. let kTestExpiresIn = "12345"
  142. let kRefreshTokenKey = "refreshToken"
  143. let kTestRefreshToken = "REFRESH_TOKEN"
  144. let kPhotoUrlKey = "photoUrl"
  145. let kTestPhotoUrl = "www.example.com"
  146. var callbackInvoked = false
  147. var rpcResponse: VerifyPasswordResponse?
  148. var rpcError: NSError?
  149. AuthBackend.post(with: makeVerifyPasswordRequest()) { response, error in
  150. callbackInvoked = true
  151. rpcResponse = response
  152. rpcError = error as? NSError
  153. }
  154. _ = try rpcIssuer?.respond(withJSON: [
  155. kLocalIDKey: kTestLocalID,
  156. kEmailKey: kTestEmail,
  157. kDisplayNameKey: kTestDisplayName,
  158. kIDTokenKey: kTestIDToken,
  159. kExpiresInKey: kTestExpiresIn,
  160. kRefreshTokenKey: kTestRefreshToken,
  161. kPhotoUrlKey: kTestPhotoUrl,
  162. ])
  163. XCTAssert(callbackInvoked)
  164. XCTAssertNil(rpcError)
  165. XCTAssertEqual(rpcResponse?.email, kTestEmail)
  166. XCTAssertEqual(rpcResponse?.localID, kTestLocalID)
  167. XCTAssertEqual(rpcResponse?.displayName, kTestDisplayName)
  168. XCTAssertEqual(rpcResponse?.idToken, kTestIDToken)
  169. let expiresIn = try XCTUnwrap(rpcResponse?.approximateExpirationDate?.timeIntervalSinceNow)
  170. XCTAssertEqual(expiresIn, 12345, accuracy: 0.1)
  171. XCTAssertEqual(rpcResponse?.refreshToken, kTestRefreshToken)
  172. XCTAssertEqual(rpcResponse?.photoURL?.absoluteString, kTestPhotoUrl)
  173. }
  174. private func makeVerifyPasswordRequest() -> VerifyPasswordRequest {
  175. return VerifyPasswordRequest(email: kTestEmail, password: kTestPassword,
  176. requestConfiguration: makeRequestConfiguration())
  177. }
  178. }