Google YouTube API v3 :: Server-to-Server Upload Service - youtube-api

Our project lets users upload videos to OUR public youtube channel when they are signed into our session. We do not want to require additional OAuth2 verification, and instead follow the follow of Google API v2.
My code (php) and error are below, but my general question is: can my server make the insert-video POST using my API key/secrets without requiring the user to authenticate.
This question - Google Calendar API v3 hardcoded credentials - is very similar. Howevr if CURLing Google for the access_token is the only answer, i'll be disappointed. Thanks regardless.
Google API V3 Settings:
Client ID: xxxx.apps.googleusercontent.com
Email address: xxxx#developer.gserviceaccount.com
Client secret: xxxx
Redirect URIs: http://fbtabs.imagendigital.co/unilever/sedal/surprise/galeria
JavaScript origins: https://fbtabs.imagendigital.co
API key:
AIzaSyBgS-jMJQUPIiAyX20xC-encFWTPsR7qxQ
Referers:
Any referer allowed
Activated on: Jul 4, 2013 1:21 PM
Activated by: xxxx#gmail.com – you
Code:
<?php
require_once BASE_CD . 'app/src/Idframework/Tools.php';
require_once BASE_CD . 'app/vendor/google-api-php-client/src/Google_Client.php';
require_once BASE_CD . 'app/vendor/google-api-php-client/src/contrib/Google_YouTubeService.php';
$client = new Google_Client();
$client->setApplicationName('Google+ PHP Starter Application');
$client->setClientId('xxx.apps.googleusercontent.com');
$client->setClientSecret('xxxx');
$client->setRedirectUri('http://fbtabs.imagendigital.co/unilever/sedal/surprise/galeria');
$client->setDeveloperKey('xxxx');
$youtube = new Google_YoutubeService($client);
$snippet = new Google_VideoSnippet();
$status = new Google_VideoStatus();
$video = new Google_Video();
if (isset($_POST['tip_desc'])) $snippet->setDescription($_POST['tip_desc']);
$snippet->setTitle($_POST['tip_name']);
$snippet->setTags(array("sedal","hair","pello","cabello"));
$status->privacyStatus = "public";
$video->setSnippet($snippet);
$video->setStatus($status);
$filename = $_FILES['videoInp']['tmp_name'];
$mime = \Idframework\Tools::get_mime($filename);
try {
$part = "status";
$obj = $youtube->videos->insert($part, $video,
array("data"=>file_get_contents($filename),
"mimeType" => $mime));
} catch(Google_ServiceException $e) {
print "Caught Google service Exception ".$e->getCode(). " message is ".$e->getMessage(). " <br>";
print "Stack trace is ".$e->getTraceAsString();
}
Error:
Notice: Undefined index: content-type in C:\DATA\IDInteractive\SedalSurprise\app\vendor\google-api-php-client\src\service\Google_MediaFileUpload.php on line 99
Caught Google service Exception 401 message is Error calling POST https://www.googleapis.com/upload/youtube/v3/videos?part=player&uploadType=multipart&key=AIzaSyBgS-jMJQUPIiAyX20xC-encFWTPsR7qxQ: (401) Login Required
Stack trace is #0 C:\DATA\IDInteractive\SedalSurprise\app\vendor\google-api-php-client\src\io\Google_REST.php(36): Google_REST::decodeHttpResponse(Object(Google_HttpRequest)) #1 C:\DATA\IDInteractive\SedalSurprise\app\vendor\google-api-php-client\src\service\Google_ServiceResource.php(186): Google_REST::execute(Object(Google_HttpRequest)) #2 C:\DATA\IDInteractive\SedalSurprise\app\vendor\google-api-php-client\src\contrib\Google_YouTubeService.php(789): Google_ServiceResource->__call('insert', Array) #3 C:\DATA\IDInteractive\SedalSurprise\youtuber.php(56): Google_VideosServiceResource->insert('player', Object(Google_Video), Array) #4 {main}

