Resolve Google Cloud API oauth2 cannot fetch token invalid_grant Error

Saturday, November 26, 2016

While trying to generate Let’s Encrypt SSL certificates with lego and gcloud DNS, I encountered the following error:

[example.com] Could not obtain certificates
    Error presenting token: GoogleCloud API call failed: Get https://www.googleapis.com/dns/v1/projects/example-project/managedZones?alt=json&dnsName=example.com.: oauth2: cannot fetch token: 400 Bad Request
Response: {
  "error" : "invalid_grant"
}

Having never encountered this error before, the first thing I tried was to revoke my credentials with command gcloud auth revoke and re-authenticate with command gcloud auth login, but it didn’t work.

Google searching didn’t reveal much. All I found were the following two posts, but the fixes either didn’t work or apply to me:

Next, I thought I had corrupted keys or tokens, so I created a backup of my current gcloud directory (~/.config/gcloud), deleted the current gcloud directory, and let the gcloud command create a new one.

After reauthenticating with command gcloud auth login, I ran the lego command from above again but encountered the following error:

Unable to get Google Cloud client: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

Because I had created a new gcloud directory, I didn’t have any application default credentials; this was confirmed by running command gcloud auth application-default print-access-token. Before deleting the gcloud directory, I had application default credentials set, but the token must have been invalidated causing the invalid_grant error from above.

After reading the following description - obtained by running command gcloud auth application-default - why I was encountering this issue started making more sense:

Application Default Credentials provide a simple way to get authorization credentials for use in calling Google APIs. These commands assist in managing the active credentials on your machine that are used for testing purposes during local application development. These credentials are strictly used by Google client libraries in your own application. They are not used for any API calls made by the gcloud CLI, nor do they have any interaction with the credentials acquired by gcloud auth login. For more information on ADC and how they work, see: https://developers.google.com/identity/protocols/application-default- credentials

The lego command does not call the gcloud command directly; it uses the Google Cloud APIs directly which requires an application default credential. Any program that uses the Google Cloud APIs directly is going to require an application default credential. This is a seperate form of authentication than what gcloud auth login creates for you.

Finally, I more than likely did not need to create a new gcloud directory, I could have simply run the following two commands to get a new application default credential token:

gcloud auth application-default revoke

gcloud auth application-default login

After running those commands, I was able to run the lego command from above to generate the Let’s Encrypt SSL certificates.



comments powered by Disqus