StorageAuthorizerTests.swift 9.3 KB

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