Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google plus cross site identity Android to PHP access token

I have a client and server app that needs to access a users g+ profile after on the SERVER side once they've validated on the client (android)

I'm gettin an ID token on the client side by this

@Background
void getAccessToken() {


    String scopes = "audience:server:client_id:xxxxxxxxxxxxx.apps.googleusercontent.com";

    Log.d(TAG,scopes);

    try {

        accessToken = GoogleAuthUtil.getToken(this,mPlusClient.getAccountName(),scopes);

        Log.d(TAG,accessToken);

        getPlusFriends();

    }
    catch (IOException transientEx) {
        Log.e(TAG, transientEx.getMessage());
        return;
    }
    catch (UserRecoverableAuthException e) {
        Log.e(TAG, e.getMessage());
        accessToken = null;
    }
    catch (GoogleAuthException authEx) {
        Log.e(TAG, authEx.getMessage());

        return;
    }
    catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Which will give me a long ID token as described in this blog http://www.tbray.org/ongoing/When/201x/2013/04/04/ID-Tokens

I think I'm supposed to send that token to my server where I need to do something to turn it into an access_token. I can verify that the id token? is good by sending a curl request to

https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=

which gives back a json string like this

{
"issuer": "accounts.google.com",
"issued_to": "xxxxxxxxxxxxxx.apps.googleusercontent.com",
"audience": "xxxxxxxxxxxxxx.apps.googleusercontent.com",
"user_id": "123456",
"expires_in": 3362,
"issued_at": 1382577073,
"email": "myemail@something",
"verified_email": true
}

php server

\Config::load('google_api', 'google');

 $key = Config::get('google.client_id');
 $secret = Config::get('google.client_secret');
 $scopes = Config::get('google.scopes');

 $client = new Google_Client();

 $client->setClientId($key);
 $client->setClientSecret($secret);
 $client->setScopes($scopes);
 $client->setState('offline');
 $client->authenticate($token);

where the issued_to is my client id for the Android app in the Google APIs console and the audience is the client is of my web app, seems right so far I think.

So now I'm using the php client and not really sure what to do from there. I tried to validate the api client using the id token but I just get the error 400 - Error fetching OAuth2 access token, message: 'invalid_grant'

I'm not sure if I'm supposed to try to authenticate the PHP Google+ client using that ID token or some how exchange it for an access token

like image 216
Brian Avatar asked Oct 24 '13 02:10

Brian


People also ask

How do I get my Google ID token?

An ID token is available when a Credential object's user ID matches the user ID of a Google account that is signed in on the device. To sign in with an ID token, first retrieve the ID token with the getIdTokens method. Then, send the ID token to your app's backend.

What is Id_token Google OAuth?

The id_token is used in OpenID Connect protocol, where the user is authenticated as well as authorized. (There's an important distinction between authentication and authorization.) You will get id_token and access_token. The id_token value contains the information about the user's authentication.


1 Answers

Did you read the Server-side access for your app documentation?

What you need is a one-time authorization code that you pass to your server and the server exchanges that authorization code for its own access and refresh tokens. The ID tokens are useful for verifying that the app and user are who they say they are, but not for getting your server access to data.

Your code is close, but is missing some key parts to make this work, such as specifying the app activity types that your app initially requested in the PlusClient configuration, and your scopes string needs a change.

Taken from the docs:

Bundle appActivities = new Bundle();
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
          "<app-activity1> <app-activity2>");
String scopes = "oauth2:server:client_id:<server client-id>:api_scope:<scope1> <scope2>";
String code = null;
try {
  code = GoogleAuthUtil.getToken(
    this,                             // Context context
    mPlusClient.getAccountName(),     // String accountName
    scopes,                           // String scope
    appActivities                     // Bundle bundle
  );

} catch (IOException transientEx) {
  // network or server error, the call is expected to succeed if you try again later.
  // Don't attempt to call again immediately - the request is likely to
  // fail, you'll hit quotas or back-off.
  ...
  return;
} catch (UserRecoverableAuthException e) {
  // Recover
  code = null;
} catch (GoogleAuthException authEx) {
  // Failure. The call is not expected to ever succeed so it should not be
  // retried.
  ...
  return;
} catch (Exception e) {
  throw new RuntimeException(e);
}

The code that you get back, you pass to your server. See line 98 in the PHP quick-start for how to perform the code exchange (and other steps like verifying the ID) using the PHP client library. You'll also need to configure your PHP client for offline access. The basics are:

$client = new apiClient();
$client->setClientId('From APIs console');
$client->setClientSecret('From APIs console');
$client->setScopes('exact same list of scopes as Android app, space separated');
$client->setRedirectUri('postmessage');  // Used in hybrid flows
$client->setState('offline');
// Exchange authorization code for access and refresh tokens
$client->authenticate($code);
$token = json_decode($client->getAccessToken());
like image 114
BrettJ Avatar answered Oct 29 '22 08:10

BrettJ