How to retrieve data from YouTube Analytics API without user action? - youtube

I would to create a script launched by a cron job that periodically store data about my channel in a file. Those data are retrieved via YouTube Analytics API (not the ordinary YouTube API).
How can i achieve this result?
Are service access compatible with those API?

If this is just a once-off - for your account - running on a server/desktop that you trust, I think the best mechanism will be to:
Create an OAuth client ID for an "Installed application". Create a Google Cloud Console project, enable the API you need, register your application (under "APIs & Auth").
Go through the installed application flow once manually to grant yourself a refresh token - this will require you opening a browser and clicking through a consent screen.
Persist the refresh token.
On subsequent unattended runs, use the refresh token to get a fresh access token to make calls on your behalf.
If you are using Python - and have installed the Google API Python Client, the following code will do steps 2 - 4 for you (assuming you have already done step 1 and saved a client_secrets.json file):
import httplib2
from oauth2client.file import Storage
from oauth2client.client import flow_from_clientsecrets
from oauth2client.tools import run
from apiclient.discovery import build
storage = Storage("/path/to/saved_user_creds.dat")
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = run(flow_from_clientsecrets("/path/to/client_secrets.json", scope="https://www.googleapis.com/auth/yt-analytics.readonly"), storage)
http = credentials.authorize(httplib2.Http())
# Do your stuff - remember to pass the authenticated http object to execute methods
service = build("youtubeAnalytics", "v1")
result = service.object().method(name=value).execute(http=http)

Related

Google Youtube Api Access blocked: This app’s request is invalid

I am trying to access google youtube API using the auth2.0 method but am unable to get an access
token.
Given Below python code
import os
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
def main():
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
api_service_name = "youtube"
api_version = "v3"
client_secrets_file = "client.json"
channel_id='channeld'
# Get credentials and create an API client
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
credentials = flow.run_console()
youtube = googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
Not Sure What I am missing here ? can you help out any suggestion are welcomed
Click on the link error details. It will tell you the redirect uri your application is sending from.
Take that redirect uri and add it in google developer console, the redirect uri must exactly match.
Google OAuth2: How the fix redirect_uri_mismatch error. Part 2 server sided web applications.
web app vs installed app
The code you are using is designed for an installed application hence the oogle_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file So to use it you need to create installed application credetials You appear to have done that. This code will open up the web browser consent screen on the machine its running on. This code is not designed for running on a web server.
update
Open your credentials.json file there should be two redirect URIs in there delete the urn:ietf:wg:oauth:2.0:oob one

How do I authenticate against the Dynamics 365 Data Export Service API?

