GIDDecodeIDTokenOperation.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. //
  2. // GIDDecodeIDTokenOperation.m
  3. // GoogleSignIn
  4. //
  5. // Created by Matt Mathias on 4/3/25.
  6. //
  7. #import "GIDDecodeIDTokenOperation.h"
  8. #import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDProfileData.h"
  9. #import "GoogleSignIn/Sources/GIDAuthorizationFlow/Implementations/Operations/GIDTokenFetchOperation.h"
  10. #import "GoogleSignIn/Sources/GIDProfileData_Private.h"
  11. #import "GoogleSignIn/Sources/GIDSignInConstants.h"
  12. #import "GoogleSignIn/Sources/GIDSignInPreferences.h"
  13. #ifdef SWIFT_PACKAGE
  14. @import AppAuth;
  15. @import GTMAppAuth;
  16. #else
  17. #import <AppAuth/OIDAuthState.h>
  18. #import <GTMAppAuth/GTMAuthSession>
  19. #endif
  20. @interface GIDDecodeIDTokenOperation ()
  21. @property(nonatomic, readwrite, nullable) GIDProfileData *profileData;
  22. @property(nonatomic, readwrite, nullable) NSError *error;
  23. @end
  24. @implementation GIDDecodeIDTokenOperation
  25. - (void)main {
  26. GIDTokenFetchOperation *tokenFetch = (GIDTokenFetchOperation *)self.dependencies.firstObject;
  27. OIDAuthState *authState = tokenFetch.authState;
  28. NSError *maybeError = tokenFetch.error;
  29. if (!authState || maybeError) {
  30. return;
  31. }
  32. OIDIDToken *idToken =
  33. [[OIDIDToken alloc] initWithIDTokenString: authState.lastTokenResponse.idToken];
  34. // If the profile data are present in the ID token, use them.
  35. if (idToken) {
  36. self.profileData = [self profileDataWithIDToken:idToken];
  37. }
  38. // If we can't retrieve profile data from the ID token, make a userInfo request to fetch them.
  39. if (self.profileData) {
  40. NSURL *infoURL = [NSURL URLWithString:
  41. [NSString stringWithFormat:kUserInfoURLTemplate,
  42. [GIDSignInPreferences googleUserInfoServer],
  43. authState.lastTokenResponse.accessToken]];
  44. [self startFetchURL:infoURL
  45. fromAuthState:authState
  46. withComment:@"GIDSignIn: fetch basic profile info"
  47. withCompletionHandler:^(NSData *data, NSError *error) {
  48. if (data && !error) {
  49. NSError *jsonDeserializationError;
  50. NSDictionary<NSString *, NSString *> *profileDict =
  51. [NSJSONSerialization JSONObjectWithData:data
  52. options:NSJSONReadingMutableContainers
  53. error:&jsonDeserializationError];
  54. if (profileDict) {
  55. self.profileData = [[GIDProfileData alloc]
  56. initWithEmail:idToken.claims[kBasicProfileEmailKey]
  57. name:profileDict[kBasicProfileNameKey]
  58. givenName:profileDict[kBasicProfileGivenNameKey]
  59. familyName:profileDict[kBasicProfileFamilyNameKey]
  60. imageURL:[NSURL URLWithString:profileDict[kBasicProfilePictureKey]]];
  61. }
  62. }
  63. if (error) {
  64. self.error = error;
  65. }
  66. }];
  67. }
  68. }
  69. - (GIDProfileData *)profileDataWithIDToken:(OIDIDToken *)idToken {
  70. if (!idToken ||
  71. !idToken.claims[kBasicProfilePictureKey] ||
  72. !idToken.claims[kBasicProfileNameKey] ||
  73. !idToken.claims[kBasicProfileGivenNameKey] ||
  74. !idToken.claims[kBasicProfileFamilyNameKey]) {
  75. return nil;
  76. }
  77. return [[GIDProfileData alloc]
  78. initWithEmail:idToken.claims[kBasicProfileEmailKey]
  79. name:idToken.claims[kBasicProfileNameKey]
  80. givenName:idToken.claims[kBasicProfileGivenNameKey]
  81. familyName:idToken.claims[kBasicProfileFamilyNameKey]
  82. imageURL:[NSURL URLWithString:idToken.claims[kBasicProfilePictureKey]]];
  83. }
  84. - (void)startFetchURL:(NSURL *)URL
  85. fromAuthState:(OIDAuthState *)authState
  86. withComment:(NSString *)comment
  87. withCompletionHandler:(void (^)(NSData *, NSError *))handler {
  88. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  89. GTMSessionFetcher *fetcher;
  90. GTMAuthSession *authorization = [[GTMAuthSession alloc] initWithAuthState:authState];
  91. id<GTMSessionFetcherServiceProtocol> fetcherService = authorization.fetcherService;
  92. if (fetcherService) {
  93. fetcher = [fetcherService fetcherWithRequest:request];
  94. } else {
  95. fetcher = [GTMSessionFetcher fetcherWithRequest:request];
  96. }
  97. fetcher.retryEnabled = YES;
  98. fetcher.maxRetryInterval = kFetcherMaxRetryInterval;
  99. fetcher.comment = comment;
  100. [fetcher beginFetchWithCompletionHandler:handler];
  101. }
  102. @end