StorageAuthorizerTests.swift 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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 fetcherService: GTMSessionFetcherService!
  25. var auth: FIRAuthInteropFake!
  26. var appCheck: FIRAppCheckFake!
  27. let StorageTestAuthToken = "1234-5678-9012-3456-7890"
  28. override func setUp() {
  29. super.setUp()
  30. appCheckTokenSuccess = FIRAppCheckTokenResultFake(token: "token", error: nil)
  31. appCheckTokenError = FIRAppCheckTokenResultFake(token: "dummy token",
  32. error: NSError(
  33. domain: "testAppCheckError",
  34. code: -1,
  35. userInfo: nil
  36. ))
  37. let fetchRequest = URLRequest(url: StorageTestHelpers().objectURL())
  38. fetcher = GTMSessionFetcher(request: fetchRequest)
  39. fetcherService = GTMSessionFetcherService()
  40. auth = FIRAuthInteropFake(token: StorageTestAuthToken, userID: nil, error: nil)
  41. appCheck = FIRAppCheckFake()
  42. fetcher?.authorizer = StorageTokenAuthorizer(googleAppID: "dummyAppID",
  43. fetcherService: fetcherService!,
  44. authProvider: auth, appCheck: appCheck)
  45. }
  46. override func tearDown() {
  47. fetcher = nil
  48. fetcherService = nil
  49. auth = nil
  50. appCheck = nil
  51. appCheckTokenSuccess = nil
  52. super.tearDown()
  53. }
  54. func testSuccessfulAuth() {
  55. let expectation = self.expectation(description: #function)
  56. setFetcherTestBlock(with: 200) { fetcher in
  57. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  58. }
  59. fetcher?.beginFetch { data, error in
  60. let headers = self.fetcher!.request?.allHTTPHeaderFields
  61. XCTAssertEqual(headers!["Authorization"], "Firebase \(self.StorageTestAuthToken)")
  62. expectation.fulfill()
  63. }
  64. waitForExpectation(test: self)
  65. }
  66. func testUnsuccessfulAuth() {
  67. let expectation = self.expectation(description: #function)
  68. let authError = NSError(domain: "FIRStorageErrorDomain",
  69. code: StorageErrorCode.unauthenticated.rawValue, userInfo: nil)
  70. let failedAuth = FIRAuthInteropFake(token: nil, userID: nil, error: authError)
  71. fetcher?.authorizer = StorageTokenAuthorizer(
  72. googleAppID: "dummyAppID",
  73. fetcherService: fetcherService!,
  74. authProvider: failedAuth,
  75. appCheck: nil
  76. )
  77. setFetcherTestBlock(with: 401) { fetcher in
  78. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  79. }
  80. fetcher?.beginFetch { data, error in
  81. let headers = self.fetcher!.request?.allHTTPHeaderFields
  82. XCTAssertNil(headers)
  83. let nsError = error as? NSError
  84. XCTAssertEqual(nsError?.domain, "FIRStorageErrorDomain")
  85. XCTAssertEqual(nsError?.code, StorageErrorCode.unauthenticated.rawValue)
  86. XCTAssertEqual(nsError?.localizedDescription, "User is not authenticated, please " +
  87. "authenticate using Firebase Authentication and try again.")
  88. expectation.fulfill()
  89. }
  90. waitForExpectation(test: self)
  91. }
  92. func testSuccessfulUnauthenticatedAuth() {
  93. let expectation = self.expectation(description: #function)
  94. // Simulate Auth not being included at all
  95. fetcher?.authorizer = StorageTokenAuthorizer(
  96. googleAppID: "dummyAppID",
  97. fetcherService: fetcherService!,
  98. authProvider: nil,
  99. appCheck: nil
  100. )
  101. setFetcherTestBlock(with: 200) { fetcher in
  102. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  103. }
  104. fetcher?.beginFetch { data, error in
  105. let headers = self.fetcher!.request?.allHTTPHeaderFields
  106. XCTAssertNil(headers!["Authorization"])
  107. XCTAssertNil(error)
  108. expectation.fulfill()
  109. }
  110. waitForExpectation(test: self)
  111. }
  112. func testSuccessfulAppCheckNoAuth() {
  113. let expectation = self.expectation(description: #function)
  114. appCheck?.tokenResult = appCheckTokenSuccess!
  115. // Simulate Auth not being included at all
  116. fetcher?.authorizer = StorageTokenAuthorizer(
  117. googleAppID: "dummyAppID",
  118. fetcherService: fetcherService!,
  119. authProvider: nil,
  120. appCheck: appCheck
  121. )
  122. setFetcherTestBlock(with: 200) { fetcher in
  123. self.checkAuthorizer(fetcher: fetcher, trueFalse: false)
  124. }
  125. fetcher?.beginFetch { data, error in
  126. let headers = self.fetcher!.request?.allHTTPHeaderFields
  127. XCTAssertEqual(headers!["X-Firebase-AppCheck"], self.appCheckTokenSuccess?.token)
  128. XCTAssertNil(error)
  129. expectation.fulfill()
  130. }
  131. waitForExpectation(test: self)
  132. }
  133. func testSuccessfulAppCheckAndAuth() {
  134. let expectation = self.expectation(description: #function)
  135. appCheck?.tokenResult = appCheckTokenSuccess!
  136. setFetcherTestBlock(with: 200) { fetcher in
  137. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  138. }
  139. fetcher?.beginFetch { data, error in
  140. let headers = self.fetcher!.request?.allHTTPHeaderFields
  141. XCTAssertEqual(headers!["Authorization"], "Firebase \(self.StorageTestAuthToken)")
  142. XCTAssertEqual(headers!["X-Firebase-AppCheck"], self.appCheckTokenSuccess?.token)
  143. XCTAssertNil(error)
  144. expectation.fulfill()
  145. }
  146. waitForExpectation(test: self)
  147. }
  148. func testAppCheckError() {
  149. let expectation = self.expectation(description: #function)
  150. appCheck?.tokenResult = appCheckTokenError!
  151. setFetcherTestBlock(with: 200) { fetcher in
  152. self.checkAuthorizer(fetcher: fetcher, trueFalse: true)
  153. }
  154. fetcher?.beginFetch { data, error in
  155. let headers = self.fetcher!.request?.allHTTPHeaderFields
  156. XCTAssertEqual(headers!["Authorization"], "Firebase \(self.StorageTestAuthToken)")
  157. XCTAssertEqual(headers!["X-Firebase-AppCheck"], self.appCheckTokenError?.token)
  158. XCTAssertNil(error)
  159. expectation.fulfill()
  160. }
  161. waitForExpectation(test: self)
  162. }
  163. func testIsAuthorizing() {
  164. let expectation = self.expectation(description: #function)
  165. setFetcherTestBlock(with: 200) { fetcher in
  166. do {
  167. let authorizer = try XCTUnwrap(fetcher.authorizer)
  168. XCTAssertFalse(authorizer.isAuthorizingRequest(fetcher.request!))
  169. } catch {
  170. XCTFail("Failed to get authorizer: \(error)")
  171. }
  172. }
  173. fetcher?.beginFetch { data, error in
  174. XCTAssertNil(error)
  175. expectation.fulfill()
  176. }
  177. waitForExpectation(test: self)
  178. }
  179. func testStopAuthorizingNoop() {
  180. let expectation = self.expectation(description: #function)
  181. setFetcherTestBlock(with: 200) { fetcher in
  182. do {
  183. let authorizer = try XCTUnwrap(fetcher.authorizer)
  184. // Since both of these are noops, we expect that invoking them
  185. // will still result in successful authenticatio
  186. authorizer.stopAuthorization()
  187. authorizer.stopAuthorization(for: fetcher.request!)
  188. } catch {
  189. XCTFail("Failed to get authorizer: \(error)")
  190. }
  191. }
  192. fetcher?.beginFetch { data, error in
  193. XCTAssertNil(error)
  194. let headers = self.fetcher!.request?.allHTTPHeaderFields
  195. XCTAssertEqual(headers!["Authorization"], "Firebase \(self.StorageTestAuthToken)")
  196. expectation.fulfill()
  197. }
  198. waitForExpectation(test: self)
  199. }
  200. func testEmail() {
  201. let expectation = self.expectation(description: #function)
  202. setFetcherTestBlock(with: 200) { fetcher in
  203. do {
  204. let authorizer = try XCTUnwrap(fetcher.authorizer)
  205. XCTAssertNil(authorizer.userEmail)
  206. } catch {
  207. XCTFail("Failed to get authorizer: \(error)")
  208. }
  209. }
  210. fetcher?.beginFetch { data, error in
  211. XCTAssertNil(error)
  212. expectation.fulfill()
  213. }
  214. waitForExpectation(test: self)
  215. }
  216. // MARK: Helpers
  217. private func setFetcherTestBlock(with statusCode: Int,
  218. _ validationBlock: @escaping (GTMSessionFetcher) -> Void) {
  219. fetcher?.testBlock = { (fetcher: GTMSessionFetcher,
  220. response: GTMSessionFetcherTestResponse) in
  221. validationBlock(fetcher)
  222. let httpResponse = HTTPURLResponse(url: (fetcher.request?.url)!,
  223. statusCode: statusCode,
  224. httpVersion: "HTTP/1.1",
  225. headerFields: nil)
  226. response(httpResponse, nil, nil)
  227. }
  228. }
  229. private func checkAuthorizer(fetcher: GTMSessionFetcher, trueFalse: Bool) {
  230. do {
  231. let authorizer = try XCTUnwrap(fetcher.authorizer)
  232. XCTAssertEqual(authorizer.isAuthorizedRequest(fetcher.request!), trueFalse)
  233. } catch {
  234. XCTFail("Failed to get authorizer: \(error)")
  235. }
  236. }
  237. }