Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access token is invalid #20

Closed
ndamnjanovic opened this issue Aug 12, 2014 · 39 comments
Closed

Access token is invalid #20

ndamnjanovic opened this issue Aug 12, 2014 · 39 comments

Comments

@ndamnjanovic
Copy link

Hi there,

I have a problem with retrieving spreadsheets (at very beginnig :)).
The error that I get is _An error occurred: Access token is invalid_.

Not sure how is that possible, since I authenticated myself just before these calls.
I saw on stackoverflow that before creating $serviceRequest, this guy first creates $request. But that class is not available anymore.

Am I missing something?

    $serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($token['access_token']);
    Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);
    $spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
    $spreadsheetFeed = $spreadsheetService->getSpreadsheets();
    $spreadsheet = $spreadsheetFeed->getByTitle('Test');

My token is something like this: ya29.XwBiWPalOnpCNxwAAADama7fGb7uKPj2DhwF2cKJkvhRH9hk1ewyihk9QiI-oA

Thanks a lot!

@asimlqt
Copy link
Owner

asimlqt commented Aug 12, 2014

Hi,

The API version used in the stackoverflow link above is in an older version, there have been a few changes since then.

That code you've pasted above is correct as i've tested it with my own access token just now and it works,

Also the token you've pasted above looks to be correct because my token starts with "ya29." as well, although it is a little shorter, have you intentionally not pasted the full token?

So i don't know what to suggest other than the error from google "Access token is invalid". Without access to your account i can't really do anything else! Most likely the issue is with the token, remember that the token is only valid for an hour and if you reauthenticate with google using whatever process you're currently using then it will invalidate your previous token, even if your previous token was created 5 minutes ago.

@Schepp
Copy link

Schepp commented Aug 13, 2014

Same here with me. Maybe this has to do with the service I authenticated against? Or the permissions?

$client = new Google_Client();
$client->setClientId(GOOGLE_CLIENTID);
$client->setClientSecret(GOOGLE_CLIENTSECRET);
$client->setRedirectUri(GOOGLE_REDIRECTURL);
$service = new Google_Service_Datastore($client);
$client->setScopes(Google_Service_Datastore::DATASTORE);

I definitely get a token back, but at the moment I call...

$spreadsheetFeed = $spreadsheetService->getSpreadsheets();

...I get a:

Fatal error: Uncaught exception 'Google\Spreadsheet\UnauthorizedException' with message 'Access token is invalid' in /var/www/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php:232

It would be nice if you could include some more info on creating the correct token with the Google library in your documentation.

Thank you in advance!

@Schepp
Copy link

Schepp commented Aug 13, 2014

Okay, got it running, too. Good to know that one needs to authenticate via "OAuth 2.0 Service Account Authentication", not "OAuth 2.0 Web Server Authentication".

@ndamnjanovic
Copy link
Author

Thanks both for your replies!
@Schepp, I guess I'm doing same mistake. What exactly I need to change? I was configuring client, same way you do above.

@Schepp
Copy link

Schepp commented Aug 13, 2014

Hey, @ndamnjanovic,

here is what worked for me:

  • Go into the Google Developer Console
  • Create a new project (and wait for it to complete)
  • Once in that project select "APIS & AUTH" from the left side
  • Select "Credentials"
  • Push the button "Create new Client ID"
  • Chose "Service Account"
  • You get offered a JSON formatted private key for download. I don't think you need it, but save it anyways (who knows?)
  • On the right hand side you now find all the data you need to implement the code following at the end of this post.
  • You need to generate a (new) .p12 file and save it so you can use it, too, in the following script (in file_get_contents(GOOGLE_CLIENTKEYPATH))..

That's it. Authentication works now. But the next problem for me is that the list of spreadsheets which I retrieve through the API is empty. No idea why that is... :(

$client = new Google_Client();
$client->setApplicationName('My Webservice');
$client->setClientId(GOOGLE_CLIENTID);

$cred = new Google_Auth_AssertionCredentials(
    GOOGLE_CLIENTEMAIL,
    array('https://spreadsheets.google.com/feeds'),
    file_get_contents(GOOGLE_CLIENTKEYPATH)
);

