FIRStorageTokenAuthorizerTests.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2017 Google
  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 "FirebaseStorage/Tests/Unit/FIRStorageTestHelpers.h"
  15. #import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
  16. #import "SharedTestUtilities/AppCheckFake/FIRAppCheckFake.h"
  17. #import "SharedTestUtilities/AppCheckFake/FIRAppCheckTokenResultFake.h"
  18. #import "SharedTestUtilities/FIRAuthInteropFake.h"
  19. @interface FIRStorageTokenAuthorizerTests : XCTestCase
  20. @property(strong, nonatomic) GTMSessionFetcher *fetcher;
  21. @property(strong, nonatomic) GTMSessionFetcherService *fetcherService;
  22. @property(strong, nonatomic) FIRAuthInteropFake *auth;
  23. @property(strong, nonatomic) FIRAppCheckFake *appCheck;
  24. @property(strong, nonatomic) FIRAppCheckTokenResultFake *appCheckTokenSuccess;
  25. @property(strong, nonatomic) FIRAppCheckTokenResultFake *appCheckTokenError;
  26. @end
  27. @implementation FIRStorageTokenAuthorizerTests
  28. - (void)setUp {
  29. [super setUp];
  30. self.appCheckTokenSuccess = [[FIRAppCheckTokenResultFake alloc] initWithToken:@"token" error:nil];
  31. self.appCheckTokenError = [[FIRAppCheckTokenResultFake alloc]
  32. initWithToken:@"dummy token"
  33. error:[NSError errorWithDomain:@"testAppCheckError" code:-1 userInfo:nil]];
  34. NSURLRequest *fetchRequest = [NSURLRequest requestWithURL:[FIRStorageTestHelpers objectURL]];
  35. self.fetcher = [GTMSessionFetcher fetcherWithRequest:fetchRequest];
  36. self.fetcherService = [[GTMSessionFetcherService alloc] init];
  37. self.auth = [[FIRAuthInteropFake alloc] initWithToken:kFIRStorageTestAuthToken
  38. userID:nil
  39. error:nil];
  40. self.appCheck = [[FIRAppCheckFake alloc] init];
  41. self.fetcher.authorizer =
  42. [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:@"dummyAppID"
  43. fetcherService:self.fetcherService
  44. authProvider:self.auth
  45. appCheck:self.appCheck];
  46. }
  47. - (void)tearDown {
  48. self.fetcher = nil;
  49. self.fetcherService = nil;
  50. self.auth = nil;
  51. self.appCheck = nil;
  52. self.appCheckTokenSuccess = nil;
  53. [super tearDown];
  54. }
  55. - (void)testSuccessfulAuth {
  56. XCTestExpectation *expectation = [self expectationWithDescription:@"testSuccessfulAuth"];
  57. [self setFetcherTestBlockWithStatusCode:200
  58. validationBlock:^(GTMSessionFetcher *fetcher) {
  59. XCTAssertTrue([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  60. }];
  61. [self.fetcher
  62. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  63. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  64. XCTAssertEqualObjects(headers[@"Authorization"], [self validAuthToken]);
  65. [expectation fulfill];
  66. }];
  67. [FIRStorageTestHelpers waitForExpectation:self];
  68. }
  69. - (void)testUnsuccessfulAuth {
  70. XCTestExpectation *expectation = [self expectationWithDescription:@"testUnsuccessfulAuth"];
  71. NSError *authError = [NSError errorWithDomain:FIRStorageErrorDomain
  72. code:FIRStorageErrorCodeUnauthenticated
  73. userInfo:nil];
  74. FIRAuthInteropFake *failedAuth = [[FIRAuthInteropFake alloc] initWithToken:nil
  75. userID:nil
  76. error:authError];
  77. self.fetcher.authorizer =
  78. [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:@"dummyAppID"
  79. fetcherService:self.fetcherService
  80. authProvider:failedAuth
  81. appCheck:nil];
  82. [self
  83. setFetcherTestBlockWithStatusCode:401
  84. validationBlock:^(GTMSessionFetcher *fetcher) {
  85. XCTAssertFalse([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  86. }];
  87. [self.fetcher
  88. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  89. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  90. NSString *authHeader = [headers objectForKey:@"Authorization"];
  91. XCTAssertNil(authHeader);
  92. XCTAssertEqualObjects(error.domain, FIRStorageErrorDomain);
  93. XCTAssertEqual(error.code, FIRStorageErrorCodeUnauthenticated);
  94. [expectation fulfill];
  95. }];
  96. [FIRStorageTestHelpers waitForExpectation:self];
  97. }
  98. - (void)testSuccessfulUnauthenticatedAuth {
  99. XCTestExpectation *expectation =
  100. [self expectationWithDescription:@"testSuccessfulUnauthenticatedAuth"];
  101. // Simulate Auth not being included at all.
  102. self.fetcher.authorizer =
  103. [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:@"dummyAppID"
  104. fetcherService:self.fetcherService
  105. authProvider:nil
  106. appCheck:nil];
  107. [self
  108. setFetcherTestBlockWithStatusCode:200
  109. validationBlock:^(GTMSessionFetcher *fetcher) {
  110. XCTAssertFalse([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  111. }];
  112. [self.fetcher
  113. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  114. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  115. NSString *authHeader = [headers objectForKey:@"Authorization"];
  116. XCTAssertNil(authHeader);
  117. XCTAssertNil(error);
  118. [expectation fulfill];
  119. }];
  120. [FIRStorageTestHelpers waitForExpectation:self];
  121. }
  122. - (void)testSuccessfulAppCheckNoAuth {
  123. self.appCheck.tokenResult = self.appCheckTokenSuccess;
  124. self.fetcher.authorizer =
  125. [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:@"dummyAppID"
  126. fetcherService:self.fetcherService
  127. authProvider:nil
  128. appCheck:self.appCheck];
  129. [self
  130. setFetcherTestBlockWithStatusCode:200
  131. validationBlock:^(GTMSessionFetcher *fetcher) {
  132. XCTAssertFalse([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  133. }];
  134. XCTestExpectation *expectation = [self expectationWithDescription:@"fetchCompletion"];
  135. [self.fetcher
  136. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  137. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  138. XCTAssertEqualObjects(headers[@"X-Firebase-AppCheck"], self.appCheckTokenSuccess.token);
  139. [expectation fulfill];
  140. }];
  141. [FIRStorageTestHelpers waitForExpectation:self];
  142. }
  143. - (void)testSuccessfulAppCheckAndAuth {
  144. self.appCheck.tokenResult = self.appCheckTokenSuccess;
  145. [self setFetcherTestBlockWithStatusCode:200
  146. validationBlock:^(GTMSessionFetcher *fetcher) {
  147. XCTAssertTrue([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  148. }];
  149. XCTestExpectation *expectation = [self expectationWithDescription:@"fetchCompletion"];
  150. [self.fetcher
  151. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  152. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  153. XCTAssertEqualObjects(headers[@"Authorization"], [self validAuthToken]);
  154. XCTAssertEqualObjects(headers[@"X-Firebase-AppCheck"], self.appCheckTokenSuccess.token);
  155. [expectation fulfill];
  156. }];
  157. [FIRStorageTestHelpers waitForExpectation:self];
  158. }
  159. - (void)testAppCheckError {
  160. self.appCheck.tokenResult = self.appCheckTokenError;
  161. [self setFetcherTestBlockWithStatusCode:200
  162. validationBlock:^(GTMSessionFetcher *fetcher) {
  163. XCTAssertTrue([fetcher.authorizer isAuthorizedRequest:fetcher.request]);
  164. }];
  165. XCTestExpectation *expectation = [self expectationWithDescription:@"fetchCompletion"];
  166. [self.fetcher
  167. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  168. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  169. XCTAssertEqualObjects(headers[@"Authorization"], [self validAuthToken]);
  170. XCTAssertEqualObjects(headers[@"X-Firebase-AppCheck"], self.appCheckTokenError.token);
  171. [expectation fulfill];
  172. }];
  173. [FIRStorageTestHelpers waitForExpectation:self];
  174. }
  175. - (void)testIsAuthorizing {
  176. XCTestExpectation *expectation = [self expectationWithDescription:@"testIsAuthorizing"];
  177. [self
  178. setFetcherTestBlockWithStatusCode:200
  179. validationBlock:^(GTMSessionFetcher *fetcher) {
  180. XCTAssertFalse([fetcher.authorizer isAuthorizingRequest:fetcher.request]);
  181. }];
  182. [self.fetcher
  183. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  184. [expectation fulfill];
  185. }];
  186. [FIRStorageTestHelpers waitForExpectation:self];
  187. }
  188. - (void)testStopAuthorizingNoop {
  189. XCTestExpectation *expectation = [self expectationWithDescription:@"testStopAuthorizingNoop"];
  190. [self setFetcherTestBlockWithStatusCode:200
  191. validationBlock:^(GTMSessionFetcher *fetcher) {
  192. // Since both of these are noops, we expect that invoking them
  193. // will still result in successful authentication
  194. [fetcher.authorizer stopAuthorization];
  195. [fetcher.authorizer stopAuthorizationForRequest:fetcher.request];
  196. }];
  197. [self.fetcher
  198. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  199. NSDictionary<NSString *, NSString *> *headers = self.fetcher.request.allHTTPHeaderFields;
  200. NSString *authHeader = [headers objectForKey:@"Authorization"];
  201. NSString *firebaseToken =
  202. [NSString stringWithFormat:kFIRStorageAuthTokenFormat, kFIRStorageTestAuthToken];
  203. XCTAssertEqualObjects(authHeader, firebaseToken);
  204. [expectation fulfill];
  205. }];
  206. [FIRStorageTestHelpers waitForExpectation:self];
  207. }
  208. - (void)testEmail {
  209. XCTestExpectation *expectation = [self expectationWithDescription:@"testEmail"];
  210. [self setFetcherTestBlockWithStatusCode:200
  211. validationBlock:^(GTMSessionFetcher *fetcher) {
  212. XCTAssertNil([fetcher.authorizer userEmail]);
  213. }];
  214. [self.fetcher
  215. beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) {
  216. [expectation fulfill];
  217. }];
  218. [FIRStorageTestHelpers waitForExpectation:self];
  219. }
  220. #pragma mark - Helpers
  221. - (void)setFetcherTestBlockWithStatusCode:(NSUInteger)httpStatusCode
  222. validationBlock:(void (^)(GTMSessionFetcher *fetcher))validationBlock {
  223. self.fetcher.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) {
  224. validationBlock(fetcher);
  225. NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL
  226. statusCode:httpStatusCode
  227. HTTPVersion:kHTTPVersion
  228. headerFields:nil];
  229. response(httpResponse, nil, nil);
  230. };
  231. }
  232. - (NSString *)validAuthToken {
  233. return [NSString stringWithFormat:kFIRStorageAuthTokenFormat, kFIRStorageTestAuthToken];
  234. }
  235. @end