First off, letting arbitrary users upload videos into a "master" YouTube channel is not recommended, for the reasons outlined in this blog post.
That being said, if you're determined to do it, then you need to include an access token associated with your channel in each upload request. The appropriate way to get a fresh access token (they expire after an hour) is to take a refresh token that you've previously generated and stored somewhere and make an HTTP request to the appropriate URL to get back an access token, as explained in the OAuth 2 documentation. There's no way around that—I'm not sure whether there's a native method in the Google APIs PHP client library that will automate the process for you, but that's what needs to happen under the hood.
The information in Google Calendar API v3 hardcoded credentials does seem relevant.

Related

goog api homegraph - scope

I want to control (read) statuses of a smart swithc associated in my google home app. I did a similat application using the smartdevice api and i am able to control a google thermostat.
Now back to the smart switch, i read that I need to use the homegraph api (correct me if i'm wrong). I followed the docs on google api and tried many times with oauth , setting the scope https://www.googleapis.com/auth/homegraph (as per this link https://developers.google.com/identity/protocols/oauth2/scopes). When I send the request to get the token i receive an error that this scope is not authorised.
Authorization Error
Error 400: invalid_scope
Some requested scopes cannot be shown: [https://www.googleapis.com/auth/homegraph]
my code is below, can anyone lighten me up what is the issue? I searched and there is no php code example fro this type of implementation with the homegraph.
require_once('vendor/autoload.php');
$client = new Google\Client();
$client->setAuthConfig('client_secret_oauth.apps.googleusercontent.com.json');
$client->addScope( 'https://www.googleapis.com/auth/homegraph' );
$client->setRedirectUri('https://' . $_SERVER['HTTP_HOST'] . '/homegraph-api/oauth2callback.php');
$client->setAccessType('offline');
$client->setIncludeGrantedScopes(true);
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
// code for google client api to interact with homegraph
Thank you.

MIcrosoft Graph get token request failing due to CORS

I am trying to get an access token to access one drive of the user inside the word online add-in. I am following the instructions on this link.
I used following URL to request authorization code from within ms word online add-in which I am developing.
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=code
&redirect_uri=http://localhost/myapp/
&response_mode=query
&scope=offline_access user.read mail.read
&state=12345
I generate GET request with the following code:
function getAuthorizationCode() {
var xhr = new XMLHttpRequest();
xhr.open(
"GET",
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?\
client_id=6731de76-14a6-49ae-97bc-6eba6914391e\
&response_type=code\
&response_mode=query\
&scope=offline_access%20user.read%20mail.read\
&state=12345",
true
);
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);
xhr.onreadystatechange = processRequest;
function processRequest(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
}
}
}
But server is throwing error saying
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:3000' is therefore not allowed access.
If the above link is copied and pasted into the browser it works fine.
What should I do? Is there any other way to get access token inside MS Word Online add-in.
Office Web Add-ins include support for pulling a token based on the application user. This provides an SSO experience and eliminates the need to have them re-authenticate using the same credentials that they've already logged into the application with.
You can read about this functionality at Enable single sign-on for Office Add-ins.

Microsoft Graph API access token validation failure

