GIDEMMSupport.m 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright 2022 Google LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <TargetConditionals.h>
  17. #if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
  18. #import "GoogleSignIn/Sources/GIDEMMSupport.h"
  19. #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h"
  20. #import "GoogleSignIn/Sources/GIDEMMErrorHandler.h"
  21. #import "GoogleSignIn/Sources/GIDMDMPasscodeState.h"
  22. #ifdef SWIFT_PACKAGE
  23. @import AppAuth;
  24. #else
  25. #import <AppAuth/AppAuth.h>
  26. #endif
  27. NS_ASSUME_NONNULL_BEGIN
  28. // Additional parameter names for EMM.
  29. static NSString *const kEMMSupportParameterName = @"emm_support";
  30. static NSString *const kEMMOSVersionParameterName = @"device_os";
  31. static NSString *const kEMMPasscodeInfoParameterName = @"emm_passcode_info";
  32. // Old UIDevice system name for iOS.
  33. static NSString *const kOldIOSSystemName = @"iPhone OS";
  34. // New UIDevice system name for iOS.
  35. static NSString *const kNewIOSSystemName = @"iOS";
  36. // The error key in the server response.
  37. static NSString *const kErrorKey = @"error";
  38. // Optional separator between error prefix and the payload.
  39. static NSString *const kErrorPayloadSeparator = @":";
  40. // A list for recognized error codes.
  41. typedef NS_ENUM(NSInteger, ErrorCode) {
  42. ErrorCodeNone = 0,
  43. ErrorCodeDeviceNotCompliant,
  44. ErrorCodeScreenlockRequired,
  45. ErrorCodeAppVerificationRequired,
  46. };
  47. @implementation GIDEMMSupport
  48. - (instancetype)init {
  49. return [super init];
  50. }
  51. + (void)handleTokenFetchEMMError:(nullable NSError *)error
  52. completion:(void (^)(NSError *_Nullable))completion {
  53. NSDictionary *errorJSON = error.userInfo[OIDOAuthErrorResponseErrorKey];
  54. if (errorJSON) {
  55. __block BOOL handled = NO;
  56. handled = [[GIDEMMErrorHandler sharedInstance] handleErrorFromResponse:errorJSON
  57. completion:^() {
  58. if (handled) {
  59. completion([NSError errorWithDomain:kGIDSignInErrorDomain
  60. code:kGIDSignInErrorCodeEMM
  61. userInfo:error.userInfo]);
  62. } else {
  63. completion(error);
  64. }
  65. }];
  66. } else {
  67. completion(error);
  68. }
  69. }
  70. + (NSDictionary<NSString *,NSString *> *)updatedEMMParametersWithParameters:
  71. (NSDictionary *)parameters {
  72. return [self parametersWithParameters:parameters
  73. emmSupport:parameters[kEMMSupportParameterName]
  74. isPasscodeInfoRequired:parameters[kEMMPasscodeInfoParameterName] != nil];
  75. }
  76. + (NSDictionary<NSString *,NSString *> *)parametersWithParameters:(NSDictionary *)parameters
  77. emmSupport:(nullable NSString *)emmSupport
  78. isPasscodeInfoRequired:(BOOL)isPasscodeInfoRequired {
  79. if (!emmSupport) {
  80. return parameters;
  81. }
  82. NSMutableDictionary *allParameters = [(parameters ?: @{}) mutableCopy];
  83. allParameters[kEMMSupportParameterName] = emmSupport;
  84. UIDevice *device = [UIDevice currentDevice];
  85. NSString *systemName = device.systemName;
  86. if ([systemName isEqualToString:kOldIOSSystemName]) {
  87. systemName = kNewIOSSystemName;
  88. }
  89. allParameters[kEMMOSVersionParameterName] =
  90. [NSString stringWithFormat:@"%@ %@", systemName, device.systemVersion];
  91. if (isPasscodeInfoRequired) {
  92. allParameters[kEMMPasscodeInfoParameterName] = [GIDMDMPasscodeState passcodeState].info;
  93. }
  94. return [GIDEMMSupport dictionaryWithStringValuesFromDictionary:allParameters];
  95. }
  96. #pragma mark - GTMAuthSessionDelegate
  97. - (nullable NSDictionary<NSString *,NSString *> *)
  98. additionalTokenRefreshParametersForAuthSession:(GTMAuthSession *)authSession {
  99. return [GIDEMMSupport updatedEMMParametersWithParameters:
  100. authSession.authState.lastTokenResponse.additionalParameters];
  101. }
  102. - (void)updateErrorForAuthSession:(GTMAuthSession *)authSession
  103. originalError:(NSError *)originalError
  104. completion:(void (^)(NSError * _Nullable))completion {
  105. [GIDEMMSupport handleTokenFetchEMMError:originalError completion:^(NSError *_Nullable error) {
  106. completion(error);
  107. }];
  108. }
  109. #pragma mark - Private Helpers
  110. + (NSDictionary<NSString *, NSString *> *)
  111. dictionaryWithStringValuesFromDictionary:(NSDictionary *)originalDictionary {
  112. NSMutableDictionary<NSString *, NSString *> *stringifiedDictionary =
  113. [NSMutableDictionary dictionaryWithCapacity:originalDictionary.count];
  114. [originalDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
  115. if ([value isKindOfClass:[NSString class]]) {
  116. stringifiedDictionary[key] = value;
  117. return;
  118. }
  119. if ([value isKindOfClass:[NSNumber class]]) {
  120. if (CFGetTypeID((__bridge CFTypeRef)value) == CFBooleanGetTypeID()) {
  121. stringifiedDictionary[key] = [value boolValue] ? @"true" : @"false";
  122. } else {
  123. stringifiedDictionary[key] = [value stringValue];
  124. }
  125. return;
  126. }
  127. }];
  128. return stringifiedDictionary;
  129. }
  130. @end
  131. NS_ASSUME_NONNULL_END
  132. #endif // TARGET_OS_IOS && !TARGET_OS_MACCATALYST