Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth showing Access Denied - youtube-data-api

I'm using Youtube V3 .net library in my web application. It is working fine on my local machine. But While I deploy it on my local IIS and try it on browser then it is showing me below exception:
Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=201573269273-eoteo6aj8hqq3343qi0qvc6378qt3q22.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A54419%2Fauthorize%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.upload" for authorization. See inner exception for details.
And In it inner exception it is showing me Access Denied.
Please help out in this.
I'm using following code:
UserCredential credential;
using (var stream = new FileStream(JsonClient, FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
BLL.Error.Insert("UserCredential", "No Error", "No Error");
}
Thanks In advance.

Related

Google Drive API's file Export endpoint is failing with API Key authentication?

Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
I have a Windows Service that creates and sends daily course emails for an educational group. The source content for each email is stored in a Google Drive, as a Google Doc, so that the faculty can update the course content easily.
This has been working flawlessly for the past year, but suddenly stopped working about 27-Mar-2018. Since then, I can retrieve the file details;
_googleDriveHtmlContent.LoadFile(
fileId
);
But not the contents. When I Export the file as HTML, I immediately get a DownloadStatus.Failed from the ProgressChanged handler;
var request = _driveService.Files.Export(
fileId,
"text/html"
);
I'm using API keys for security, rather than OAuth, since it's a UI-less service. To do this I need to mark the file folders as publicly accessible - specifically I'm using "Accessible to everyone, with link." This has been working great.
I've updated to the latest API v3 libraries through NuGet, with no change in behavior.
Using Google's API Explorer, I'm seeing a similar behavior.
I can retrieve my file successfully using the API Explorer with the get endpoint.
https://developers.google.com/drive/v3/reference/files/get
fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
Authentication: API key (uses a "demo API key")
But with the export endpoint, I get an Internal Error (500)-
https://developers.google.com/drive/v3/reference/files/export
fileId 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
mimeType: text/html
Authentication: API key (uses a "demo API key")
Changing the Authentication in the API Explorer to OAuth 2.0, and approving access, then returns a successful 200 result with the file HTML. However I'm unable to do that since I'm accessing the API via a UI-less service.
Has anything changed recently with the Google Drive APIs and specifically the Export function, which would cause it to fail while using API Key access after 27-Mar-2018?
Its possible but its most likely a stealth change that you will not get any official word on. Not that long ago i saw someone posting a similar question they were using an API key to update a Google sheet and it suddenly stopped working.
IMO if google has changed this its probably a good thing. API keys are meant for accessing public data. Setting a document to public is a really bad idea if anyone did manage to find the file ID of your document they would then be able to update your document.
Suggestion:
What you should be using is a Service account. Service accounts are dummy users by creating service account credentials on Google developer console and then taking the service account email address you can share the file on Google Drive with the service account granting it access to said file without the need of making the file public.
You havent specified what language you are using but you said you were making a windows service so i am going to assume you are using .net. Here is an example of service account authencation with the Google .net client library.
public static DriveService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
throw new Exception("Path to the service account credentials file is required.");
if (!File.Exists(serviceAccountCredentialFilePath))
throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
if (string.IsNullOrEmpty(serviceAccountEmail))
throw new Exception("ServiceAccountEmail is required.");
// For Json file
if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
{
GoogleCredential credential;
using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}
// Create the Analytics service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive Service account Authentication Sample",
});
}
else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
{ // If its a P12 file
var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
// Create the Drive service.
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive Authentication Sample",
});
}
else
{
throw new Exception("Unsupported Service accounts credentials.");
}
}
catch (Exception ex)
{
throw new Exception("CreateServiceAccountDriveFailed", ex);
}
}
}
code ripped from serviceaccount.cs. Assuming that you were already using the Google .net client library the service this method returns will be the same drive service you were using with an api key.
Once you have granted your service account access to the file it will be able to access the file when ever it needs there is no authentication needed as you have preauthorized it by sharing the file with it.

Error: Access Denied on IIS using Google Youtube Data API V3 Oauth service

I have created a web page (youtubeuploader.aspx) in asp.net to upload Video to youtube channel on button click.
The video file location say eg:
'd:\\youtubevdos\\test.3gp'.
I have hosted this web application in IIS7.
This page works fine on local machine with proper Oauth2.0 authentication and Video is uploaded to youtube channel. But, it wont work when hosted on web server i mean IIS server
It gives error:
"Access Denied" Access to path/directory 'App_Data' is denied.
UserCredential credential;
//string googleaccesstoken = Server.MapPath("mygooglestorage");
string googleaccesstoken = "D:\\websites\\mygooglestorage\\";
//using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
using (var stream = new FileStream(jsonpath, FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload, YouTubeService.Scope.YoutubeUpload, YouTubeService.Scope.Youtube },
"user",
CancellationToken.None,
new FileDataStore(googleaccesstoken)
);
}
I have tried following ways:
Explicitly setting the FileDataStore while authentication i.e specifying file location something to 'D:\websites\myproj\authkey\' but still same error.
Created a folder in hosted location as given above and given access rights as 'FullControl' to folder still same error.
Note: i am using GoogleAuthorizationCodeFlow, Google Youtube API v3, OAuth2.0
Any suggestions?
Help Appreciated!
Try this - Give all permissions to app data folder for users - IUSER and Network Service.
Try this:
new FileDataStore(googleaccesstoken, true)
The second parameter is to indicate that fullPath is absolute.

