GIDAuthStateMigrationTest.m 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright 2021 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 <XCTest/XCTest.h>
  15. #import "GoogleSignIn/Sources/GIDAuthStateMigration.h"
  16. #import "GoogleSignIn/Sources/GIDSignInCallbackSchemes.h"
  17. #ifdef SWIFT_PACKAGE
  18. @import AppAuth;
  19. @import GTMAppAuth;
  20. @import OCMock;
  21. #else
  22. #import <AppAuth/AppAuth.h>
  23. #import <GTMAppAuth/GTMAppAuthFetcherAuthorization+Keychain.h>
  24. #import <GTMAppAuth/GTMKeychain.h>
  25. #import <GTMAppAuth/GTMOAuth2KeychainCompatibility.h>
  26. #import <OCMock/OCMock.h>
  27. #endif
  28. static NSString *const kTokenURL = @"https://host.com/example/token/url";
  29. static NSString *const kCallbackPath = @"/callback/path";
  30. static NSString *const kKeychainName = @"keychain_name";
  31. static NSString *const kBundleID = @"com.google.GoogleSignInInternalSample.dev";
  32. static NSString *const kClientID =
  33. @"223520599684-kg64hfn0h950oureqacja2fltg00msv3.apps.googleusercontent.com";
  34. static NSString *const kDotReversedClientID =
  35. @"com.googleusercontent.apps.223520599684-kg64hfn0h950oureqacja2fltg00msv3";
  36. static NSString *const kSavedFingerprint = @"com.google.GoogleSignInInternalSample.dev-"
  37. "223520599684-kg64hfn0h950oureqacja2fltg00msv3.apps.googleusercontent.com-email profile";
  38. static NSString *const kSavedFingerprint_HostedDomain =
  39. @"com.google.GoogleSignInInternalSample.dev-"
  40. "223520599684-kg64hfn0h950oureqacja2fltg00msv3.apps.googleusercontent.com-email profile-"
  41. "hd=test.com";
  42. static NSString *const kGTMOAuth2PersistenceString = @"param1=value1&param2=value2";
  43. static NSString *const kAdditionalTokenRequestParametersPostfix = @"~~atrp";
  44. static NSString *const kAdditionalTokenRequestParameters = @"param3=value3&param4=value4";
  45. static NSString *const kFinalPersistenceString =
  46. @"param1=value1&param2=value2&param3=value3&param4=value4";
  47. static NSString *const kRedirectURI =
  48. @"com.googleusercontent.apps.223520599684-kg64hfn0h950oureqacja2fltg00msv3:/callback/path";
  49. static NSString *const kMigrationCheckPerformedKey = @"GID_MigrationCheckPerformed";
  50. static NSString *const kFingerprintService = @"fingerprint";
  51. NS_ASSUME_NONNULL_BEGIN
  52. @interface GIDAuthStateMigration ()
  53. + (nullable GTMAppAuthFetcherAuthorization *)
  54. extractAuthorizationWithTokenURL:(NSURL *)tokenURL callbackPath:(NSString *)callbackPath;
  55. + (nullable NSString *)passwordForService:(NSString *)service;
  56. @end
  57. @interface GIDAuthStateMigrationTest : XCTestCase
  58. @end
  59. @implementation GIDAuthStateMigrationTest {
  60. id _mockUserDefaults;
  61. id _mockGTMAppAuthFetcherAuthorization;
  62. id _mockGIDAuthStateMigration;
  63. id _mockGTMKeychain;
  64. id _mockNSBundle;
  65. id _mockGIDSignInCallbackSchemes;
  66. id _mockGTMOAuth2KeychainCompatibility;
  67. }
  68. - (void)setUp {
  69. [super setUp];
  70. _mockUserDefaults = OCMStrictClassMock([NSUserDefaults class]);
  71. _mockGTMAppAuthFetcherAuthorization = OCMStrictClassMock([GTMAppAuthFetcherAuthorization class]);
  72. _mockGIDAuthStateMigration = OCMStrictClassMock([GIDAuthStateMigration class]);
  73. _mockGTMKeychain = OCMStrictClassMock([GTMKeychain class]);
  74. _mockNSBundle = OCMStrictClassMock([NSBundle class]);
  75. _mockGIDSignInCallbackSchemes = OCMStrictClassMock([GIDSignInCallbackSchemes class]);
  76. _mockGTMOAuth2KeychainCompatibility = OCMStrictClassMock([GTMOAuth2KeychainCompatibility class]);
  77. }
  78. - (void)tearDown {
  79. [_mockUserDefaults verify];
  80. [_mockUserDefaults stopMocking];
  81. [_mockGTMAppAuthFetcherAuthorization verify];
  82. [_mockGTMAppAuthFetcherAuthorization stopMocking];
  83. [_mockGIDAuthStateMigration verify];
  84. [_mockGIDAuthStateMigration stopMocking];
  85. [_mockGTMKeychain verify];
  86. [_mockGTMKeychain stopMocking];
  87. [_mockNSBundle verify];
  88. [_mockNSBundle stopMocking];
  89. [_mockGIDSignInCallbackSchemes verify];
  90. [_mockGIDSignInCallbackSchemes stopMocking];
  91. [_mockGTMOAuth2KeychainCompatibility verify];
  92. [_mockGTMOAuth2KeychainCompatibility stopMocking];
  93. [super tearDown];
  94. }
  95. #pragma mark - Tests
  96. - (void)testMigrateIfNeeded_NoPreviousMigration {
  97. [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults];
  98. [[[_mockUserDefaults expect] andReturnValue:@NO]
  99. boolForKey:kMigrationCheckPerformedKey];
  100. [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization]
  101. extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath];
  102. [[[_mockGTMAppAuthFetcherAuthorization expect] andReturnValue:@YES]
  103. saveAuthorization:_mockGTMAppAuthFetcherAuthorization toKeychainForName:kKeychainName];
  104. [[_mockUserDefaults expect] setBool:YES forKey:kMigrationCheckPerformedKey];
  105. [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL]
  106. callbackPath:kCallbackPath
  107. keychainName:kKeychainName
  108. isFreshInstall:NO];
  109. }
  110. - (void)testMigrateIfNeeded_HasPreviousMigration {
  111. [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults];
  112. [[[_mockUserDefaults expect] andReturnValue:@YES]
  113. boolForKey:kMigrationCheckPerformedKey];
  114. [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL]
  115. callbackPath:kCallbackPath
  116. keychainName:kKeychainName
  117. isFreshInstall:NO];
  118. }
  119. - (void)testMigrateIfNeeded_KeychainFailure {
  120. [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults];
  121. [[[_mockUserDefaults expect] andReturnValue:@NO]
  122. boolForKey:kMigrationCheckPerformedKey];
  123. [[[_mockGIDAuthStateMigration expect] andReturn:_mockGTMAppAuthFetcherAuthorization]
  124. extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL] callbackPath:kCallbackPath];
  125. [[[_mockGTMAppAuthFetcherAuthorization expect] andReturnValue:[NSNumber numberWithBool:NO]]
  126. saveAuthorization:_mockGTMAppAuthFetcherAuthorization toKeychainForName:kKeychainName];
  127. [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL]
  128. callbackPath:kCallbackPath
  129. keychainName:kKeychainName
  130. isFreshInstall:NO];
  131. }
  132. - (void)testMigrateIfNeeded_isFreshInstall {
  133. [[[_mockUserDefaults stub] andReturn:_mockUserDefaults] standardUserDefaults];
  134. [[[_mockUserDefaults expect] andReturnValue:@NO]
  135. boolForKey:kMigrationCheckPerformedKey];
  136. [[_mockUserDefaults expect] setBool:YES forKey:kMigrationCheckPerformedKey];
  137. [GIDAuthStateMigration migrateIfNeededWithTokenURL:[NSURL URLWithString:kTokenURL]
  138. callbackPath:kCallbackPath
  139. keychainName:kKeychainName
  140. isFreshInstall:YES];
  141. }
  142. - (void)testExtractAuthorization {
  143. [self extractAuthorizationWithFingerprint:kSavedFingerprint];
  144. }
  145. - (void)testExtractAuthorization_HostedDomain {
  146. [self extractAuthorizationWithFingerprint:kSavedFingerprint_HostedDomain];
  147. }
  148. #pragma mark - Helpers
  149. // Generate the service name for the stored additional token request parameters string.
  150. - (NSString *)additionalTokenRequestParametersKeyFromFingerprint:(NSString *)fingerprint {
  151. return [NSString stringWithFormat:@"%@%@", fingerprint, kAdditionalTokenRequestParametersPostfix];
  152. }
  153. // The parameterized extractAuthorization test.
  154. - (void)extractAuthorizationWithFingerprint:(NSString *)fingerprint {
  155. [[[_mockGIDAuthStateMigration expect] andReturn:fingerprint]
  156. passwordForService:kFingerprintService];
  157. [[[_mockGTMKeychain expect] andReturn:kGTMOAuth2PersistenceString]
  158. passwordFromKeychainForName:fingerprint];
  159. [[[_mockNSBundle expect] andReturn:_mockNSBundle] mainBundle];
  160. [[[_mockNSBundle expect] andReturn:kBundleID] bundleIdentifier];
  161. [[[_mockGIDSignInCallbackSchemes expect] andReturn:_mockGIDSignInCallbackSchemes] alloc];
  162. (void)[[[_mockGIDSignInCallbackSchemes expect] andReturn:_mockGIDSignInCallbackSchemes]
  163. initWithClientIdentifier:kClientID];
  164. [[[_mockGIDSignInCallbackSchemes expect] andReturn:kDotReversedClientID] clientIdentifierScheme];
  165. [[[_mockGIDAuthStateMigration expect] andReturn:kAdditionalTokenRequestParameters]
  166. passwordForService:[self additionalTokenRequestParametersKeyFromFingerprint:fingerprint]];
  167. [[[_mockGTMOAuth2KeychainCompatibility expect] andReturn:_mockGTMAppAuthFetcherAuthorization]
  168. authorizeFromPersistenceString:kFinalPersistenceString
  169. tokenURL:[NSURL URLWithString:kTokenURL]
  170. redirectURI:kRedirectURI
  171. clientID:kClientID
  172. clientSecret:nil];
  173. GTMAppAuthFetcherAuthorization *authorization =
  174. [GIDAuthStateMigration extractAuthorizationWithTokenURL:[NSURL URLWithString:kTokenURL]
  175. callbackPath:kCallbackPath];
  176. XCTAssertNotNil(authorization);
  177. }
  178. @end
  179. NS_ASSUME_NONNULL_END