$client->setAssertionCredentials($cred);

if($client->isAccessTokenExpired()) {
    $client->getAuth()->refreshTokenWithAssertion($cred);
}

$obj_token  = json_decode($client->getAccessToken());
$accessToken = $obj_token->access_token;

$serviceRequest = new DefaultServiceRequest($accessToken);
ServiceRequestFactory::setInstance($serviceRequest);

$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();

@zarseny
Copy link

zarseny commented Aug 13, 2014

It helped me to share the sheet with service account.
Even if it's public I have a feeling you need to access it once to be able to get it though api.

@Schepp
Copy link

Schepp commented Aug 13, 2014

@zarseny YOU. MADE. MY. DAY!!! <3 <3 <3

For everyone not getting what's going on: He meant that I should share the document with a virtual user that has the email that was generated in the Google Developers Console.

@asimlqt
Copy link
Owner

asimlqt commented Aug 13, 2014

Hi Guys,

You're not the first ones to have issues authenticating with Google using OAuth. I'm going to create a new project here in Github which will describe how to authenticate and provide some sample code.

@asimlqt
Copy link
Owner

asimlqt commented Aug 13, 2014

@Schepp
Copy link

Schepp commented Aug 14, 2014

That was a very good idea. Thank you @asimlqt !

@ndamnjanovic
Copy link
Author

This is great, thanks a lot to everyone, I'll check this out.

@ZurabWSG
Copy link

Do I need to share each spreadsheet with the service account? What about the new spreadsheets I create from my main account not the service one? Please help.

@asimlqt
Copy link
Owner

asimlqt commented Nov 26, 2014

Hi,

I've not a used a service account before and this doesn't seem to be a bug/issue with this library rather an access/permissions issue with google. You can read more about using a service account at the following url:

https://developers.google.com/accounts/docs/OAuth2ServiceAccount

@nekromoff
Copy link

I have this problem, I always get this:

{"access_token":"ya29.3AAc-8mXbyHSaOFS_TJJX4dkrvH92eY956HV5ZyR1mR6gTnQnr-jPzZkDEa0rJl9pOaR4lJ3DdGJuQ","token_type":"Bearer","expires_in":3600,"created":1418520786}
Fatal error: Uncaught exception 'Google\Spreadsheet\UnauthorizedException' with message 'Access token is invalid' in /whatever/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php:240 Stack trace: #0 /whatever/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php(131): Google\Spreadsheet\DefaultServiceRequest->execute(Resource id #46) #1 /whatever/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/SpreadsheetService.php(38): Google\Spreadsheet\DefaultServiceRequest->get('feeds/spreadshe...') #2 /whatever/sample.php(27): Google\Spreadsheet\SpreadsheetService->getSpreadsheets() #3 {main} thrown in /whatever/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php on line 240

scopes:
$client->setScopes(array('https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive','https://docs.google.com/feeds/'));

spreadsheet access code:
$serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($token['access_token']);
Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();

sometimes i get this instead:
Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error fetching OAuth2 access token, message: 'invalid_grant: i'' in /whatever/vendor/google/apiclient/src/Google/Auth/OAuth2.php:127 Stack trace: #0 /whatever/vendor/google/apiclient/src/Google/Client.php(130): Google_Auth_OAuth2->authenticate('4/gGfFncBJOs5id...') #1 /whatever/sample.php(19): Google_Client->authenticate('4/gGfFncBJOs5id...') #2 {main} thrown in /whatever/vendor/google/apiclient/src/Google/Auth/OAuth2.php on line 127

@nekromoff
Copy link

anyone?

@ZurabWSG
Copy link

Access token is invalid, you're generating it in a wrong way. I used Google APIs Client Library for PHP to make it work as needed.

1: Google APIs Client Library for PHP: https://github.com/google/google-api-php-client

@nekromoff
Copy link

I am using exactly that project's code to generate this access token, so how it could be invalid?

