I need to extract information from videos using YouTube Analytics and Reporting Api.
I have access to multiple YouTube Brand Accounts, when I log into YouTube with my Google Account.
Using the "Try it" for testing the API, I'm only able to retrieve data for a channel once I switch to the Brand Account that this channel belongs, otherwise I get 403 - Forbidden error.
Is there any way to extract data using the Google Account that I'm using to log in? Because once I create the credentials in developers console, they will be associated to the Google Account and not to the Brand Accounts.
My google account has Manager Role on the brand accounts.
I've search for the onBehalfOfContentOwner field to be used in requests, but I don't know how to get this ID, and I'm not sure if this is applicable in my situations, since we're talking about Brand Accounts, correct me if I'm wrong.
I fought with this just two days ago. Turns out it IS possible, it's just undocumented and works a bit differently than you'd expect:
Once I create the credentials in developers console, they will be associated to the Google Account and not to the Brand Accounts.
I had the same exact misconception when I first tried (even went so far as to find out the brand account's client_id). Turns out you don't want to use the brand's oauth info -- you want to use your own client_id/client_secret to create a refresh token on behalf of the brand account then use that to create auth tokens.
Steps:
Using your main account create an oauth client_id and client_secret via https://console.developers.google.com/apis/credentials
Edit the client_id/client_secret entry you just added and add "https://developers.google.com/oauthplayground" to the "Authorized redirect URIs" at the bottom of the page.
We're going to create a refresh token the lazy way. Go to https://developers.google.com/oauthplayground/
Click the gears on the top right corner and set access type to "offline", then click "Use your own OAuth credentials" and enter the client_id and client_secret you created in step 1.
Select the scopes you want to give it access to. Click authorize APIs.
Here's the magic bit: You'll now be asked to "Choose an account". Choose the brand account you want to access here, NOT your main account. Since you have permission to access it this'll work fine even though you're using your own client_id and client_secret
Allow the permission access when it prompts you, then you'll be brought back to the oauth playground.
Click "Exchange authorization code for tokens"
Grab the refresh token and use it like normal to generate auth tokens as needed.
Congratulations, you now have api access to the brand account!
Hope that helps.
The YouTube API is different then other google APIs. With other APIs you authenticate access to the full account. However with the YouTube API its channel based. You are going to need to authenticate your application once for each channel.
onBehalfOfContentOwner
This parameter is intended for YouTube content partners that own and
manage many different YouTube channels. It allows content owners to
authenticate once and get access to all their video and channel data,
without having to provide authentication credentials for each
individual channel. The actual CMS account that the user authenticates
with needs to be linked to the specified YouTube content owner.
You need to be a YouTube partner then you can contact your account manager and get a CMS id. I have yet to figure out what magic one must archive to become a YouTube partner.
I will give an update to #Paolo's incredible answer. In my case, I was trying to get my private videos using the Playlist.list api. I've never seen an api as poorly documented, asinine, and CONVOLUTED as youtube's api.
Context: I have a main google account for which my youtube api credentials are tied to (there is no google developer accounts for youtube brand accounts) but would like to get the private playlists (and videos) for my youtube account (a brand account). mine=true, key, channelId, onBehalfOfContentOwner, and onBehalfOfContentOwnerChannel all did NOTHING for me. I was getting either public playlists or api errors with various combinations and values of those parameters.
In the end, these were the steps I took to run a node script to get private videos from my brand account:
Go to https://console.developers.google.com/ for your main google account.
In the sidebar, go to APIs & Services, then Credentials
At the top, click +Create Credentials, then Service account
Under Service account details, enter any name, then click Create and Continue
Under "Grand this service account access to project", click continue
Under "Grant users access to this service account", click Done
On the main credentials page that loads, click the newly created service account under Service Accounts
In the tabs, click Keys
Click the Add Key button, then Create new key
Keep JSON, then click create
Save the file as client-key.json in the root of your nodejs project
Go to https://developers.google.com/oauthplayground
Scroll to bottom of scopes and select YouTube Data API v3 v3, then https://www.googleapis.com/auth/youtube and https://www.googleapis.com/auth/youtube.readonly.
In the window that pops up, click your youtube (brand) account, then allow
In the next step, click Exchange authorization code for tokens
Copy the access token
Go back to your node script and use like this:
const auth = new google.auth.GoogleAuth({
keyFile: "client-key.json",
scopes: [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.force-ssl",
"https://www.googleapis.com/auth/youtube.readonly",
"https://www.googleapis.com/auth/youtubepartner",
"https://www.googleapis.com/auth/youtubepartner-channel-audit",
],
})
const authClient = await auth.getClient()
google.options({ auth: authClient })
const youtube = google.youtube("v3")
const token = "your token here"
const results = await youtube.playlists.list({
part: [
"snippet",
"id",
"contentDetails",
"status",
"localizations",
"status",
],
mine: true,
auth: token,
oauth_token: token,
maxResults: 50,
})
Note mine: true and that the token must be passed to BOTH auth and oauth_token, but not key. If either parameter is missing, the call will fail. (Why? No clue. Please tell me.) Also, you must continuously renew your access token in the playground after it expires.
Now, with all of this said, I encourage you to find me an api worse than the youtube api. My guess is you'll be hard-pressed to find one even half as ridiculous as this.
P.S.
I believe there were additional things required before this such as enabling the youtube api and doing something on the OAUTH Consent Screen but I'm too exhausted with this thing to continue. Hopefully the Google console UX will be enough to guide you through those steps, though quite frankly, I doubt it.
Hope this helps and good luck, because you may actually need it.
If you follow the solution for getting a permanent refresh token and use Java, this works for me
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setClientSecrets(oauth2ClientId, oauth2ClientSecret)
.build()
.setRefreshToken(oauth2RefreshToken);
this.youTubeClient = new YouTube.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
Required dependencies
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-youtube</artifactId>
<version>v3-rev212-1.25.0</version>
</dependency>
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>0.18.0</version>
</dependency>
These resources might also help once you have the refresh token:
Authenticate programmatically to Google with OAuth2
https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35
Related
Is there a way to automatically authenticate the google javascript api client, without user interaction?
Something like this:
User loads webpage -> webpage automatically signs in into a predefined user account -> api calls get executed
Basically i want to prevent the popup where you have to select an account and sign in to it. As the account which will be signed in is always the same.
EDIT:
pinoyyid answer looks promising and is what im looking for. But this only works if the user has signed in with an account at least once, if im not mistaken.
Now i dont want to use an account supplied by the user, but a predefined account which i am the owner of and sign this account in.
Im not entirely sure if this is even possible, as i have to provide the password/some authentication code to google and somehow do this in a secure way.
Use Case: The website will create a Youtube Broadcast via the Youtube Data/Livestream API for the specified account.
Yes you can do that. Referring to https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow
there are three pieces of information that will get you where you want to be:-
The OAuth URL can include a login_hint which is the email of your intended user
The OAuth URL can also include prompt=none which will do its work silently
This all needs to run in an iframe because this is based on origins and redirects.
==EDIT==
If the requirement is for a browser client to connect to a Google Account other than that of the browser user, then this is not possible. It's kinda obvious really that to do so would require a credential in the browser which by definition is not a secure environment.
The approach I would take would be to use a service such as Lambda or Google Cloud Functions (or whatever marketing name they have this week) to create a proxy for the corresponding Google API using a credential stored server-side.
I'm trying to integrate my bot too the Hangouts Chat API. I migrated from C# to node.js in order to be able to take advantage of the HangoutsAdapter: https://botkit.ai/docs/v4/platforms/hangouts.html
The problem is that the HangoutsAdapter expects a google token and when I go to the Hangouts Chat API configuration tab, I select Bot URL under Connection Settings section, but the only thing I get is a field to enter my bot's url endpoint. Nothing about the Verification Token I'm supposed to pass to the Hangouts Adapter.
Is there any other way to validate the connection to that API with HangoutsAdapter? Should I use something else rather than HangoutsAdapter? Or maybe I should use it in a different way?
Technically, this is an alternative solution (I think). In order to create Google Hangouts credentials a GSuite account is required, which I don't have. The Interface HangoutsAdapterOptions docs state the "Shared secret token [is] used" for validation and is found under the Configuration tab. As the fields are locked down, I can't test this.
However, the alternative is to use the built-in OAuth feature of the Bot Framework. I use this in my bot without a hitch. I did navigate to the Google Hangouts web site and it recognized me immediately. By using the OAuth login, a token is returned which you can use to pass into the Hangouts adapter.
I should add that the below implementation produces a sign-in magic code which some people don't like (it doesn't bother me). There may be a SSO option, but I haven't researched that.
First, you need to setup Google credentials which will provide you with a "Client id" and "Client secret". General instructions can be found here. Credentials can be created here. You can ignore any coding references as they aren't necessary (thanks to the BF OAuth feature).
From the Credentials Page, click on "Credentials" in the left menu. There are two areas you need to configure, once there: "OAuth consent screen" and "Credentials".
For OAuth consent screen, provide an app name. This doesn't need to match the associated requesting app and is just for reference when visiting the Credentials Page. Enter a support email, the scopes you will be using (email, profile, and openid). There may be other required scopes, but this worked for me when I visited the Hangouts web site. Lastly, enter in the Authorized Domains. The botframework.com domain is required. Others, if any, you will have to experiment with. Save and return to the Credentials Page.
Click the "Create Credentials" button and complete the form. Give your credentials a name (again, not referenced anywhere else for this project), enter any authorized origins, and enter https://token.botframework.com/.auth/web/redirect as the authorized redirect URI. Save the settings, copy the "Client id" and "Client secret" somewhere, and navigate to Azure and into your bot's settings page.
Here, you need to create your bot's OAuth connection. This is done in the Settings blade. At the bottom of the blade is the "OAuth Connection Settings" section. Click the "Add Setting" button to get started.
Once in, give your connection a name. This name will be referenced by your bot in the next step, so save the name somewhere. Then, select Google from the list of Service Providers and paste the "Client id" and "Client secret", that you saved earlier, into the respective fields. In "Scopes", you will want to enter the same scope values you selected in your Google credentials app ("email profile openid"). Be sure they are space-separated when you enter them.
Lastly, you will want to model your OAuth login off of sample 18.bot-authentication from the Botbuilder-Samples repo. This builds in the functionality you need for enabling a user to log in via your bot.
Add the connection name you assigned to your Google connection setting for your bot into a .env file as a variable, like this: connectionName=<CONNECTION_NAME>.
When setting up the OAuth prompt, you will pass this variable in:
this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
connectionName: process.env.connectionName,
text: 'Please Sign In',
title: 'Sign In',
timeout: 300000
}));
At this point, your bot and login process should be good to go. Assuming the flow is setup correctly, a user should be able to login via the OAuth prompt, by use of a magic code. A token is returned back to the bot which will be accessible via the context on the next step. The token can then be saved to state and passed to the adapter for use. In the below bit, I'm using a simple waterfall with an oauthPrompt step and a loginResults step. The token is captured in the second step where I console log it.
async oauthPrompt(step) {
return await step.prompt(OAUTH_PROMPT, {
prompt: {
inputHint: 'ExpectingInput'
}
});
}
async loginResults(step) {
let tokenResponse = step.result;
console.log('TOKEN: ', tokenResponse);
if (tokenResponse != null) {
await step.context.sendActivity('You are now logged in.');
return await step.prompt(CONFIRM_PROMPT, 'Do you want to view your token?', ['yes', 'no']);
}
// Something went wrong, inform the user they were not logged in
await step.context.sendActivity('Login was not successful please try again');
return await step.endDialog();
}
Hope of help!
I created an issue on https://github.com/howdyai/botkit/issues/1722
Basically hangouts adapter expects a token in order to compare it to the token gotten from the hangouts chat api. But given that the token is not provided anymore by google, the authentication mechanism needs to change
I'm trining to create live stream on youtube using google API. Now it working only when I use oauth authorisation. When I use API key authorisation I get authorisation error (login required)
When I use oauth authorisation - it require to enter confirmation code each time I create new translation. Is it possible to use "liveStreams->insert" method of API with authorisation that does not require entering of confirmation code?
From what you are writing it appears to me that you haven't understood the concept of OAuth and when to use OAuth vs an API key.
Try to think about it this way: You, as a person, have a Google account. This Google account is not the same as your YouTube account (or, as it is more commonly refered to, your YouTube channel). But your Google account is associated with your YouTube channel (of which you can have multiple). Because you are logged in to your Google account and your channel and Google account are linked, the YouTube website knows who you are and gives you access to your channel.
Now you head over to the Google Cloud Console. Here you create a project, which is very similar to a YouTube account in the sense that it, too, is an independent account which in this case represents your app, but is linked to your Google account so the Cloud Console website knows to give you access to the project as long as you are logged-in to your Google account.
HOWEVER, your YouTube account is not linked to your Cloud Console project. When you make an API request with an API key, the API does not see you as in "your Google account", but rather your apps's Cloud Console Project. That's why with an API key, you can only access publicly available data (everything you could "see" when you browse YouTube while not being logged-in).
So, in order for an application to read private channel information or modify channel information, the API needs verification that whoever makes that request is actually allowed to do that. This is where OAuth comes into play.
When you say you have to provide the confirmation code for each request, I think you don't save the access token and refresh token. I highly recommend you read Using OAuth 2.0 to Access Google APIs and Obtaining authorization credentials over on Google Developers to help get you started.
I am trying to access Google play developer API https://developers.google.com/android-publisher/ to build an inapp purchase product for my company Application.
We have to get authorization to make a GET call to the Google play developer API. https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get
I followed the steps presented here. https://developers.google.com/android-publisher/authorization
Created an Oauth client and and also service account. The gmail account I used was part of the 'Users and permissions' in play.google.com console.
But when I tried to access the API, I got an error
As I started searching about this error, I understood that there is something else called 'API Access' in play.google.com. When I tried to access it, All I saw was
But I saw in other posts that there exists a screen with details like
https://i.stack.imgur.com/Hdjjy.png
So how can I go forward to access API. I did everything as mentioned in documentation of google but it didnt work. Also I dont have access to see the screen of 'API Access'.
Also I am confused, if you can create service accounts from both 'API Access' screen and also from 'credentials' screen in console.developers.com, which one should be used ?
Just to check you understand there are a few different APIs to do with in-app purchases.
Play billing library is designed to be used in your app. This is what allows users to buy things from your app
Configuring in app products. When your app supports in-app products you have to support what the products are and the prices. This is done via the Play console, either manually or in batches uploading CSV files.
Finally is the API you refer to in your question. This is not designed for use in your app, and you don't have to use it to support in-app products. Instead this API allows your server (not app) to validate a user's purchase. In order to use this API, you need to enable the "API access" in the page you found. This can only be enabled by the account owner for the Play console, for security reasons. You will need to find the Owner of your Google Play account, and get them to log in and create a service account which has API access.
I am able to access it now. I am not the owner of the Google Play console.That was the issue. You just have to go to API Access page and click on "create OAuth Client" or "create Service Account ".
You can use those credentials to access API from postman or through your code.
I made a members-only site that uses Google oauth2 to authorise users. The site is built with the Laravel framework and Artdarek's oath library.
When the authorization callback comes from Google, I lookup the user record in the DB by email and proceed to the protected page if the record exists, otherwise to a register page.
The problem is some of our members use two Google accounts. One user registered via his primary account (e.ge. a#gmail.com). The next day he returned and mistakenly tried to login with b#gmail.com. Naturally the system showed him the registration page. From that time on each time he visits the site the authentication mechanism sees him using his second (unwanted) set of credentials.
To resolve this one case I instructed him to logout of all accounts (on both sides), clear cookies and start from scratch but this is not a practical solution for all users. In same cases even this measure does not seem to correct the problem.
How can I solve this case? What is the right way to request oauth authentication and get them back from the right account? Can I force Google to ask the user with which account to proceed?
Google will automatically ask the user which account they want on an oauth request if they enable the account chooser.
I have logged into my Google Apps and my Google account, so for me on an oauth request, I get the following prompt:
In order to do the same for your user, they have to click "Stay signed in", but of course this is not advisable for public computers.
Beyond the above, I'm afraid not much can be done. - if they logged in with a#gmail.com at that time, these are the credentials you will receive.
They way I solve this problem is to have a field where the customer can add additional emails, and select one that is primary. I will then inspect against these emails when a request comes in to avoid duplicate user accounts.