Windows Store App Push Notifications via Azure Service Bus

I'm trying to send a push notification to my Windows Store App developed in my laptop using VS 2013 Express. It's been few days now but I cannot figure out why I get "The Token obtained from the Token Provider is wrong" error. I use Windows Azure Notification Bus for this purpose. I use VS Server Explorer to send test notifications. I can see my laptop is being registered as a device in the Device Registration tab too. I tried the Azure portal as well, but the same error. However, when I try to connect to Service Bus Explorer 2.4.3.0 providing the connection string it throws below error.
<21:47:14> Exception: The remote server returned an error: (401) Unauthorized. Manage claim is required for this operation..TrackingId:c0c4fea2-08bc-4def-964c-ec6e690b7551_G45,TimeStamp:10/12/2014 4:17:11 PM. Method b__7e: retry 2 of 10.
FYI: I'm following below article step by step.
http://azure.microsoft.com/en-us/documentation/articles/notification-hubs-windows-store-dotnet-get-started/
Please help me. Thank you.
Mahesh
Looks like token is just expired. Make sure you obtain token each time application starts. In terms of the article you refer it means you should call method InitNotificationsAsync() to do it. Here is that method:
private async void InitNotificationsAsync()
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("<hub name>", "<connection string with listen access>");
var result = await hub.RegisterNativeAsync(channel.Uri);
// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}

Google Domain Shared Contacts API Using OAuth 2.0 for Server to Server Applications - Credential params

I'm trying to get the "Google Domain Shared Contacts API" described here:
https://developers.google.com/admin-sdk/domain-shared-contacts/
Working using "OAuth 2.0 for Server to Server Applications" described here:
https://developers.google.com/accounts/docs/OAuth2ServiceAccount
The recommendation from the OAuth page is to use the provided Google client library... I'm using the Java library. But the Shared-Contacts API doesn't have an example that uses this library, and I'm having trouble figuring out how to use the library with the Shared-Contacts API.
I am able to make the example for the OAuth to work for me... It uses Google Cloud Storage. Here's a snippet of the code:
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
try {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
String p12Content = Files.readFirstLine(new File(keyFile), Charset.defaultCharset());
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
.setServiceAccountPrivateKeyFromP12File(new File(keyFile))
.build();
// Set up and execute Google Cloud Storage request.
String URI;
URI = "https://storage.googleapis.com/" + BUCKET_NAME;
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl(URI);
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse response = request.execute();
content = response.parseAsString();
} catch (IOException e) {
System.err.println(e.getMessage());
}
} catch (Throwable t) {
t.printStackTrace();
}
return content;
It's a request to get a listing of what's in a certain bucket on GCS. It calls a specific URL using the Credentials object, where the Credentials object does the work of the OAuth, using a key file I downloaded. There's other steps involved for getting it to work (setting the service account email, etc), which I did. It returns an xml string containing what is inside the bucket, and it works fine for me.
I then tried changing the URI to this string:
URI = "https://www.google.com/m8/feeds/contacts/myGoogleAppsDomain.com/full";
and I changed the STORAGE_SCOPE variable to be this string:
STORAGE_SCOPE = "http://www.google.com/m8/feeds/";
Hoping it would then return an xml-string of the shared-contacts. But instead, it returns this error:
403 Cannot request contacts belonging to another domain
I believe I'm getting this error because I'm not specifying the "hd" parameter when I do the authentication request... However, I'm unsure how I can specify the "hd" parameter using the GoogleCredential object (or the other parameters, except for "scope")... Can someone help me with that?
I think the issue here is that you are not specifying which user you want to impersonate in the domain (and you haven't configured the security settings in your domain to authorize the service account to impersonate users in the domain).
The doubleclick API auth documentation has good examples on how to do this. You can use their sample and replace the scopes and API endpoint:
https://developers.google.com/doubleclick-publishers/docs/service_accounts#benefits

Getting a 403 - Forbidden for Google Service Account

I am trying to get an access token for Google Service Account. Following is my code -
String SERVICE_ACCOUNT_EMAIL = "edited#developer.gserviceaccount.com";
List scope = new ArrayList();
scope.add("https://www.googleapis.com/auth/admin.directory.user");
String keyFile = "C:\\edited-privatekey.p12";
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(scope)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(keyFile))
.build();
credential.refreshToken();
String accessTokens = credential.getAccessToken();
Although the code works fine and I do get an access token, when I try to use it to 'GET' a Google Apps User using the Google Directory APIs, I get a 403 - Forbidden response code. Could someone please help?
I know the code for GET user is correct because it works fine with the access token generated by Google Apps Admin.
You need to set an admin account with:
.setServiceAccountUser(some_admin_email)
And make sure your App (with the correct scopes) is granted access in the cpanel.
Proceed to https://admin.google.com . Login and add Security control if not exists from More Controls.
Click on Security->Advance Settings->Manage ThirdParty OAuth Client Access and check that those scopes are added(comma separated) for your xxxxxxxxxxxxxxxxxx.apps.googleusercontent.com service account id/client id.
You have to enable the specific api before using it inside https://console.developers.google.com/ library, to make it work with your api key.
watch the video https://www.youtube.com/watch?v=s_G5CnAu69M.

Resources