I am trying to stream video using the Youtube api.
I want to stream video in private mode.
Here is my code for the same
`const {google} = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(
//CLIENT_ID
//CLIENT SCRETE
// YOUR_REDIRECT_URL
);
oauth2Client.setCredentials({
access_token: //access token,
refresh_token: //refresh token
});
oauth2Client.refreshAccessToken((err, tokens) => {
});
const youtube = google.youtube({
version: 'v3',
auth : oauth2Client
});
broadcastParams = {
"part": "snippet,status,contentDetails",
"resource": {
"snippet": {
"title": "into the starry sky..",
//"scheduledStartTime": "2018-03-04T20:50:00.000Z",
// "scheduledEndTime": "2018-03-03T18:05:00.000Z",
},
"status": {
"privacyStatus": "private",
},
"contentDetails": {
"monitorStream": {
"enableMonitorStream": true,
}
},
"cdn": ''
}
};
// TODO watch the auth parameters in broadcasting in the console testing
youtube.broadcast.insert(broadcastParams, function (err, broadcast) {
if (err) {
return console.log('Error creating broadcast: ', err);
}
console.log('Broadcast = ' + broadcast.valueOf());
});`
But I want to add participant's email address so as to make them see the private video which only the added person could see.
If there is any way to do this please help me out.
Thanks in advance
[1]: http://developers.google.com/youtube/v3/
After some research I came to know that YouTube's private videos require that the viewer have a YouTube account, be signed into that account and have that account added to the video's access list. Its also limited to 50 people only.
And also need to change the contentDetails parameter from monitorStream to broadcast stream. But need to explicitly invite people and there is no other way to invite people using API.
So for most of the case it's preferred to use unlisted for the streaming which means person with the link can view the video and It can be embedded in website too.
Related
I have a typical web app with a client and a node.js server. When a user selects an option on the client, I want to export (create) a google doc in their drive.
I am half way there following this tutorial https://developers.google.com/identity/protocols/oauth2/web-server
With my current set up, after the user authenticates, the authentication token is sent to a web hook (server side), but I don't have any of the data for creating the google doc there.
If I did, I could create the doc from there. Otherwise, I need to send the token itself back to the client so I can create the doc with the necessary payload from there.
In that case, I don't know how to signal to the client that the user has been authenticated. Should I use a web socket?
Something tells me that my general set up might not be correct, and that I should be doing it a different way in my use case.
This is my client side code that brings the user to the google auth page after getting the auth url (not sure if this really needs to be done server side, but since I have some user credentials I thought it might be better).
export async function exportToGoogleDoc() {
const response = await POST(`${API_URL}export/gdoc`, {
'hello': 'world'
});
if (response.status == 200){
window.location.href = response.authUrl;
}
}
And then the endpoint (just returns the autheticationUrl)
api.post('/export/gdoc', express.raw({ type: 'application/json' }), async (req, res, next) => {
try {
const scopes = [
'https://www.googleapis.com/auth/drive'
];
const oauth2Client = new google.auth.OAuth2(
credentials.web.client_id,
credentials.web.client_secret,
credentials.web.redirect_uris[0]
);
const authorizationUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
include_granted_scopes: true
});
res.json({ 'status': 200, authUrl : authorizationUrl } );
} catch (err){
next(err);
}
});
But then after the user agrees and authenticates with their google account, the auth token is sent to this web hook. At the bottom I am able to write an empty google doc to the authenticated google drive, but I don't have the data I need to create the real doc.
api.get('/auth/google', express.raw({ type: 'application/json' }), async (req, res, next) => {
const q = url.parse(req.url, true).query;
const oauth2Client = new google.auth.OAuth2(
credentials.web.client_id,
credentials.web.client_secret,
credentials.web.redirect_uris[0]
);
if (q.error) {
console.log('Error:' + q.error);
} else {
const { tokens } = await oauth2Client.getToken(q.code.toString());
oauth2Client.setCredentials(tokens);
const drive = google.drive('v3');
const requestBody = {
'name': 'Dabble',
'mimeType': 'application/vnd.google-apps.document',
};
drive.files.create({
requestBody: requestBody,
fields: 'id',
auth: oauth2Client
}, function (err, file) {
if (err) {
// Handle error
console.error(err);
} else {
console.log('File Id: ', file);
}
});
}
Somehow I either need to get the data for the google doc inside this web hook, or to listen for this web hook from the client.
OR I need an entirely different set up. I realize I also should be probably storing this token somewhere (local storage on client side?) and only making this call if they do not have a token.
Can anyone help me modify my set up? Thanks!
My Assistant app gets a status of PEMISSION_DENIED with a message saying that
the caller does not have permission
I have followed all instructions here by this person: Digital Goods Implementation
I have created APK, managed SKU (valid status) items, Android app that became published (valid status), enabled Actions API from Google API Console and made a service account key for my project, and released my Assistant app for beta to test it. The Connect App status is connected and the toggle is on. I think everything required is completed but the error message does not get fixed, which means I cannot receive purchasable items I prepared in my Google Developer Console.
const createJwtClient = () => {
const scopes = [
"https://www.googleapis.com/auth/actions.purchases.digital"
];
return new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes,
null
);
};
const packageName = 'com.myproject.name'
const getSkus = (tokens, conv) => {
return new Promise((resolve, reject) => {
const url = `https://actions.googleapis.com/v3/packages/${packageName}/skus:batchGet`;
const convId = conv.request.conversation.conversationId;
const param = {
conversationId: convId,
skuType: "SKU_TYPE_IN_APP",
ids: [
"item-id1",
"item-id2"
]
};
request.post(url, {
auth: {
bearer: tokens.access_token
},
json: true,
body: param
}, (err, httpResponse, body) => {
if (err) {
reject(err);
} else {
const statusCode = httpResponse.statusCode;
const statusMessage = httpResponse.statusMessage;
console.log(`${statusCode}: ${statusMessage}`);
console.log(JSON.stringify(body));
resolve(body);
}
});
});
};
I expect I get purchasable items as JSON, but my request to fetch SKU seems to fail.
But I do receive access_token from JWT request using my service account key.
Could you point out something that is wrong??
First, make sure your testing email is different from the Play Console Admin's email. Second, ensure you've added managed products and subscriptions to the Google Play Console (see below) The Actions on Google Github sample has been recently updated as well and the Kotlin APK has all the specifics in the 'Getting Started' section of the readme.
I'm trying to retrieve the name of a logged in user using Google API Node.js Client, using OAuth2 API.
Following the usage example, I managed to do the login, but I can't find a way to get the profile information.
I'm not using People API nor Plus API, cause as far as i know, OAuth2 includes https://www.googleapis.com/auth/userinfo.profile, which should be enough for the task.
I have seen some similar questions and tried the solutions of this one but it didn't work, maybe it's too old (?)
With the npm package googleapis how do I get the user's email address after authenticating them?
Looking at other API's like Google Sheets, it's possible to call their functions like this:
var google = require('googleapis');
var sheets = google.sheets('v4');
...
sheets.spreadsheets.values.get({
auth: auth,
spreadsheetId: file_id,
range: my_ranges,
}, function(err, response){
...
}
);
But it seems that OAuth2 doesn't work like that...
You can use Quickstart for node.js. The detail information is https://developers.google.com/gmail/api/quickstart/nodejs. Using a sample script from Quickstart, you can retrieve access token by OAuth2, and retrieve email and user profile.
Before it runs a sample of Quickstart, please confirm Prerequisites, Step 1 and Step 2.
You can use by changing listLabels(auth) as follows. The scope is https://www.googleapis.com/auth/gmail.readonly.
Script :
var gmail = google.gmail({
auth: auth,
version: 'v1'
});
gmail.users.getProfile({
auth: auth,
userId: 'me'
}, function(err, res) {
if (err) {
console.log(err);
} else {
console.log(res);
}
});
gmail.users.messages.get({
'userId': 'me',
'id': 'mail ID',
'format': 'raw'
}, function (err, res) {
console.log(new Buffer(res.raw, 'base64').toString())
});
gmail.users.getProfile retrieves user profile.
gmail.users.messages.get retrieves email.
If I misunderstand your question, I'm sorry.
Added :
Please change above to following script. Scope is https://www.googleapis.com/auth/userinfo.profile.
Script :
var oauth2 = google.oauth2({
auth: auth,
version: 'v2'
});
oauth2.userinfo.v2.me.get(
function(err, res) {
if (err) {
console.log(err);
} else {
console.log(res);
}
});
Result :
{
id: '#####',
name: '#####',
given_name: '#####',
family_name: '#####',
link: '#####',
picture: '#####',
gender: '#####',
locale: '#####'
}
2021 Solution
This answer may divert from the originally asked question but I think it will be useful for some people who are getting google user information in the backend by generating AuthUrl and sending it to the client side and then receiving the data response in the call back URL after the user gives permission from the client side.
Some global declarations
import { google } from "googleapis";
const Oauth2Client = new google.auth.OAuth2(
googleCredentials.CLIENT_ID,
googleCredentials.CLIENT_SECRET,
googleCredentials.REDIRECT_URI
);
Generate the Auth URL with the scopes
const SCOPE = [
'https://www.googleapis.com/auth/userinfo.profile', // get user info
'https://www.googleapis.com/auth/userinfo.email', // get user email ID and if its verified or not
];
const auth_url = Oauth2Client.generateAuthUrl({
access_type: "offline",
scope: SCOPE,
prompt: "consent",
state: "GOOGLE_LOGIN",
});
return res.json({ url: auth_url }); // send the Auth URL to the front end
Get the user data in the callback
let code = req.query.code; // get the code from req, need to get access_token for the user
let { tokens } = await Oauth2Client.getToken(code); // get tokens
let oauth2Client = new google.auth.OAuth2(); // create new auth client
oauth2Client.setCredentials({access_token: tokens.access_token}); // use the new auth client with the access_token
let oauth2 = google.oauth2({
auth: oauth2Client,
version: 'v2'
});
let { data } = await oauth2.userinfo.get(); // get user info
console.log(data); // you will find name, email, picture etc. here
Feel free to discuss in the comments if there's any confusion or error
You can also look into PassportJS. They have multiple strategies, including OAuth2 and 3 different Google Auth strategies. My answer doesn't really answer your question but maybe even taking a peek at Passport's code, you may get your answer.
http://passportjs.org/
I am trying to upload videos from server without any manual authentication by user in the client side . I tried the below code snippet for video upload but it authenticates the user in the browser and asks for the acceptance of the app.
var ResumableUpload = require('node-youtube-resumable-upload');
var googleauth = require('google-auth-cli');
var google = require('googleapis');
var getTokens = function(callback) {
googleauth({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/youtube.upload' //can do just 'youtube', but 'youtube.upload' is more restrictive
},
{ client_id: CLIENT_ID, //replace with your client_id and _secret
client_secret: CLIENT_SECRET,
port: 3000
},
function(err, authClient, tokens) {
console.log(tokens);
callback(tokens);
});
};
getTokens(function(result) {
tokens = result;
upload();
});
var upload = function() {
var metadata = {snippet: { title: 'title', description: 'Uploaded with ResumableUpload' },
status: { privacyStatus: 'public' }};
var resumableUpload = new ResumableUpload(); //create new ResumableUpload
resumableUpload.tokens = tokens;
resumableUpload.filepath = 'youtube/test4.mp4';
resumableUpload.metadata = metadata;
resumableUpload.monitor = true;
resumableUpload.eventEmitter.on('progress', function(progress) {
console.log(progress);
});
resumableUpload.initUpload(function(result) {
console.log(result);
return;
});
}
But for my app it should directly upload the video to youtube from the server. For that I need the access token and refresh token I tried lot to get the access token directly but I couldn't able to get it.
So any help or idea to how to make the video upload directly from server to a channel account. I searched lot in google for a node module to do that but I couldn't able to find it.
I have been using this approach to upload video
Getting the web based generated token using the client library.
Getting the youtube upload permission from user for my application &
access_type=offline.
Access type offline gives refresh token in response. This token
will help to continue upload from backend server token when its
expires.
After getting the permission. It will redirect to URL with code.
Using the given code generate access_token
Save this token for future use.
Use the same token to push the video from your server to youtube
server
Refresh the token when it expires.
But is there any way to implement this approach without getting the youtube upload permission from user for my application.
You can do server side authetication using google API(JWT) with "Service Account". But direct upload from your server to youtube server without user permission is not possible. For uploading the video google needs OAuth2.0 authentication. It will give you error unAuthorized(401)- youtubeSignupRequired with "Service Account" using JWT authentication.
Becuase of the above limitation. You have use below Approach to work with this is-
Get the web based generated token using the client library.
Get the youtube upload permission from user for your application & access_type=offline.
Access type offline gives you refresh token in response. This token will help you to continue upload from backend server token when its expires.
After getting the permission. It will redirect to URL with code.
Using the given code generate access_token
Save this token for future use.
Use the same token to push the video from your server to youtube server
Refresh the token when it expires. And follow the step 3 - 5 again.
Currently this is the only way to upload the video on youtube.
Added the code on git repository nodejs-upload-youtube-video-using-google-api
For why its not possible? Check the below reference link & code:
From google API Doc: This error is commonly seen if you try to use the OAuth 2.0 Service Account flow. YouTube does not support Service Accounts, and if you attempt to authenticate using a Service Account, you will get this error. You can check all the error code & its detail using link: YouTube Data API - Errors
From gadata Issues: Youtube v3 Google Service Account Access
From google blog spot:List of Google API supported using Service Account
Check below code to get access_token from server side
You can check it yourself using below steps & code:
Go to Google Developer Console
Create Project
To Get Google+ API Access go to: APIs & Auth->APIs ->enable YouTube Data API v3
To Enable Service Account go to: APIs & Auth->Credentials->Create new Client ID->Click on Service Account->Create Client Id
Save the secret file on your system & keep it secure.
Create the secret key using below command & file you have downloaded:
openssl pkcs12 -in /home/rajesh/Downloads/Yourkeyfile.p12 -out youtube.pem -nodes
- Enter password: ***notasecret***
6. You can authorize & access api from server side as below:
var google = require('googleapis');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem', #path to pem file which we create using step 6
null,
['https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
console.log(tokens);
});
Get youtube video list using Service Account(working):
var google = require('googleapis');
var youtube = google.youtube('v3');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
youtube.videos.list({auth:authClient,part:'snippet',chart:'mostPopular'}, function(err, resp) {
console.log(resp);
console.log(err);
});
});
Insert youtube video using Service Account and googleapis module:
var google = require('googleapis');
var youtube = google.youtube('v3');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
youtube.videos.insert({auth:authClient,part:'snippet,status,contentDetails'},function(err,resp)
console.log(resp);
console.log(err);
});
});
Insert/Upload API Returned below Error:
{ errors:
[ { domain: 'youtube.header',
reason: 'youtubeSignupRequired',
message: 'Unauthorized',
locationType: 'header',
location: 'Authorization' } ],
code: 401,
message: 'Unauthorized' }
Insert youtube video using Service Account and ResumableUpload module:
var google = require('googleapis');
var ResumableUpload = require('node-youtube-resumable-upload');
var authClient = new google.auth.JWT(
'Service account client email address', #You will get "Email address" in developer console for Service Account:
'youtube.pem',
null,
['https://www.googleapis.com/auth/youtube','https://www.googleapis.com/auth/youtube.upload'],
null
);
authClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
var metadata = {snippet: { title: 'title', description: 'Uploaded with ResumableUpload' },status: { privacyStatus: 'private' }};
var resumableUpload = new ResumableUpload(); //create new ResumableUpload
resumableUpload.tokens = tokens;
resumableUpload.filepath = 'youtube.3gp';
resumableUpload.metadata = metadata;
resumableUpload.monitor = true;
resumableUpload.eventEmitter.on('progress', function(progress) {
console.log(progress);
});
resumableUpload.initUpload(function(result) {
console.log(result);
return;
});
});
Insert/Upload API Returned below Error:
{ 'www-authenticate': 'Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token',
'content-type': 'application/json; charset=UTF-8',
'content-length': '255',
date: 'Tue, 16 Sep 2014 10:21:53 GMT',
server: 'UploadServer ("Built on Aug 18 2014 11:58:36 (1408388316)")',
'alternate-protocol': '443:quic,p=0.002' }
Screen shot attached for "How to get google key?"
Conclusion: Uploading a video without user permission is not possible.
I do my PHD work dedicated to Social Network Analysis.
As tools was selected Node JS and Facebook API
Now what I can do is retrieve user's ID's with the additional info, but to build graph I need lists of the user's friends.
I have Heroku App but I'm totally disappointed what to do with te APP_ID to get information needed to build data.
Where I should start?
There are some Node.js packages available for this purpose.
Third party SDKs for Facebook
This is very useful, in case you want to write the same code and share between your server (nodejs) and the client (FB JS-SDK)
In order to start, you need to have access_tokens from users, you want information from. (Through FB App)
FB.login(function(response) {
if (response.authResponse) {
var res = response.authResponse;
FB.api('/me', function(response) {
registerUser({ "fb_user_id": res.userID, //register user in your database
"access_token": res.accessToken
}, function() {
//handle here after registration
});
});
} else {
//handle reject in requested fields
}
}, { scope: 'email,friends_about_me'});
//you can set scope field according to your use.
Refer to this for extended profile properties that can be used in scope field.
Once you get access_tokens, you can use them with one of the third party SDK above.
For example with facebook-node-sdk,
This sdk also provides you request access_token api
var FB = require('fb');
var accessToken = FB.getAccessToken();
FB.setAccessToken(accessToken);
FB.api('idHere', { fields: ['id', 'name'] }, function (res) { //you can access fields, access_token has access to
if(!res || res.error) {
console.log(!res ? 'error occurred' : res.error);
return;
}
console.log(res.id);
console.log(res.name);
});
You can also use api function directly with access_token.
FB.api('me', { fields: ['id', 'name'], access_token: 'access_token' }, function (res) {
console.log(res);
}