6

Users authorize in my android application. And I am sending users' token and other information to my server. At this server I want to implement some logic for users.

I want to have exactly this flow.

I followed the steps quickstart.php in this link to get users' calendars on server.

But I get following error :

google oauth exception' with message 'could not json decode the token'

For this reason I tried this solution. But i take same error. So as 3rd option I created the json format myself like in this solution as below.

$access_token = '{
    "access_token":'.$access_token.',
    "token_type":"Bearer",
    "expires_in":3600, 
    "id_token":'.$id_token.', 
    "refresh_token":" ",
    "created":'. time() .'
}';

as you see I do not know how to exchange refresh token . I searched how to get refresh token and saw this question. And implemented this solution to my code but nothing changed.

Edit 4 : I tried to get access token according to this answer at android application and send it to app server. I'm taking the code as before I did :

GoogleSignInAccount acct = result.getSignInAccount();
code = acct.getServerAuthCode();//sending this code to AsyncTask to get access token

my function to get Access Token:

private void getAccessToken()throws GoogleAuthException, IOException{
    new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            List<String> scopes = new LinkedList<String>();
                scopes.add("https://www.googleapis.com/auth/calendar");
                scopes.add("https://www.googleapis.com/auth/calendar.readonly");
                scopes.add("https://www.googleapis.com/auth/urlshortener");

                GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(transport, jsonFactory, client_id, client_secret, scopes).build();

                try{
                    GoogleTokenResponse res = flow.newTokenRequest(code).execute();
                    accessToken = res.getAccessToken();
                }catch(IOException e){
                }

at the php server side I changed user-example.php file little bit as below because I have the access token now:

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setAccessType("offline");
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/urlshortener");
$service = new Google_Service_Urlshortener($client);
if (isset($_REQUEST['logout'])) {
    unset($_SESSION['access_token']);
}
$client->setAccessToken('{"access_token":"'. $access_token .'","token_type":"Bearer","expires_in":3600,"created":'. time() .'}');
if ($client->getAccessToken() && isset($_GET['url'])) {
$url = new Google_Service_Urlshortener_Url();
$url->longUrl = $_GET['url'];
$short = $service->url->insert($url);
$_SESSION['access_token'] = $client->getAccessToken();

But now I'm getting below error:

Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST https://www.googleapis.com/urlshortener/v1/url: (403) Insufficient Permission' in C:\wamp\www\google-php\src\Google\Http\REST.php on line 110

Community
  • 1
  • 1
melomg
  • 737
  • 3
  • 20
  • 39
  • Variables in single quotes don't get evaluated. Break open the string for variables. `$sp = 'hi i am '.$name.' and i write strings.';` – Charlotte Dunois Apr 22 '16 at 08:41
  • I still take same json decode error. :\ – melomg Apr 22 '16 at 08:56
  • If these two tokens aren't integers, put them into double quotes. – Charlotte Dunois Apr 22 '16 at 09:00
  • They're both string. – melomg Apr 22 '16 at 11:12
  • [This answer](http://stackoverflow.com/a/32826129/3918109) changed my mind not to use service account :( I don't have a google domain and I don't wanna impersonate users of only one domain. I guess I lost my way in Google's documents. :) – melomg Apr 28 '16 at 18:21
  • Maybe a dummy tip but have you looked at the provided examples by google?: https://github.com/google/google-api-php-client/tree/master/examples – jobbert May 03 '16 at 07:44
  • Yes I tried but in these examples clients have to authorized with Google's Choose Account screen. My codes are on the server so users can do this on the server side and server is connected to the android mobile application. User authorized on the android side and I'm sending the access token and code from Android to server. – melomg May 04 '16 at 16:30
  • Now I understood if I get access token for Calendar api on android application, I can send it and get user's calendar on the server side. But I don't know how to get access token for Google Calendar scope. – melomg May 04 '16 at 17:23
  • @jobbert I edited my question for you. – melomg May 04 '16 at 18:48

1 Answers1

2

I was getting Insufficient Permission error after I started to use GoogleAuthorizationCodeFlow to get access token as I mentioned in my OP. And then I tried to add Calendar scope to GoogleApiClient.Builder(this) but I get error like I can't add scope if I add Auth.GOOGLE_SIGN_IN_API because I had added Auth.GOOGLE_SIGN_IN_API to GoogleApiClient.Builder. So this time I tried to add the scope to GoogleSignInOptions.Builder and it is working now. I'm able to get both refresh token and access token. Below code solved my problem:

GoogleSignInOptions gso = state.getGso();
if(gso == null){
    gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestScopes(new Scope("https://www.googleapis.com/auth/calendar"))
        .requestIdToken(getString(R.string.server_client_id))
        .requestEmail()
        .requestServerAuthCode(getString(R.string.server_client_id), false)
        .requestProfile()
        .build();
}
melomg
  • 737
  • 3
  • 20
  • 39
  • Hi! Could you please help me with google log out? I think you had to implement it in your app if you working with googleAuth... I have such issue, i implemented logIn in first activity , but LogOut button i implemented on another activity and then if i click this button i invoke `Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient)` and get error `GoogleApiClient is not connected yet.` as far as i understend i get it because of it is different entity when i make log in and log out... but how i can save the same entity? Which way did you implement it in your app? – Sirop4ik Sep 23 '16 at 18:26
  • I can not test the project because I don't have a server now. And as far as I understand from my codes :D, I recall sign in activity with different flag and in sign in activity at the onConnected function I'm checking this flag. If the flag is true I simply call `Auth.GoogleSignInApi.signOut` function by setting result callback. But I'm pretty sure this isn't a nice way to achieve this goal. Also there are ways to store a value as global. You can look at [this link](http://stackoverflow.com/a/1945297/3918109) and after you get the `mGoogleApiClient` object, you can check if it is connected. – melomg Sep 23 '16 at 18:58
  • as far as i remember `onConnected()` method was provided in previous ver google auth... in last implementation it is some difference... i don't have this method in my implementation( but i get your point of view – Sirop4ik Sep 24 '16 at 12:34