Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 38 additions & 20 deletions GoogleSignIn/Sources/GIDSignIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,20 @@
// The URL template for the token endpoint.
static NSString *const kTokenURLTemplate = @"https://%@/token";

// The URL template for the URL to get user info.
static NSString *const kUserInfoURLTemplate = @"https://%@/oauth2/v3/userinfo?access_token=%@";
// The path for the endpoint to get user info.
static NSString *const kUserInfoPath = @"/oauth2/v3/userinfo";

// The URL template for the URL to revoke the token.
static NSString *const kRevokeTokenURLTemplate = @"https://%@/o/oauth2/revoke?token=%@";
// The name of the query parameter carrying the access token for the user info request.
static NSString *const kAccessTokenParameter = @"access_token";

// The path for the endpoint to revoke the token.
static NSString *const kRevokeTokenPath = @"/o/oauth2/revoke";

// The name of the query parameter carrying the token to be revoked.
static NSString *const kRevokeTokenParameter = @"token";

// The scheme used for requests to Google's servers.
static NSString *const kHTTPSScheme = @"https";

// Expected path in the URL scheme to be handled.
static NSString *const kBrowserCallbackPath = @"/oauth2callback";
Expand Down Expand Up @@ -573,17 +582,22 @@ - (void)disconnectWithCompletion:(nullable GIDDisconnectCompletion)completion {
}
return;
}
NSString *revokeURLString = [NSString stringWithFormat:kRevokeTokenURLTemplate,
[GIDSignInPreferences googleAuthorizationServer], token];
// Append logging parameter
revokeURLString = [NSString stringWithFormat:@"%@&%@=%@&%@=%@",
revokeURLString,
kSDKVersionLoggingParameter,
[GIDSignInPreferences sdkVersion],
kEnvironmentLoggingParameter,
[GIDSignInPreferences environment]];
NSURL *revokeURL = [NSURL URLWithString:revokeURLString];
[self startFetchURL:revokeURL
NSURLComponents *revokeURLComponents = [[NSURLComponents alloc] init];
revokeURLComponents.scheme = kHTTPSScheme;
revokeURLComponents.host = [GIDSignInPreferences googleAuthorizationServer];
revokeURLComponents.path = kRevokeTokenPath;

NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray array];
[queryItems addObject:[NSURLQueryItem queryItemWithName:kRevokeTokenParameter value:token]];
NSDictionary<NSString *, NSString *> *loggingParameters =
[GIDSignInPreferences loggingParameters];
for (NSString *name in [loggingParameters.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:name
value:loggingParameters[name]]];
}
revokeURLComponents.queryItems = queryItems;

[self startFetchURL:revokeURLComponents.URL
fromAuthState:authState
withComment:@"GIDSignIn: revoke tokens"
withCompletionHandler:^(NSData *data, NSError *error) {
Expand Down Expand Up @@ -1135,11 +1149,15 @@ - (void)addDecodeIdTokenCallback:(GIDAuthFlow *)authFlow {
// If we can't retrieve profile data from the ID token, make a userInfo request to fetch them.
if (!handlerAuthFlow.profileData) {
[handlerAuthFlow wait];
NSURL *infoURL = [NSURL URLWithString:
[NSString stringWithFormat:kUserInfoURLTemplate,
[GIDSignInPreferences googleUserInfoServer],
authState.lastTokenResponse.accessToken]];
[self startFetchURL:infoURL
NSURLComponents *infoURLComponents = [[NSURLComponents alloc] init];
infoURLComponents.scheme = kHTTPSScheme;
infoURLComponents.host = [GIDSignInPreferences googleUserInfoServer];
infoURLComponents.path = kUserInfoPath;
infoURLComponents.queryItems = @[
[NSURLQueryItem queryItemWithName:kAccessTokenParameter
value:authState.lastTokenResponse.accessToken],
];
[self startFetchURL:infoURLComponents.URL
fromAuthState:authState
withComment:@"GIDSignIn: fetch basic profile info"
withCompletionHandler:^(NSData *data, NSError *error) {
Expand Down
17 changes: 17 additions & 0 deletions GoogleSignIn/Tests/Unit/GIDSignInTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,23 @@ - (void)testDisconnectNoCallback_accessToken {
[_tokenResponse verify];
}

// Verifies a token containing characters that are reserved in a URL query is percent-encoded
// in the revoke URL, so that it arrives at the server intact.
- (void)testDisconnectNoCallback_tokenWithReservedCharacters {
NSString *tokenWithReservedCharacters = @"token&with=reserved#characters";
[[[_authorization expect] andReturn:_authState] authState];
[[[_authState expect] andReturn:_tokenResponse] lastTokenResponse];
[[[_tokenResponse expect] andReturn:tokenWithReservedCharacters] accessToken];
[[[_authorization expect] andReturn:_fetcherService] fetcherService];
[_signIn disconnectWithCompletion:nil];
[self verifyAndRevokeToken:tokenWithReservedCharacters
hasCallback:NO
waitingForExpectations:@[]];
[_authorization verify];
[_authState verify];
[_tokenResponse verify];
}

// Verifies disconnect calls callback with no errors if refresh token is present.
- (void)testDisconnect_refreshToken {
[[[_authorization expect] andReturn:_authState] authState];
Expand Down
Loading