I use this URL to get id_token:
https://login.microsoftonline.com/common/oauth2/authorize?
response_type=id_token%20code&
client_id=MY_CLIENT_GUID_ID_IN_HERE&
redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fopenid%2Freturn&nonce=alfaYYCTxBK8oypM&
state=6DnAi0%2FICAWaH14e
and this return result like this
http://localhost:3000/auth/openid/return?
code=AAA_code_in_here&
id_token=eyJ0eXAi_xxxx_yyyy_in_here&
state=6DnAi0%2FICAWaH14e&
session_state=xxxx_guid_xxxxx
and then i use the id_token to query Graph (use POST man)
i have see this post InvalidAuthenticationToken and CompactToken issues - Microsoft Graph using PHP Curl but make no sense.
OATH 2.0 requires multiple steps. The first request returns an OAUTH Code. The next step is converting that OATUH code into a Bearer Token. This is the step you are missing here.
I would also recommend using the v2 Endpoint which is a lot easier to work with (particularly with Graph). I wrote a v2 Endpoint Primer that walks through the process and may be helpful as well.
You can't use the token directly, there is one more step to exchange the code you get from the response url into token.
Here is my C# code (using Microsoft.IdentityModel.Clients.ActiveDirectory)
public static AuthenticationResult ExchangeCodeForToken(string InTenantName, string InUserObjId, string InRedirectUri, string InApplicationAzureClientID, string InApplicationAzureClientAppKey)
{
Check.Require(!string.IsNullOrEmpty(InTenantName), "InTenantName must be provided");
Check.Require(!string.IsNullOrEmpty(InUserObjId), "InUserObjId must be provided");
if (CanCompleteSignIn) //redirect from sign-in
{
var clientCredential = new ClientCredential(InApplicationAzureClientID, InApplicationAzureClientAppKey);
var authContext = new AuthenticationContext(Globals.GetLoginAuthority(InTenantName), (TokenCache)new ADALTokenCache(InUserObjId)); //Login Authority is https://login.microsoftonline.com/TenantName
return authContext.AcquireTokenByAuthorizationCode(VerificationCode, new Uri(InRedirectUri), clientCredential, Globals.AZURE_GRAPH_API_RESOURCE_ID); //RESOURCE_ID is "https://graph.microsoft.com/"
}
return null;
}
I had this issue today when I was playing with graph API, the problem in my case was how I was generating the token.
I used postman for generating the token wherein the Auth URL section I was adding the resource = client_id whereas it should be the graph URL. After making that change I was able to make the call via postman.
In order for the above to work, please make sure your application in Azure has delegated permissions to access the Graph API.
To receive the access token and use it for profile requests, you don't need anything from server-side, you can implement the oAuth2 just from the client side.
Use the following URL for login:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=YOUR_CLIENT_ID&resource=https://graph.microsoft.com&response_type=token&redirect_uri=YOUR_REDIRECT_URI&scope=User.ReadBasic.All
After successful login, user will redirected to the page with access_token parameter. Then use the following AJAX call to fetch user info:
var token = login_window.location.href.split('access_token=').pop().split('&')[0];
$.ajax({
url: "https://graph.microsoft.com/v1.0/me",
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Bearer '+token);},
success: function(data) {
alert('Hi '+data.displayName);
console.log(data);
}
});
Note that you may need to enable oauth2AllowImplicitFlow:true setting from your Azure Active Directory application manifest file.
Set "oauth2AllowImplicitFlow": false to "oauth2AllowImplicitFlow": true.
Lastly, ensure that your app has required permissions for Microsoft Graph which are sign in users and View users' basic profile
An updated answer to get access with new applications:
Register your app in the app registration portal.
Authorization request example:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345
Authorization response will look like this:
https://localhost/myapp/?code=M0ab92efe-b6fd-df08-87dc-2c6500a7f84d&state=12345
Get a token
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps
Use the access token to call Microsoft Graph
GET https://graph.microsoft.com/v1.0/me
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: graph.microsoft.com
Source:
https://learn.microsoft.com/en-us/graph/auth-v2-user?context=graph/api/1.0
You can also get an access token without a user, see here:
https://learn.microsoft.com/en-us/graph/auth-v2-service

Google Analytics API Returning 401 On Example Code

