StorageAuthorizerTests.swift 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2022 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. @testable import FirebaseStorage
  15. import Foundation
  16. import GTMSessionFetcherCore
  17. import SharedTestUtilities
  18. import XCTest
  19. @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
  20. class StorageAuthorizerTests: StorageTestHelpers {
  21. var appCheckTokenSuccess: FIRAppCheckTokenResultFake!
  22. var appCheckTokenError: FIRAppCheckTokenResultFake!
  23. var fetcher: GTMSessionFetcher!
  24. var auth: FIRAuthInteropFake!
  25. var appCheck: FIRAppCheckFake!
  26. let StorageTestAuthToken = "1234-5678-9012-3456-7890"
  27. override func setUp() {
  28. super.setUp()
  29. appCheckTokenSuccess = FIRAppCheckTokenResultFake(token: "token", error: nil)
  30. appCheckTokenError = FIRAppCheckTokenResultFake(token: "dummy token",
  31. error: NSError(
  32. domain: "testAppCheckError",
  33. code: -1,
  34. userInfo: nil
  35. ))
  36. let fetchRequest = URLRequest(url: StorageTestHelpers().objectURL())
  37. fetcher = GTMSessionFetcher(request: fetchRequest)
  38. auth = FIRAuthInteropFake(token: StorageTestAuthToken, userID: nil, error: nil)
  39. appCheck = FIRAppCheckFake()
  40. fetcher?.authorizer = StorageTokenAuthorizer(googleAppID: "dummyAppID",
  41. callbackQueue: DispatchQueue.main,
  42. authProvider: auth, appCheck: appCheck)
  43. }
  44. override func tearDown() {
  45. fetcher = nil
  46. auth = nil
  47. appCheck = nil
  48. appCheckTokenSuccess = nil
  49. super.tearDown()
  50. }
  51. func testSuccessfulAuth() async throws {
  52. setFetcherTestBlock(with: 200) { fetcher in
  53. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  54. }
  55. let _ = try await fetcher?.beginFetch()
  56. let headers = fetcher!.request?.allHTTPHeaderFields
  57. XCTAssertEqual(headers!["Authorization"], "Firebase \(StorageTestAuthToken)")
  58. }
  59. func testUnsuccessfulAuth() async {
  60. let authError = NSError(domain: "FIRStorageErrorDomain",
  61. code: StorageErrorCode.unauthenticated.rawValue, userInfo: nil)
  62. let failedAuth = FIRAuthInteropFake(token: nil, userID: nil, error: authError)
  63. fetcher?.authorizer = StorageTokenAuthorizer(
  64. googleAppID: "dummyAppID",
  65. authProvider: failedAuth,
  66. appCheck: nil
  67. )
  68. setFetcherTestBlock(with: 401) { fetcher in
  69. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  70. }
  71. do {
  72. let _ = try await fetcher?.beginFetch()
  73. } catch {
  74. let nsError = error as NSError
  75. XCTAssertEqual(nsError.domain, "FIRStorageErrorDomain")
  76. XCTAssertEqual(nsError.code, StorageErrorCode.unauthenticated.rawValue)
  77. XCTAssertEqual(nsError.localizedDescription, "User is not authenticated, please " +
  78. "authenticate using Firebase Authentication and try again.")
  79. }
  80. }
  81. func testSuccessfulUnauthenticatedAuth() async throws {
  82. // Simulate Auth not being included at all
  83. fetcher?.authorizer = StorageTokenAuthorizer(
  84. googleAppID: "dummyAppID",
  85. authProvider: nil,
  86. appCheck: nil
  87. )
  88. setFetcherTestBlock(with: 200) { fetcher in
  89. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  90. }
  91. let _ = try await fetcher?.beginFetch()
  92. let headers = fetcher!.request?.allHTTPHeaderFields
  93. XCTAssertNil(headers!["Authorization"])
  94. }
  95. func testSuccessfulAppCheckNoAuth() async throws {
  96. appCheck?.tokenResult = appCheckTokenSuccess!
  97. // Simulate Auth not being included at all
  98. fetcher?.authorizer = StorageTokenAuthorizer(
  99. googleAppID: "dummyAppID",
  100. authProvider: nil,
  101. appCheck: appCheck
  102. )
  103. setFetcherTestBlock(with: 200) { fetcher in
  104. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  105. }
  106. let _ = try await fetcher?.beginFetch()
  107. let headers = fetcher!.request?.allHTTPHeaderFields
  108. XCTAssertEqual(headers!["X-Firebase-AppCheck"], appCheckTokenSuccess?.token)
  109. }
  110. func testSuccessfulAppCheckAndAuth() async throws {
  111. appCheck?.tokenResult = appCheckTokenSuccess!
  112. setFetcherTestBlock(with: 200) { fetcher in
  113. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  114. }
  115. let _ = try await fetcher?.beginFetch()
  116. let headers = fetcher!.request?.allHTTPHeaderFields
  117. XCTAssertEqual(headers!["Authorization"], "Firebase \(StorageTestAuthToken)")
  118. XCTAssertEqual(headers!["X-Firebase-AppCheck"], appCheckTokenSuccess?.token)
  119. }
  120. func testAppCheckError() async throws {
  121. appCheck?.tokenResult = appCheckTokenError!
  122. setFetcherTestBlock(with: 200) { fetcher in
  123. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  124. }
  125. let _ = try await fetcher?.beginFetch()
  126. let headers = fetcher!.request?.allHTTPHeaderFields
  127. XCTAssertEqual(headers!["Authorization"], "Firebase \(StorageTestAuthToken)")
  128. XCTAssertEqual(headers!["X-Firebase-AppCheck"], appCheckTokenError?.token)
  129. }
  130. func testIsAuthorizing() async throws {
  131. setFetcherTestBlock(with: 200) { fetcher in
  132. do {
  133. let authorizer = try XCTUnwrap(fetcher.authorizer)
  134. XCTAssertFalse(authorizer.isAuthorizingRequest(fetcher.request!))
  135. } catch {
  136. XCTFail("Failed to get authorizer: \(error)")
  137. }
  138. }
  139. let _ = try await fetcher?.beginFetch()
  140. }
  141. func testStopAuthorizingNoop() async throws {
  142. setFetcherTestBlock(with: 200) { fetcher in
  143. do {
  144. let authorizer = try XCTUnwrap(fetcher.authorizer)
  145. // Since both of these are noops, we expect that invoking them
  146. // will still result in successful authenticatio
  147. authorizer.stopAuthorization()
  148. authorizer.stopAuthorization(for: fetcher.request!)
  149. } catch {
  150. XCTFail("Failed to get authorizer: \(error)")
  151. }
  152. }
  153. let _ = try await fetcher?.beginFetch()
  154. let headers = fetcher!.request?.allHTTPHeaderFields
  155. XCTAssertEqual(headers!["Authorization"], "Firebase \(StorageTestAuthToken)")
  156. }
  157. func testEmail() async throws {
  158. setFetcherTestBlock(with: 200) { fetcher in
  159. do {
  160. let authorizer = try XCTUnwrap(fetcher.authorizer)
  161. XCTAssertNil(authorizer.userEmail)
  162. } catch {
  163. XCTFail("Failed to get authorizer: \(error)")
  164. }
  165. }
  166. let _ = try await fetcher?.beginFetch()
  167. }
  168. // MARK: Helpers
  169. private func setFetcherTestBlock(with statusCode: Int,
  170. _ validationBlock: @escaping (GTMSessionFetcher) -> Void) {
  171. fetcher?.testBlock = { (fetcher: GTMSessionFetcher,
  172. response: GTMSessionFetcherTestResponse) in
  173. validationBlock(fetcher)
  174. let httpResponse = HTTPURLResponse(url: (fetcher.request?.url)!,
  175. statusCode: statusCode,
  176. httpVersion: "HTTP/1.1",
  177. headerFields: nil)
  178. response(httpResponse, nil, nil)
  179. }
  180. }
  181. private func checkAuthorizer(fetcher: GTMSessionFetcher, trueFalse: Bool) {
  182. do {
  183. let authorizer = try XCTUnwrap(fetcher.authorizer)
  184. XCTAssertEqual(authorizer.isAuthorizedRequest(fetcher.request!), trueFalse)
  185. } catch {
  186. XCTFail("Failed to get authorizer: \(error)")
  187. }
  188. }
  189. }