Debugging your Google OAuth 2.0 token when you get HTTP 401s or 403s

One of the things I get asked about the most is OAuth 2.0 when developers start seeing 401s, 403s, and possibly other HTTP 4xx status codes. This post isn’t meant to be a comprehensive guide on OAuth debugging for Google/YouTube APIs. Rather, it’s a collection of some of the steps I find myself recommending or repeating when I’m trying to debug issues with OAuth authorization.

I’ve recorded a short video describing how to enable Google API access for use with web and installed apps:

The checklist is:

  1. Did you create a new API project?
  2. Did you enable the APIs you are looking to use?
  3. Did you create a client ID and client secret?

A common step for developers is that they forget step #2 – enabling the APIs.

Getting a token

Here are my cliff notes on tokens:

  • Access tokens – used to make API calls. These expire after an hour
  • Refresh tokens – you only get these if you request offline access when you ask a user to authorize. These are exchanged by your client for access tokens. Refresh tokens generally don’t expire.

What causes 401s and other 4xx status codes?

The common causes for “401 Unauthorized” when making API calls with an access token are:

  • expired access token (most common)
  • Developer accidentally disabled the APIs (uncommon)
  • User revokes token (rare)

Sometimes, more explanation exists in the response body of a HTTP 4xx. In the Java client, for example, you should log the error, because it will assist in troubleshooting:

try {   
       // Make your Google API call
} catch (GoogleJsonResponseException e) {
      GoogleJsonError error = e.getDetails();
      // Print out the message and errors

Different versions will have different API signatures. Here’s a link to the current version’s Javadocs (1.1.15) – newer versions look like they might be deviating from this a bit.

Troubleshooting the token

You could take your existing code and make an API call here whenever you get a HTTP 4xx and log that response. This’ll return some useful information:

  • When the token expires
  • What’s the token’s scope (this is important)
  • If the token is invalid

If you didn’t write the code yourself and inherited it:

  • Whether this access token came from an offline refresh_token or not (the “offline” field)

If the token is invalid … well, that doesn’t help a lot. I would troubleshoot like this:

  1. Remove the access token from your datastore or database.
  2. Use the refresh token to acquire a new access token (if you are using a refresh token)
  3. Try to make the API call again. If it works, you’re good! If not …
  4. Check the access token against the tokenInfo API
  5. If it’s still invalid, do a full reauth

Hope this helps!

About the author

I'm Ikai and I've been fascinated by technology since before I could walk. I became the 'go to' guy for my friend's tech issues and after getting the same questions over and over, I decided to write down my answers. I hope you find the same value that my friend did.

Leave a Comment