I am attempting to retrieve the data from our content experiments from google analytics...
I am using the following code, my creds are good, and have been censored for this post...
<?php
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';
session_start();
$client = new Google_Client();
$client->setApplicationName('Hello Analytics API Sample');
// Visit https://cloud.google.com/console to generate your
// client id, client secret, and to register your redirect uri.
$client->setDeveloperKey('xxxxx');
$service = new Google_Service_Analytics($client);
try {
$results = $service->management_experiments->listManagementExperiments('xxxx', 'xxxx', 'xxxx');
} catch (apiServiceException $e) {
print 'There was an Analytics API service error ' . $e->getCode() . ':' . $e->getMessage();
} catch (apiException $e) {
print 'There was a general API error ' . $e->getCode() . ':' . $e->getMessage();
}
echo '<pre>';
print_r($results);
echo '</pre>';
I am using the following example ....
https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtExperimentsGuide#list
Any ideas on why I am getting a 401 unauthorized? That a login is required?
The problem is that you haven't Authorized access to your data yet. Since you say its only your own data you want to access i sugest you look into a service account. By setting up a service account in Google apis console it will allow you to access your own data with out needing to login and autenticate the code all the time.
Check the following link. Read though Before you begin make sure you do all that.
https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtExperimentsGuide#service
Register your application in the Google Developers Console
Authorize access to Google Analytics data.
Create an Analytics service object
You have skiped the first two steps and gone directly to step 3 creating the service object. Once you have done step 1 you can use the following code for step 2.
Here is an example of how to use a service account in php ServiceAccount
That sample project is for the PredictionService not the google analytics service. You need to edit it slightly.
require_once '../../src/Google/Client.php';
require_once '../../src/Google/Service/Analytics.php';
// Set your client id, service account name, and the path to your private key.
// For more information about obtaining these keys, visit:
// https://developers.google.com/console/help/#service_accounts
const CLIENT_ID = 'INSERT_YOUR_CLIENT_ID';
const SERVICE_ACCOUNT_NAME = 'INSERT_YOUR_SERVICE_ACCOUNT_NAME';
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
const KEY_FILE = '/super/secret/path/to/key.p12';
$client = new Google_Client();
$client->setApplicationName("Google Analytics Sample");
// Load the key in PKCS 12 format (you need to download this from the
// Google API Console when the service account was created.
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME(Email),
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents(KEY_FILE))
);
$client->setClientId(CLIENT_ID);
$service = new Google_Service_Analytics($client);
Now you have $service that you can use with the rest of your calls. Note: I didnt have time to test that code let me know if it doesnt work and i will give you a hand in fixing it.

How to use OAuth access for GMail with libEtPan?

Does anyone have sample code or clear instructions on how to use libEtPan to connect to a GMail account using OAuth? I couldn't find anything.
Details for OAuth in GMail are here: http://code.google.com/apis/gmail/oauth/
libetpan has some documentation in its header files, for IMAP it's in https://github.com/dinhviethoa/libetpan/blob/master/src/low-level/imap/mailimap_oauth2.h
/*
mailimap_oauth2_authenticate()
Authenticates the client using using an oauth2 token.
To gather a deeper understanding of the OAuth2 aunthentication
process refer to: https://developers.google.com/gmail/xoauth2_protocol
For a quick start you may follow this brief set of steps:
1. Set up a profile for your app in the Google
API Console: https://code.google.com/apis/console
2. With your recently obtained client_id and secret
load the following URL (everything goes ina single line):
https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&
&access_type=offline
3. The user most follow instructions to authorize application access
to Gmail.
4. After the user hits the "Accept" button it will be redirected to another
page where the access token will be issued.
5. Now from the app we need and authorization token, to get one we issue a POST request
the following URL: https://accounts.google.com/o/oauth2/token using these parameters:
client_id: This is the client id we got from step 1
client_secret: Client secret as we got it from step 1
code: This is the code we received in step 4
redirect_uri: This is a redirect URI where the access token will be sent, for non
web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1)
grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens
6. After step 5 completes we receive a JSON object similar to:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF",
"expires_in":3920,
"token_type":"Bearer"
}
The above output gives us the access_token, now we need to also retrieve the user's e-mail,
to do that we need to perform an HTTP GET request to Google's UserInfo API using this URL:
https://www.googleapis.com/oauth2/v1/userinfo?access_token=[YOUR_ACCESS_TOKEN]
this will return the following JSON output:
{
"id": "00000000000002222220000000",
"email": "email#example.com",
"verified_email": true
}
#param session IMAP session
#param auth_user Authentication user (tipically an e-mail address, depends on server)
#param access_token OAuth2 access token
#return the return code is one of MAILIMAP_ERROR_XXX or
MAILIMAP_NO_ERROR codes
*/
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char * auth_user,
const char * access_token);
LIBETPAN_EXPORT
int mailimap_has_xoauth2(mailimap * session);
I haven't tried it out myself yet, but when I get around to implement it I'll post a link of the implementation.
Update March 2021
I finally got around to implement support for Google OAuth 2.0 in my email client nmail now. The commit can be viewed here but essentially I ended up doing steps 2-6 above in a separate external script, as libetpan does not do the token generation/refresh for us. The token handling is fairly straight-forward - see oauth2nmail.py for example.

Resources