e.g.:
Authenticate {"access_token":"ya29.3QAJX5Wr-K68q5IyO_htN1wL3dZWKlqNo8CaUBUn6Xc9C-LdhvMqHl5EUDRI9ZBq_sCA7j6OQnX9eA","token_type":"Bearer","expires_in":3600,"created":1418656287}
Fatal error: Uncaught exception 'Google\Spreadsheet\UnauthorizedException' with message 'Access token is invalid' in /www/xxx/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php:240 Stack trace: #0 /www/xxx/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php(131): Google\Spreadsheet\DefaultServiceRequest->execute(Resource id #46) #1 /www/xxx/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/SpreadsheetService.php(38): Google\Spreadsheet\DefaultServiceRequest->get('feeds/spreadshe...') #2 /www/xxx/sample.php(27): Google\Spreadsheet\SpreadsheetService->getSpreadsheets() #3 {main} thrown in /www/xxx/vendor/asimlqt/php-google-spreadsheet-client/src/Google/Spreadsheet/DefaultServiceRequest.php on line 240

@ZurabWSG
Copy link

Piece of code I'm using to generate the token:

function getToken()
{
    $client = new Google_Client();
    $client->setApplicationName(GOOGLE_APPLICATION_NAME);
    $client->setClientId(GOOGLE_CLIENT_ID);
    $key = file_get_contents(GOOGLE_KEY_FILE);
    $cred = new Google_Auth_AssertionCredentials(
        GOOGLE_CLIENT_EMAIL,
        array(GOOGLE_SPREADSHEETS_SCOPE),
        $key
    );
    $client->setAssertionCredentials($cred);
    if($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion($cred);
    }
    $service_token = json_decode($client->getAccessToken());
    return $service_token->access_token;
}

Define these variables somewhere in the beginning of your code, index.php for example:

GOOGLE_CLIENT_ID is ID like 109XXXXX-xxxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_EMAIL is the service account email address
GOOGLE_SPREADSHEETS_SCOPE is https://spreadsheets.google.com/feeds
GOOGLE_APPLICATION_NAME is the app name that you provided when creating a service account.
GOOGLE_KEY_FILE is the path to your .p12 file.

Give this a try and post back whether it works or not.

@nekromoff
Copy link

ok, thanks, will try. i was trying to use Client ID for web application

@nekromoff
Copy link

ok, works, thanks! i don't know why it needed "service app" instead of "web app".

@ZurabWSG
Copy link

Was a big pain to figure this out, good it helped you.

@brizbane
Copy link

In case it helps anyone, I ran into this issue this week, and @ZurabWSG solution was the one that made it work for me.

I'm using the service (impersonating a user) method (https://developers.google.com/api-client-library/php/auth/service-accounts).

I obtain a valid token using google-api-php-client.

However, I was getting invalid token when passing it to php-google-spreadsheet-client.

What I had to do was to decode the JSON token, and then pass only the access_token portion of the token object.

$service_token = json_decode($client->getAccessToken());
$request = new DefaultServiceRequest($service_token->access_token);

@ZurabWSG
Copy link

@brizbane, I'm glad I was helpful.

@nicodemuz
Copy link

I ran into similar issues getting a "invalid_grant". I'm running this on Docker on my local development environment and it seems like the time in docker container is not synced. Syncing should fix the problem.

@SimonEast
Copy link

Thanks to contributions from this thread, I have created a wiki page which explains how to authenticate using a "Service account". Hope that helps others. :-)

https://github.com/asimlqt/php-google-spreadsheet-client/wiki/How-to-use-%22Service-account%22-authorization-(rather-than-user-based-access-refresh-tokens)

@lopandpe
Copy link

lopandpe commented Apr 8, 2015

In Laravel, I get this error, and I'm not able to understand why or how to solve it:

ErrorException in File.php line 149:
mkdir(): Permission denied

@ZurabWSG
Copy link

ZurabWSG commented Apr 8, 2015

It looks obvious to me, you don't have enough permissions to create a directory. To find out which directory, echo its name in File.php around line 149.

@lopandpe
Copy link

lopandpe commented Apr 8, 2015

It was taking storageDir as

$storageDir = $this->path . '/' . substr(md5($file), 0, 2);

And in Laravel would be as

$storageDir = base_path() . '/storage/' . substr(md5($file), 0, 2);

@rdybarra
Copy link

I had this problem in pursuit of a web app (not a service app) and solved it through knowledge gained by looking at the curl response in DefaultServiceRequest.php#execute.

