Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Youtube Analytics API returns 403 forbidden even if token is valid

I have an issue with access to Youtube Analytics API for random youtube channels.

After a successful authorization with following scopes:

  • https://www.googleapis.com/auth/youtube.readonly
  • https://www.googleapis.com/auth/yt-analytics.readonly

I'm saving the token and refresh token in the database. Everything works well for some time. After a while (eg. three months) when my app makes a request, Google returns 403:

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "forbidden",
        "message": "Forbidden"
      }
    ],
    "code": 403,
    "message": "Forbidden"
  }
}

but only for Youtube Analytics API, other endpoints in Youtube Data API works fine with this token. That happen for random accounts (channels). Owners of this channels didn't revoke access to my app, didn't change account password etc.

This issue affects about 40% of all channels in my application (the time when Youtube Analytics API stops working is different, from 1 to 6 months after obtaining OAuth2 token). Then I have to send them periodically a new authorization url.

Where is the problem?

This is how I generate an auth url and make requests:

  • Auth URL:

    flow = client.flow_from_clientsecrets(
        secret_file_path,
        scope=["https://www.googleapis.com/auth/youtube.readonly",
               "https://www.googleapis.com/auth/yt-analytics.readonly"],
        redirect_uri=redirect_url,
        prompt="consent"
    )
    flow.params["access_type"] = "offline"
    url = flow.step1_get_authorize_url(state=state)
    
  • Stats request:

    auth = client.OAuth2Credentials.from_json(credentials_from_db)
    http_auth = auth.authorize(httplib2.Http())
    api = discovery.build("youtubeAnalytics", "v1", http=http_auth,
                       cache_discovery=False)
    api.reports().query(
        ids="channel==%s" % channel_id,
        metrics="estimatedMinutesWatched",
        dimensions="video",
        start_date=start_date,
        end_date=end_date,
        max_results=20,
        filters="video=={}".format(",".join(video_ids))
    ).execute(http=http)
    

I'm using google-api-python-client 1.6.5

Edit

I attached screenshot while debugging requests to google API using google-api-python-client. Here's what's going on:

  1. Retrieving channel's base stats using Youtube Data API
  2. Retrieving channel's advanced stats using Youtube Analytics API

My point is that, the refresh token is successfully exchanged in both cases but works only with Youtube Data API. I purposely exchange it twice. The same result is when I access only Youtube Analytics API with one successful token exchange (without calling Youtube Data API).

And the most fun part is that, this code works for some time (a couple weeks or months) and then stops :-)

API requests

like image 506
User Avatar asked May 29 '18 10:05

User


People also ask

What is YouTube Error 403?

Description. forbidden (403) forbidden. Access forbidden. The request may not be properly authorized.

What is forbidden error in API?

Short description. An HTTP 403 response code means that a client is forbidden from accessing a valid URL. The server understands the request, but it can't fulfill the request because of client-side issues.


2 Answers

Ok lets start with a little background information.

There are sevral reasons why a refresh token would stop working.

  1. It gets to old refresh tokens expire after six months if not used.
  2. A user can reauthecate your application and get a new refresh token both refresh tokens will work you can have a max of fifty outstanding refresh tokens then the first will stop working.
  3. the user can revoke your access.
  4. Wakey daylight savings time bug of 2015. (we wont talk about that)

Now none of this is the case for you. Why because the refresh token still works your just drooping a scope. Which is crazy a user cant remove your access to one scope and it wont expire one scope.

That being said i am leading towards this being a bug. I have sent an email off to someone I know who is on the Oauth team.

In the mean time. I have an idea?

What happens if you try and request a new access token using the refresh token? Could it be an issue with the access token that was returned to you?

like image 188
DaImTo Avatar answered Nov 07 '22 22:11

DaImTo


Given that you say that the token refresh works but the API call returns error, the only thing that I suspect is some issue on the api side.

Are you making these API calls from your server? For how many users? You may be running into per IP based limits. I don't know that for sure.

I think the easiest way to find the issue will be if you can send us a few tokens that start returning error. We can lookup if the tokens became invalid or there is an issue on the API side. You can email them to [email protected]

like image 1
nvnagr Avatar answered Nov 07 '22 21:11

nvnagr