I've set up something called the Data Export Service for Dynamics 365 so that it replicates into an Azure SQL database. This is working as expected.
I'm trying to find a way to be proactively notified if this service encounters any errors. There does not appear to be a native way to do this through the setup in CRM itself, but they do provide an API. The Swagger page outlining all methods can be found here.
I'm trying to call the GetProfilesByOrganizationId method using Postman:
https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true
I'm having issues with authentication and always receive the following error:
"Message": "Received unauthenticated requestRequest Url https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true"
I have registered an application in Azure that has permission to access Dynamics 365 on behalf of the authenticated user which in this case is me, the administrator.
I have set the Type to OAuth 2.0 on the Authorization tab of Postman. I have requested an Access Token using the Grant Type of Authorization Code against the above application successfully. This has added a header to the request:
Key: Authorization
Value: Bearer BIGLONGACCESSTOKEN
Despite this header being present I still get the error mentioned above.
The API documentation implies the authentication is OAuth2 Implicit Grant Flow (click on any red exclamation mark in the documentation) but I can't get this to work in Postman. When I try to request a token with this method I get the error:
unsupported_response_type
... in the Postman console.
Any ideas how to authenticate (with Implicit Grant?) against this API in Postman?
(I'd accept C# examples if they're more appropriate, but I'd be surprised if Postman can't show me what I need)
It looks like the code sample shown by Microsoft can work if updated with newer methods and with some extra configuration in Azure that's not documented.
Azure configuration
By installing the Data Export service (and assuming it's all working) you'll have a new Enterprise Application listed in Azure AD as Crm Exporter.
To take advantage of this application and authenticate with the Data Export API you must configure an app of your own.
Go to the App registrations tab in Azure AD and add a new application registration.
Give it a name and set the Application type to Native. The redirect URI doesn't typically matter as long as it's valid.
Click the Manifest button to edit the manifest, change the property oauth2AllowImplicitFlow to true and save the changes.
The only other important configuration is Required permissions which should be set as below:
Windows Azure Active Directory
Delegated permissions
Sign in and read user profile
Data Export Service for Microsoft Dynamics 365 (Crm Exporter)
Delegated permissions
Have access to Data Export Service for Microsoft Dynamics 365 API
You will then need to click Grant Permissions.
C# changes
The updated method looks like this:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
string clientId = "11cfXXXX-XXXX-XXXX-XXXX-XXXXXXXXd020";
string user = "my.username#domain.com";
string password = "PASSWORD";
var authParam= await AuthenticationParameters.CreateFromResourceUrlAsync(
new Uri("https://discovery.crmreplication.azure.net/crm/exporter/aad/challenge")
);
var context = new AuthenticationContext(authParam.Authority, false);
var credentials = new UserPasswordCredential(user, password);
var token = await context.AcquireTokenAsync(authParam.Resource, clientId, credentials).AccessToken;
You can now query the Data Export API by providing the token as a header:
Authorization : Bearer eJ0y........Hgzk
curl -X GET --header 'Accept: application/json' 'https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=MyOrgId&status=true'

How to log in the HyperLedger Composer webApp with different user other than admin

I just started building a relatively simple supply-chain app by using HyperLedger Composer webApp. In my permission file, I will have several participants that specify which role can do what. It's easy to switch role inside the playground through the wallet. However, I can't find a way to switch at my Angular webApp.
I thought it can be called through the System endpoint in the composer REST Server. But when I trying to "GET" from the /system/identities nothing show up, even I have created several participants. Can someone enlighten me with some examples?
Thank you guys so much!
Developing multi-user application using the Hyperledger Composer REST Server
Firstly, some quick background. What is Hyperledger Composer? It’s a framework for rapidly building Blockchain business networks on top of a Blockchain platform, such as Hyperledger Fabric. It’s pretty cool. You can find some more information here: http://hyperledger.github.io/composer/
Blockchain is a technology for building networks that connect organizations together. Once started, a Blockchain network allows participants to transfer assets between each other by submitting transactions, and those transactions are recorded in an immutable ledger.
So once you have your Blockchain Network how do you integrate with your client application? One solution would be to call the Hyperledger Composer JavaScript APIs directly or you could use the Hyperledger Composer REST Server in multi-user mode.
The Hyperledger Composer REST Server will generate a set of REST endpoints from a Hyperledger Composer Model. The endpoints can then be called from a client application to interact with a Blockchain. When the client applications calls one of the REST endpoints, the REST server will then submit a transaction to the Blockchain. This transaction must be signed by a certificate to say which identity is being used to submit the transaction. When the REST server is started it must be given a identity to use and by defaults all transactions will be signed with this identity.
The REST server can be configured to use authentication. This allows a client application to authenticate with the REST server and then the REST server can distinguish between each of the clients.
However this still doesn’t allow the Blockchain to distinguish between clients. The REST server will still sign each transaction with the same certificate. To enable the REST server to sign each transaction with a different identity per authenticated client the REST server must be configured to use multi-user mode. Each authenticated client will then have a private wallet on the REST server that contains the identity that will be used to sign the transaction on behalf of the different authenticated clients.
This article shows how to configure the REST server for multi-user mode and how it can be called from a client application to add participants and identities and how to submit transactions that are signed by different identities. The client app is written using Angular and will use GitHub authentication to authenticate itself with the REST server. This is just one example of the type of authentication that can be used. The REST server uses an open source library called Passport and there are over 300 plugins that are available to use, eg. LDAP, Facebook, SAML, and Google.
If you haven’t downloaded Hyperledger Composer you can follow the instructions to setup your development environment here: https://hyperledger.github.io/composer/installing/development-tools.
Once you have the development environment setup you firstly need to create and deploy a business network. The one I have used in this article can be found here: https://github.com/caroline-church/collectable-penguin-app/blob/master/collectable-penguin-network.bna. The client app used can be found here: https://github.com/caroline-church/collectable-penguin-app. The app allows users (Collectors of penguins) to sign up and to buy penguins from a “wholesaler” and each user has their own set of penguins which they have bought.
To setup the app you first need to add an OAuth application to GitHub here: https://github.com/settings/developers.
The app needs to have two REST servers running. The first has no authentication and will run in single user mode. This REST server will just be used to create participants and identities when users sign up to the app. It can be started by using the following command.
composer-rest-server -c admin#collectable-penguin-network -p 3001
The second REST server will run in multi-user mode. Firstly you need to set an environment variable to set some properties for the REST server. The and properties can be found in the github OAuth app that was created previously. The successRedirect property is set to the url of where app is running.
export COMPOSER_PROVIDERS='{
"github": {
"provider": "github",
"module": "passport-github",
"clientID": "<CLIENT-ID>",
"clientSecret": "<CLIENT-SECRET>",
"authPath": "/auth/github",
"callbackURL": "/auth/github/callback",
"successRedirect": "http://localhost:4200?loggedIn=true",
"failureRedirect": "/"
}
}'
Once the environment variable is set then the second REST server can be started with the following command
composer-rest-server -c admin#collectable-penguin-network -m true
The client app can then call the REST endpoints. To start the user needs to authenticate with GitHub. This can be done be having a link on the page, the URL is the URL of the multi-user REST server e.g
Sign in with github
Then the user needs to sign up to the app. This data can then be used to create a participant and identity. In this case a Collector participant will be created.
The following will create a Collector participant using the single user REST server
return this.httpClient.post('http://localhost:3001/api/org.collectable.penguin.Collector', collector).toPromise()
The body of the post should be the data the user supplied e.g.
const collector = {
$class: 'org.collectable.penguin.Collector',
collectorId: 'carolineId',
firstName: 'Caroline',
lastName: 'Church'
};
Once the participant has been created then an identity can be issued for that participant, again using the single user REST server. The response type must be set to blob as this endpoint returns a business network card.
return this.httpClient.post('http://localhost:3001/api/system/identities/issue', identity, {responseType: 'blob'}).toPromise();
The body of the post should include the ID and participant created previously e.g.
const identity = {
participant: 'org.collectable.penguin.Collector#carolineId,
userID: carolineId,
options: {}
};
The newly created identity can then be added to the wallet of the multi-user REST server. The card from the previous call to the endpoint is used to create a new file object, this file object is then used to create some formData. A header is added to the request to set the content type to be multipart/form-data. The wallet import endpoint can then be called with the data. The withCredentials option is set in-order to create a cookie to pass the authentication token to the REST server.
const file = new File([cardData], 'myCard.card', {type: 'application/octet-stream', lastModified: Date.now()});
const formData = new FormData();
formData.append('card', file);
const headers = new HttpHeaders();
headers.set('Content-Type', 'multipart/form-data');
return this.httpClient.post('http://localhost:3000/api/wallet/import', formData, {withCredentials: true, headers}).toPromise();
Now the client is authenticated with the REST server and an identity has been added to the wallet the endpoints can now be called. The REST server will submit transactions that are signed with the identity that was previously added.
For example the following HTTP request will get all the available penguins
return this.httpClient.get('http://localhost:3000/api/queries/availablePenguins', {withCredentials: true}).toPromise();
And the next HTTP request will get the penguins that the authenticated user owns
return this.httpClient.get('http://localhost:3000/api/queries/myPenguins', {withCredentials: true}).toPromise();
So now you know how to create a multi-user application using the Hyperledger Composer REST Server! But one last thing. If you have tried running the app you may have noticed alot of pictures of penguins. These are all penguins owned by the Hyperledger Composer team and are given to (or thrown at) people who break the build!
https://medium.com/#CazChurchUk/developing-multi-user-application-using-the-hyperledger-composer-rest-server-b3b88e857ccc