My problems were:

  1. I was following the web app authentication guide from google: https://developers.google.com/api-client-library/php/auth/web-app . It exposes a method getAccessToken(), but that method doesn't return the token. It returns a JSON object that has the token inside it. So trying to send a JSON object as the token....well that's obviously not gonna end well.
  2. The constructor for DefaultServiceRequest.php takes a token type as the second parameter. I needed to supply Bearer as the token type instead of using the default.
  3. Bonus problem... I had assumed I only needed one scope https://www.googleapis.com/auth/drive. I also needed https://spreadsheets.google.com/feeds.

I hope this info saves someone a little bit of time.

@nonaxanon
Copy link

almost have this figured out, anyone know of a way to not have to share the created file with the service account email of the console so that you can access it, i mean like having it when created already shared or something magic like that ?

@coolshrimp
Copy link

im getting this error:

Fatal error: Uncaught exception 'Google\Spreadsheet\UnauthorizedException' with message 'You need permission' in /home2/springs4/public_html/HostedSites/STEPLatam/Scripts/Google/Spreadsheet/DefaultServiceRequest.php:244

it inserts a blank row on my spreadsheet.

@mingalevme
Copy link

For addition to @rdybarra 's answer:
4. Share the spreadsheet with your Service account email address.

@mosseri
Copy link

mosseri commented Feb 10, 2016

Sorry but I'm confused. @ZurabWSG and @Schepp are saying you need to authenticate via 'OAuth 2.0 Service Account Authentication,' and not 'OAuth 2.0 Web Server Authentication' but @asimlqt wrote this and he seems to be using web server auth, as per his auth example - https://github.com/asimlqt/php-google-oauth.

Which is it?

@rdybarra, sounds like you are only using a web app, is that correct? Does that mean you have created an OAuth 2.0 client ID from the console and not a service account key? I tried setting the token type to 'Bearer' as the token does in fact look to be of that type, but I still get an "Access token is invalid" error when I try to use the SpreadsheetService.

@rdybarra
Copy link

@mosseri ,

Correct, I'm using the web app. I'm using the OAuth client ID JSON file that google prompted me to download.

Not to muddy up this thread but here's the initialization code that I'm using successfully.

 private function initGoogleClient()
 {
    require_once (dirname(__FILE__) . '/../../../vendor/google/apiclient/autoload.php');

    $client = new \Google_Client();
    $client->setAuthConfigFile(dirname(__FILE__) . '/../../../config/client_secret_json_file_from_google.apps.googleusercontent.com.json');

    if ($this->includeAuthRules) {
        $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . self::OAUTH_ENDPOINT);
        $client->setAccessType('offline');
        $client->addScope('https://www.googleapis.com/auth/drive.file');
        $client->addScope('https://spreadsheets.google.com/feeds');
    }

    if ($this->accessToken) {
        $client->setAccessToken($this->accessToken);
    }

    $this->client = $client;

    return $this;
}

Then, when I want to init this spreadsheet service I have

    private function initSpreadsheetService()
    {
        $accessTokenObj = json_decode($this->googleClient->getAccessToken());

        $serviceRequest = new DefaultServiceRequest($accessTokenObj->access_token, 'Bearer');
        ServiceRequestFactory::setInstance($serviceRequest);

        $spreadsheetService = new \Google\Spreadsheet\SpreadsheetService();

        $this->spreadsheetService = $spreadsheetService;

        return $this;
    }

I realize this is just snippets but I hope it helps.

@nemeth-it
Copy link

@rdybarra Thank you! Point 3 of your post (#20 (comment)) did it for me.

I got Invalid Token every time, tried to manipulate the tokentype (Bearer). But with your hint, I got access to my spreadsheets in the end. Thank you!

@michal-loksik
Copy link

@rdybarra Thank you, your advices just saved my life! :)

@coolshrimp
Copy link

i have a solution!
http://shop.coolshrimpmodz.com/index.php/other/html-form-to-google-doc-script.html

@nemeth-it
Copy link

How to mark coolshrimp post as spam?

@coolshrimp
Copy link

It's not spam my script uses the oAuth 2.0 to send data to a google doc shared with a service account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests