Using the Youtube Data API to get Content Owner data - youtube-api

We have several Content Owners set up in Youtube (I'll call them A, B, C, D). All of them are already associated with a Google account (I'll call it GA1). We have a custom application that needs to be able to retrieve video and analytics data for the Content Owners, by using the Youtube Data API v3. (v2 of the API is going EOL on April 20.)
The problem I'm having is that there's apparently no way to do this. Using a Service Account (and Google's PHP library for talking to the Youtube APIs), I end up making a call that looks like this:
$optParams = array(
'forContentOwner' => true,
'onBehalfOfContentOwner' => '[A]',
'order' => 'date',
'maxResults' => 20,
'type' => 'video',
);
$serviceYT->search->listSearch('snippet', $optParams);
This ends up throwing a 403 Forbidden exception. (The "[A]" above is replaced with the actual Content Owner name.) I can do many other calls successfully, such as listing channels or videos, or even other kinds of searches, but as soon as I add in the "forContentOwner" and "onBehalfOfContentOwner" parameters, I get a 403 Forbidden (with no additional information as to why it's forbidden).
In the Youtube API docs (https://developers.google.com/youtube/v3/guides/authentication), I found this line:
The service account flow supports server-to-server interactions that do not access user information. However, the YouTube Data API does not support this flow. Since there is no way to link a Service Account to a YouTube account, attempts to authorize requests with this flow will generate a NoLinkedYouTubeAccount error.
However, when I authorize (OAuth 2.0) using the Service Account that I created in the developer console (for the account GA1, which is linked to the Content Owners), it authorizes just fine, and I never see any "NoLinkedYouTubeAccount" error. Does anyone know what I'm doing wrong? Or is it simply impossible to access Content Owner data through a Service Account? Is there another OAuth 2.0 flow I should be using instead? The code that needs to call the APIs is triggered via a cron job; it is not interactive at all.

Related

Getting Meeting IDs from Events in an M365 Group

I've been tasked with a project to get attendance information from specific types of Teams. I have a service account that is already a member of these Teams, however it is unable to access an endpoint needed to resolve JoinWebUrls to meetingIDs (See example #3, 'Retrieve an online meeting by JoinWebUrl').
I have done the following thus far:
Create a new App Registration and assigning it 'OnlineMeetings.Read.All' as an Application permission (this process needs to run as a script, meaning that Delegate permissions won't work here)
Create a new Application Access Policy, assigned the aforementioned App Registration's App ID to it, and granted it to the service account.
Signed into MS Graph as the service account (using the 'password' grant_type) and retrieved the 'events' within the Team (via /v1.0/groups/$GroupID/events)
Extracted the JoinWebURL parameter from each of those events.
Step 5 would be to resolve the meetingID from the JoinWebURL, however when I all of the following requests fail:
GET /v1.0/me/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the service account, which should be able to interact with the meeting)
GET /v1.0/users/$ServiceAccountObjectID/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the service account to access it's own object's meetings, however this does seem to be the endpoint for Application permissions rather than Delegate permissions)
GET /v1.0/users/$ServiceAccountObjectID/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (using the App Registration mentioned earlier, signing in with the 'client_credentials' grant_type)
GET /v1.0/me/onlineMeetings?$filter=JoinWebUrl eq '$JoinWebURL' (as the App Registration trying to access any meeting, however this does seem to be the endpoint for Delegate permissions rather than Application permissions)
Basically, I'm stuck. Is there something obvious that I'm missing? I'm also considering raising a support call with Microsoft, to see if the behaviour I'm experiencing is merely a bug.
Thanks in advance.
Events and online meetings are two different API's, you have created an event and trying to get online meeting details. That's the reason you are getting those errors. If you want to get event details please try this document.

Google OAuth is making call to Youtube API

I am trying to use Google OAuth2.0 for authentication. Everything is working fine but on initial(first) loading it is taking extra time (30 seconds-RequestTimeOut) on client side(Web-App) to load prompt. I've checked the Network Tab (Developer Console-Chrome), where I've found that it is trying to make call to
https://accounts.youtube.com/accounts/CheckConnection?pmpo=VALUE&v=VALUE&timestamp=VALUE.
This request is failing with ERR_TIMED_OUT, and In my organization we don't have access to Youtube (That I'm aware of it). But Why and Where my application is making request to Youtube API is my question. If so How do I stop this (fetch accounts from youtube)?
The scope of My App goes like this
"scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
It is happening on initial load itself, later it is giving 200 status for the same request. What am I missing.
I'm completely new to this. (Sorry, If it is noob question)
Thanks in advance.
Edit::
I came to know why it is making request to youtube api, It is trying to fetch any other accounts(login users) from youtube(gmail-accounts). But how to stop making request to youtube(accounts.youtube.com). It is fine for my application to fetch accounts from google(accounts.google.com).
Thanks.
Google puts an iframe inside google o-auth account picker.
Google oauth and youtube accounts iframe
Analyzing the javascript inside that iframe, we find some evidence that, this might be an approach to load youtube session, in order to get the userId for the current logged user in Youtube.
By creating an iframe, you get the normal context of opening an website, this is, you get access to session information.
And it's exactly what this is used for, proof:
//# sourceURL=/_/mss/boq-identity/_/js/k=boq-identity.AccountsDomaincookiesCheckconnectionJs.pt_PT.4FJ4-a_ocZ8.es5.O/d=1/ct=zgms/rs=AOaEmlHUdMtrscDWG6wHCiHHFunuI9afAg/m=base
if (window.parent && window.parent.postMessage) {window.parent.postMessage( google.checkconnection.getMsgToSend('youtube', 'some_id'), 'https:\/\/accounts.google.com');}</script>
iframes can communicate, as long as one another is listening to this messages.

Youtube Data API - How to avoid Google OAuth redirect URL authorization

Requirement: I am trying to upload videos to my Youtube channel through Youtube Data API for Java. The request is sent from a war file hosted on tomcat container.My application is not for external users and I only use it to upload my own generated videos. With the help of the api documentation and sample youtube code snippets, I have successfully managed to post video on youtube.
Problem: The issue is that whenever I try to run the code, I get prompted for
Please open the following address in your browser:
https://accounts.google.com/o/oauth2/auth?client_id=&redirect_uri=http://localhost:8080/Callback&response_type=code&scope=https://www.googleapis.com/auth/youtube.upload
Since I run this code on a remote server, it is not possible for me to always open this URL on the browser. Since I have registered my web app in Google Console, and got a pair of Client ID and Secret and a JSON file, so Youtube must allow me to publish videos by default to atleast my channel, isin't it?
I have used the Auth.java file(provided in youtube java code samples) and the following code is where this thing happens.
// Authorize.
return new AuthorizationCodeInstalledApp(flow, localReceiver).authorize("user#.com");
LocalServerReceiver localReceiver = new LocalServerReceiver.Builder().setPort(8080).build();
Please help here as this is really eating up a lot of my development time.
You should only need to authenticate your code once. When your code is authenticated you get a refresh token back. the refresh token will then allow you to get a new access token the next time your code runs.
There is no service account authentication for the YouTube api. Your code has to be authenticated by you the first time in order to get that refresh token.
I am not a java programmer but from a quick check of the documentation it looks quite similar to what I do in.net. You need to create a datastore to to store the first refreshh token then you should be able to run your code in the future with out needing to authenticate it again.

YouTube Api Explorer Usuage as ContentOwner: forbidden

I'd like to get the impressionBasedCpm from the Api Explorer ( and later from my app).
I can log in with an youtube partner account and toggle the oauth switch. I set all scopes to checked.
Then I try to enter
ids: contentOwner==NAME_OF_CONTENT_OWNER (not the id, retrieved from the content API, https://developers.google.com/youtube/partner/docs/v1/contentOwners/list#try-it)
metrics: impressionBasedCpm
start-date: '2015-05-01'
end-date: '2015-06-01'
The output still tells me:
You do not have permission to execute this method.
Can someone help me?
My guess is that when I authorize the application I seam to still login as a channel, so the query as a content owner is not allowed. I picked the main one with the email address. But when I'm on youtube I can switch to a specific Content-Manager Channel/Account.
Even when I try to just get the 'likes' for the contentOwner it doesn't work. If I try to get the likes based on the channel_id it works. But I like to get reports for a youtube partner that uses youtube's cms.
cheers
This query won't work because it does not follow the semantics of the API. You need to provide the ID of the contentOwner in order to get a 200 OK response. Name of Content Owner cannot be unique and hence would lead to erroneous results.

YouTube API broken by Google. 'Authentication with Google failed. Reason: NoLinkedYouTubeAccount'

** UPDATE **
It truly seems that Google has just screwed every single person on the planet by absolutely requiring user interaction to upload a video. Of course I know, they are free. Exactly what I warned the client years ago about, so I don't need to be reminded. Thank You.
So I would like to try to take this in a different direction and just find a loophole and a workaround to still keep doing what we are doing in spite of Google's complete lack of support or caring in any way about the developers and what they have to deal with.
It would be different if you can actually call a phone number and talk to a human being about YouTube Partner access, but you can more quickly get access to the Illuminati.
OAuth 2.0 is now the only supported authentication method period. It does require user interaction.
But what about that token? Does anybody know how long the token lasts?
If I can obtain a token just once using user interaction and place it in the database, I can automate possibly hundreds or thousands of interactions afterwards.
In other words, I'm trying to turn the user interaction into a speed bump instead of a concrete wall.
If anybody has any examples of obtaining that token, caching it, and using it afterwards, that would be a godsend to me right now.
Thanks for the comments and the help. I'm not surprised that the YouTube Developers Forum just folded and said to come here instead :)
It seems that Google has completely pulled the plug on the existing dashboard.
https://code.google.com/apis/youtube/dashboard/gwt/index.html
That link is now 404'd. Tried from several different browsers on different systems.
Registered under the new Google APIs Console already, but still get the problem.
// Set the authentication URL for this connection object
$authenticationURL= 'https://www.google.com/youtube/accounts/ClientLogin';
// Try to connect to YouTube with the channel credentials passed
try {
$httpClient =
Zend_Gdata_ClientLogin::getHttpClient(
$username = $channelfields['EMAIL_ADDRESS'],
$password = $channelfields['PASSCODE'],
$service = 'youtube',
$client = null,
$source = 'Redacted Data',
$loginToken = $channelfields['CACHED_TOKEN'],
$loginCaptcha = '',
$authenticationURL);
} catch (Zend_Gdata_App_HttpException $httpException) {
$update_error['response_body'] = $httpException->getRawResponseBody();
$update_error['error'] = 1;
} catch (Zend_Gdata_App_Exception $e) {
$update_error['message'] = $e->getMessage();
$update_error['error'] = 1;
}
This code has worked perfectly fine before, but does not work with the older API key, or the newer one generated inside the Google APIs console.
I'm attempting a simple upload and this concerns me greatly:
"The service account flow supports server-to-server interactions that do not access user information. However, the YouTube Data API does not support this flow. Since there is no way to link a Service Account to a YouTube account, attempts to authorize requests with this flow will generate a NoLinkedYouTubeAccount error."
From all reports it seems that Google has forced YouTube uploads to become interactive in all cases precluding all possibility of platforms that automatically upload generated content from working at all.
Any help or insights into the process is appreciated.
P.S - Ohhh, it's been awhile since I looked at that system and Google shut down the YouTube Developer Forums and said "YOU" were responsible for their support now :)
OAuth2 does support the ability to avoid user interaction through the offline access type parameter (ie, using access_type=offline). Check out Google documentation for details.
The solution is really rather simple. Your app needs to use oauth to request offline access. It will be given an access cide which you convert to a refresh token, which is the thing you store in your database. This doesn't expire. Well actually it sometimes does, but that's another story. Whenever you need to access the api, use the stored refresh token to request an access token which you include in each api call.
See https://developers.google.com/accounts/docs/OAuth2WebServer for details.
I don't know what you did but https://code.google.com/apis/youtube/dashboard/gwt/index.html works perfectly fine for me. Maybe it was a temporary issue. If you want no user interaction you HAVE to use YouTube API v2 OR you have to use v3 with methods that don't require authentification OR you have to provide your own youtube account credentials which is not recommended and probably not appropriate for you situation.
Several issues to respond here, I think.
1) The older API console has not been removed, but I've noticed intermittent outages to it and to the newer API console while Google is rolling out their new "cloud console."
2) ClientLogin was officially deprecated in April of 2012, not just 48 hours ago. Jeff Posnick has detailed all the changes over the months (and related ones, such as AuthSub, Youtube Direct, etc.) at his blog (apiblog.youtube.com).
3) You're right that, with v3 of the APIs, you cannot do automatic uploads across the board, as the oAuth2 flow requires user interaction. However, given the limited description of your use case, using refresh tokens is probably your best bet. If the content is user generated, somewhere they must be logging into your app, correct? (so that your app knows which credentials to leverage to do the uploads). At the point they're logging into your app, and you're starting the oAuth2 flow, you just have to hit the first oAuth endpoint and pass it the parameter access_type=offline (along with any other parameters). This will ensure that, when they grant that initial permission, you're returned a refresh token instead of an access token. With that refresh token, you can exchange it for multiple access tokens as needed (an access token lives for about an hour. I don't know how long a refresh token lives, but I've never had one expire before my own login cookies did, and then I just get a new one when my users re-login to my app).
Here's some more info on how to use the refresh token; note, too, that the various google api client libraries make it pretty smooth.
https://developers.google.com/accounts/docs/OAuth2WebServer#refresh
Also, this video tutorial from a Google Developers Live broadcast a couple of months ago might help illustrate the point: http://www.youtube.com/watch?v=hfWe1gPCnzc -- it's using the oAuth playground rather than a client library, but the concept is the same.
The answer is to use google-api-php-client, create an interactive auth page, and set up YouTube API v3 correctly with the new API console.
You can create a very simple page that will authenticate for the supplied channel and then store the correct token in your database. Is already working and uploading hundreds of videos on one channel. You do need to remember to fully activate yourself under the new API console and add the services required. Just keep authenticating and adding the services it says it needs. After that, the regular v3 upload process works just fine. On failure send a group an email and they can get a new token in 10 seconds.
Not the most elegant solution, but the documentation from Google is far from elegant anyways that Stack Overflow is now their front line support.
Just hang in there, a solution is always found. Don't give up!
I didn't get here by myself either, the other answers on this page helped me get all the way to this point. Thanks guys.
P.S - Don't forget the scopes
$client->setScopes("https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload");

Resources