Proper method of getting a server auth access token for a client to use with google analytics

I have a global account that has several views that I want to use on the server side to embed dashboards for the various views on the client side. From what I understand, I get an access token using a service account on the server side and can then send the access token to the client side whenever needed. I was wondering, is this the correct flow? Should the access token be per session?
The authorization on the client side shown here has a field for a server auth access token, but couldn't find documentation on the exact flow I wanted. Basically I'm unsure what the proper way of generating that server auth access token is. Any help/pointers would be very much appreciated.
[Here][1] is an example of how to set up server side auth. The above code creates a new token when anyone visits the site. You can see the endpoint that gets that access token [here][2].
Below are the general steps to get to a working version:
Step 1: Create a service account and download the JSON key
Step 2: Add the service account as a user in Google Analytics
Step 3: Use the JSON key data to request an access token
# service-account.py
import json
from oauth2client.client import SignedJwtAssertionCredentials
# The scope for the OAuth2 request.
SCOPE = 'https://www.googleapis.com/auth/analytics.readonly'
# The location of the key file with the key data.
KEY_FILEPATH = 'path/to/json-key.json'
# Load the key file's private data.
with open(KEY_FILEPATH) as key_file:
_key_data = json.load(key_file)
# Construct a credentials objects from the key data and OAuth2 scope.
_credentials = SignedJwtAssertionCredentials(
_key_data['client_email'], _key_data['private_key'], SCOPE)
# Defines a method to get an access token from the credentials object.
# The access token is automatically refreshed if it has expired.
def get_access_token():
return _credentials.get_access_token().access_token
Back to the client side:
Step 4: Load the Embed API library.
<script>
(function(w,d,s,g,js,fs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(f){this.q.push(f);}};
js=d.createElement(s);fs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fs.parentNode.insertBefore(js,fs);js.onload=function(){g.load('analytics');};
}(window,document,'script'));
</script>
Step 5: Add HTML containers to host the dashboard components.
<div id="chart-1-container"></div>
<div id="chart-2-container"></div>
Step 6: Write the dashboard code.
Use the access token obtained in step 3 to authorize the Embed API.
gapi.analytics.ready(function() {
/**
* Authorize the user with an access token obtained server side.
*/
gapi.analytics.auth.authorize({
'serverAuth': {
'access_token': '{{ ACCESS_TOKEN_FROM_SERVICE_ACCOUNT }}'
}
});
...
The additional work of creating an endpoint which returns the token depends on your back end implementation but the source code of how the demo does it can be found [here][2].
[1]: https://ga-dev-tools.appspot.com/embed-api/server-side-authorization/
[2]: https://github.com/googleanalytics/ga-dev-tools/blob/abb3c5a18160327a38bf5c7f07437dc402569cac/lib/controllers/server_side_auth.py
I'm not very familiar with Google Analytics, but as far as OAuth goes, the handling of access tokens and refresh tokens should all be on the server-side. The client receives an authorization code and provides that to the server, which then obtains the tokens and uses the tokens to obtain the data necessary. There shouldn't be any need to send an access token to the client.
It might be helpful to read this, which describes the standard OAuth flow:
https://developers.google.com/identity/protocols/OAuth2

How to make API requests with an access_token for a Service Account

My end goal is to be able to retrieve place details from Google's API.
I need to do this as a Service Account, since this is kicked off as a background task on my server. Service Accounts require you to exchange a JWT (JSON Web Token) for an access_token. I finally got that working and am receiving an access_token. Phew.
Now however, I don't know what to do with this access_token.
The Place Details API says that the key parameter is required, but I don't have a key. Just an access_token. Using that value for key or changing the name of the paramater to access_token is not working.
Ultimately I need to be able to hit a URL like so:
https://maps.googleapis.com/maps/api/place/details/json?reference={MY_REFERENCE}&sensor=false&key={MY_ACCESS_TOKEN}
How do I use my Access Token to make a request to the Google Place Detail APIs?
Update 1
Still no success, but I thought I'd post the details of my request in case there's something wrong with what I'm submitting to Google.
I'm using the JWT Ruby library, and here are the values of my claim set:
{
:iss => "54821520045-c8k5dhrjmiotbi9ni0salgf0f4iq5669#developer.gserviceaccount.com",
:scope => "https://www.googleapis.com/auth/places",
:aud => "https://accounts.google.com/o/oauth2/token",
:exp => (Time.now + 3600),
:iat => Time.now.to_i
}
Looks sane to me.
Create the service account and its credentials
You need to create a service account and its credentials. During this procedure you need to gather three items that will be used later for the Google Apps domain-wide delegation of authority and in your code to authorize with your service account. These three items are your service account:
• Client ID.
• Private key file.
• Email address.
In order to do this, you first need a working Google APIs Console project with the Google Calendar API enabled. Follow these steps:
Go to the Google APIs Console.
Open your existing project or create a new project.
Go to the Service section.
Enable the Calendar API (and potentially other APIs you need access to).
You can now create the service account and its credentials. Follow these steps:
Go to the API Access section.
Create a client ID by clicking Create an OAuth 2.0 client ID...
Enter a product name, specify an optional logo and click Next.
Select Service account when asked for your Application type and click Create client ID.
At this point you will be presented with a dialog allowing you to download the Private Key as a file (see image below). Make sure to download and keep that file securely, as there will be no way to download it again from the APIs Console.
After downloading the file and closing the dialog, you will be able to get the service account's email address and client ID.
You should now have gathered your service account's Private Key file, Client ID and email address. You are ready to delegate domain-wide authority to your service account.
Delegate domain-wide authority to your service account
The service account that you created now needs to be granted access to the Google Apps domain’s user data that you want to access. The following tasks have to be performed by an administrator of the Google Apps domain:
Go to your Google Apps domain’s control panel. The URL should look like: www.google.com/a/cpanel/mydomain.com
Go to Advanced tools... > Manage third party OAuth Client access.
In the Client name field enter the service account's Client ID.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to (see image below). For example if you need domain-wide access to the Google Calendar API enter: www.googleapis.com/auth/calendar.readonly
Click the Authorize button.
Your service account now has domain-wide access to the Google Calendar API for all the users of your domain, and potentially the other APIs you’ve listed in the example above.
Below is a description that uses a service account to access calendar data in PHP
The general process for service account access to user calendars is a follows:
• Create the Google client
• Set the client application name
• If you already have an Access token then check to see if it is expired
• If the Access token is expired then set the JWT assertion credentials and get a new token
• Set the client id
• Create a new calendar service object based on the Google client
• Retrieve the calendar events
Note: You must save the Access token and only refresh it when it is about to expire otherwise you will receive an error that you have exceeded the limit for the number of access tokens in a time period for a user.
Explanation of Google PHP Client library functions used:
The client object has access to many parameters and methods all of the following are accessed through the client object:
Create a new client object:
$client = new Google_Client();
Set the client application name:
$client->setApplicationName(“My Calendar App”);
Set the client access token if you already have one saved:
$client->setAccessToken($myAccessToken);
Check to see if the Access token has expired, there is a 30 second buffer, so this will return true if the token is set to expire in 30 seconds or less. The lifetime of an Access token is one hour. The Access token is actually a JSON object which contains the time of creation, it’s lifetime in seconds, and the token itself. Therefore no call is made to Google as the token has all of the information locally to determine when it will expire.
$client->isAccessTokenExpired();
If the token has expired or you have never retrieved a token then you will need to set the assertion credentials in order to get an Access token:
$client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME,array(CALENDAR_SCOPE), $key,'notasecret','http://oauth.net/grant_type/jwt/1.0/bearer',$email_add));
Where:
SERVICE_ACCOUNT_NAME is the the service account email address setup earlier.
For example:’abcd1234567890#developer.gserviceaccount.com’
CALENDAR_SCOPE is the scope setup in the Google admin interface.
For example: ‘https://www.googleapis.com/auth/calendar.readonly’
$key is the content of the key file downloaded when you created the project in Google apps console.
$email_add is the Google email address of the user for whom you want to retrieve calendar data.
Set the client id:
$client-setClientId(SERVICE_CLIENT_ID);
Where:
SERVICE_CLIENT_ID is the service account client ID setup earlier.
For example: ‘abcd123456780.apps.googleusercontent.com’
Create a new calendar service object:
$cal = new Google_CalendarService($client);
Several options can be set for calendar retrieval I set a few of them in the code below, they are defined in the api document.
$optEvents = array('timeMax' => $TimeMax, 'timeMin' => $TimeMin, 'orderBy' => 'startTime', 'singleEvents' => 'True');
Get the list of calendar events and pass the above options to the call:
$calEvents = $cal->events->listEvents('primary', $optEvents);
Loop through the returned event list, the list is paged so we need to fetch pages until the list is exhausted:
foreach ($calEvents->getItems() as $event) {
// get event data
$Summary = $event->getSummary();
$description = $event->getDescription();
$pageToken = $calEvents->getNextPageToken();
if ($pageToken) { // if we got a token the fetch the next page of events.
$optParams = array('pageToken' => $pageToken);
$calEvents = $cal->events->listEvents('primary', $optParams);
} else {
break;
}
}
Get the Access token:
$myAccessToken=$client->getAccessToken();
Save the access token to your permanent store for the next time.
The language isn't important php, ruby, .net, java the process is the same. The api's console shows the Places API as supporting service accounts so it should be possible to access it.
As far as using the token please have a look at https://code.google.com/p/google-api-ruby-client/ code as the usage is clearly defined in the code repository. Doesn't make any difference if the access token is for a service account or a single user the process for using the token is the same. See the section titled "Calling a Google API" in the following link: https://developers.google.com/accounts/docs/OAuth2InstalledApp
The access token is sent in the http authorization header along with the request.For a calendar request it would look something like the following:
GET /calendar/v3/calendars/primary HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: OAuth ya29.AHES6ZTY56eJ0LLHz3U7wc-AgoKz0CXg6OSU7wQA

Resources