1
votes

I am requesting access to the user's data from an IOS app using this code from the GoogleSignIn pod

 [GIDSignIn sharedInstance].uiDelegate = self;
 [[GIDSignIn sharedInstance] setScopes:@[ ... ];
 [[GIDSignIn sharedInstance] signInSilently];

I then receive the accessToken and the refreshToken in the appDelegate and I send that to the server running PHP and using this google client library (https://github.com/googleapis/google-api-php-client) ... for the first hour everything is working fine and the access token is valid and allowing me access to all the scopes. Then after an hour the access token expires and I try to refresh it using this code

$client = new Google_Client();
$client->setApplicationName(<app name>);
$client->setDeveloperKey(<google_oauth_developer_key>);
$client->setClientSecret(<google_oauth_client_secret>);
$client->setClientId(<google_oauth_client_id>);
$client->refreshToken("1/12ju3ZZim-r6co195lIVNNvzBq9x5G64GJCWkYsOQ18");

and the "refreshToken" function above returns this error

=> [
     "error" => "unauthorized_client",
     "error_description" => "Unauthorized",
   ]

It's worth noting that the app name, google_oauth_developer_key, google_oauth_client_secret, and google_oauth_client_id have not changed. They are the same ones that were working earlier to retrieve the user's contacts, calendar events, etc when the access token was not yet expired.

What could be causing this error?

2

2 Answers

1
votes

You need to actually use your refresh token at some point.

if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        $client->getAccessToken();

Code ripped from my Oauth2Authentication.php sample

Note

Also remember that refresh tokens are user / client based. So if the token was generated by one client then a different client will probably not be able to use it. I will be very surprised if you can use a refresh token created in Ios code in a php application. The client types are different.

0
votes

Ok so I figured out what I did wrong. I originally followed these instructions https://developers.google.com/identity/sign-in/ios/sign-in which assume you need online access only, but I actually need offline access to the scopes so I followed these instructions https://developers.google.com/identity/sign-in/ios/offline-access and it works now. So instead of having the IOS app send up the access token and the refresh token separately like this

- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
     withError:(NSError *)error {

    if (!error) {
        NSString *accessToken = user.authentication.accessToken;
        NSString *refreshToken = user.authentication.refreshToken;

I simply have it send up the serverAuthCode like this

- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
     withError:(NSError *)error {

      if (!error) {
        NSString *serverAuthCode = user.serverAuthCode;

and then on the server I run this code to get the access token

$access_token = $client->authenticate($google_server_auth_code);
$client->setAccessToken($access_token);

and then when the access token expires I run this to refresh it

$access_token = $client->refreshToken($client->getRefreshToken());
$client->setAccessToken($access_token);