Google.GoogleApiException was unhandled by user code - google-reseller-api

I am having trouble connecting to the Google Apps Reseller API (for .NET) using the service credentials model.
Any ideas of where I am going wrong?
Steps:
Created service application in google developer console
Enabled APIs (Admin SDK; BigQuery API; Debuglet Controller API; Enterprise; License Manager API; Google Apps Reseller API ; Google Cloud Logging API ; Google Cloud SQL; Google Cloud Storage; Google Cloud Storage JSON API; Site Verification API)
Created API permissions on Google apps domain (reseller domain)
Source:
=====================
using Google.Apis.Auth.OAuth2;
using Google.Apis.Reseller.v1;
using Google.Apis.Reseller.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
namespace GoogleApiWeb
{
public partial class _Default : Page
{
static string ApplicationName = "Testing API";
protected void Page_Load(object sender, EventArgs e)
{
String serviceAccountEmail = "...removed...#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"C:\\Dev\\GoogleApiWeb\\GoogleApiWeb\\TestingResellerAPI-6555.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { ResellerService.Scope.AppsOrder }
}.FromCertificate(certificate));
// Create Google Apps Reseller API service.
var service = new ResellerService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request.
SubscriptionsResource.ListRequest request = service.Subscriptions.List();
request.MaxResults = 10;
// List subscriptions.
IList<Subscription> subscriptions = request.Execute().SubscriptionsValue;
Response.Write("<p>Subscriptions:</p>");
if (subscriptions != null && subscriptions.Count > 0)
{
foreach (var subscription in subscriptions)
{
{
Response.Write(subscription.CustomerId.ToString());
Response.Write(": ");
Response.Write(subscription.SkuId.ToString());
Response.Write(" ");
Response.Write(subscription.Plan.PlanName.ToString());
Response.Write('\n');
}
}
}
else
{
Response.Write("No subscriptions found.");
}
}
}
}
Application error:
Google.GoogleApiException was unhandled by user code
HResult=-2146233088
Message=Google.Apis.Requests.RequestError
Forbidden [403]
Errors [
Message[Forbidden] Location[ - ] Reason[forbidden] Domain[global]
]
Source=Google.Apis
ServiceName=reseller
StackTrace:
at Google.Apis.Requests.ClientServiceRequest`1.Execute() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\test\default\Src\GoogleApis\Apis\Requests\ClientServiceRequest.cs:line 96
at GoogleApiWeb._Default.Page_Load(Object sender, EventArgs e) in c:\Dev\GoogleApiWeb\GoogleApiWeb\Default.aspx.cs:line 53
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:

Related

SMTP gmx server problam

Im tyring to send an email with my program to an gmx email. Every time I try to send the mail I get the same error message in my console.
What can be the solution for that?
The error message:
System.Net.Mail.SmtpException: SMTP server requiers secure connection or the client wasnt authenticated. server response was: authentication required.
in - System.Net.Mail.SendMailAsyncResult.End(IAsyncResult result)
in - System.Net.Mail.SmtpClient.SendMailCallback(IAsyncResult result)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.ComponentModel;
namespace SMTP_Client
{
class Program
{
static bool mailSent = false;
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this asynchronous operation.
String token = (string)e.UserState;
if (e.Cancelled)
{
Console.WriteLine("[{0}] Send canceled.", token);
}
if (e.Error != null)
{
Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
}
else
{
Console.WriteLine("Message sent.");
}
mailSent = true;
}
public static void Main(string[] args)
{
SmtpClient client = new SmtpClient("smtp.gmx.com",25);
MailAddress from = new MailAddress("example#project.com", "me " + (char)0xD8 + " you", System.Text.Encoding.UTF8);
MailAddress to = new MailAddress("example#gmx.com");
MailMessage message = new MailMessage(from, to);
message.Body = "The project has succeeded ";
message.Subject = "made it!";
client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
string userState = "test message2\n";
client.SendAsync(message, userState);
Console.WriteLine("Sending message... press c to cancel mail. Press any other key to exit.");
string answer = Console.ReadLine();
if (answer.StartsWith("c") && mailSent == false)
{
client.SendAsyncCancel();
}
message.Dispose();
Console.WriteLine("proccess ended.");
}
}
}

Cannot find files that I uploaded to google drive using google drive sdk

I am using .NET SDK for google drive.
I have successfully managed to upload a file on google drive but when I log in using browser cannot see the file there?
Here is my code:
private string privKey = "-----BEGIN PRIVATE KEY-----\MYKEYHERE-----END PRIVATE KEY-----\n";
private string[] scopes = { DriveService.Scope.Drive };
string serviceAccountEmail = "<myaccounthere>";
public File uploadToDrive(string uploadFilePath)
{
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromPrivateKey(privKey));
BaseClientService.Initializer initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
};
// Create Drive API service.
var service = new DriveService(initializer);
if (!string.IsNullOrEmpty(uploadFilePath))
{
File fileMetadata = new File();
fileMetadata.Name = System.IO.Path.GetFileName(uploadFilePath);
fileMetadata.MimeType = GetMimeType(uploadFilePath);
try
{
System.IO.FileStream uploadStream = new System.IO.FileStream(uploadFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
FilesResource.CreateMediaUpload request = service.Files.Create(fileMetadata, uploadStream, GetMimeType(uploadFilePath));
request.ProgressChanged += Upload_ProgressChanged;
request.ResponseReceived += UploadRequest_ResponseReceived;
var task = request.UploadAsync();
task.ContinueWith(t =>
{
});
return request.ResponseBody;
}
catch (System.IO.IOException iox)
{
return null;
}
catch (Exception e)
{
//Log
return null;
}
}
else
{
//Log file does not exist
return null;
}
}
private string GetMimeType(string fileName)
{
string mimeType = "application/unknown";
string ext = System.IO.Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}
private void Upload_ProgressChanged(IUploadProgress progress)
{
Debug.WriteLine(progress.Status + " " + progress.BytesSent);
}
private void UploadRequest_ResponseReceived(Google.Apis.Drive.v3.Data.File file)
{
Debug.WriteLine(file.Name + " was uploaded successfully");
}
Does anyone happen to know what am I doing wrong?
Thanks in advance
If that doesn't work, you can try the suggested answer in this related SO question:
Since you are using a Service Account, all the folders and files will be created in this Service Account's Drive which cannot be accessed through a web UI and will be limited to the default quota.
To add content in a user's Drive, you will need to go through the regular OAuth 2.0 flow to retrieve credentials from this user. You can find more information about OAuth 2.0 on this pages:
Retrieve and use OAuth 2.0 credentials.
Quickstart: it has a quickstart sample in C# that you could use.
Using OAuth 2.0 to access Google APIs
Hope this helps!
Yes you are right. Service accounts have this limitation. For anyone that has the same problem what I did (using .NET) to overcome this was to enable Domain-Wide delegation and impersonate the account that I needed.
e.g my service account is srv1#myaccount.gserviceaccount.com impersonates srv1#gmail.com
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("srv1#myaccount.gserviceaccount.com")
{
Scopes = new string[] { DriveService.Scope.Drive },
User = "srv1#gmail.com"
}.FromPrivateKey(PRIVATE_KEY));
When I login to google drive using srv1#gmail.com I can now see the files

Google Drive REST API (Server to Server): no binding with account files

I try getting list of Google Drive files from my application (simple Google account)(https://developers.google.com/identity/protocols/OAuth2ServiceAccount)
List with OAuth2 authorization work perfect: https://developers.google.com/drive/v3/reference/files/list#try-it
I've create service account with delegation to Google Apps domain (https://console.developers.google.com/iam-admin/serviceaccounts):
and download json service key.
Apply to GD from application:
private static HttpTransport HTTP_TRANSPORT;
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
public static void main(String[] args) throws IOException {
Credential credential = GoogleCredential
.fromStream(new FileInputStream(".\\config\\google_drive_api.json"))
.createScoped(DriveScopes.all());
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName("javawebinar-1314").build();
FileList result = service.files().list().execute();
List<File> files = result.getFiles();
System.out.println(files.size());
API work: result at the beginning was single "Getting started" file, now result is 0. It seems that service account has no any relation to my own and delegating to doman has no meening for me as I have no domain account.
Are there any possibility to manage my simple google account google drive files by REST API ?

Getting domain installs for my Google Docs Add-on

We have a Google-docs Add-on (built on Google Apps Script) for which we enabled the Google Apps Marketplace SDK - so that Google Apps Administrators could install our add-on at the domain level.
We have noticed a few domains have now installed our add-on - but I can't seem to find a way to get information on which domains have installed us. Is it even possible?
I have tried the Marketplace license API https://developers.google.com/apps-marketplace/v2/reference/ but it fails with a 403 error - Not authorized to access the application ID.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "Not authorized to access the application ID"
}
],
"code": 403,
"message": "Not authorized to access the application ID"
}
}
I even tried by creating a service account and accessed the API using the service account but got the same error.
Any input would be awesome.
Here's my Java (Groovy technically) code so far (the response is the json I've pasted above):
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.http.GenericUrl
import com.google.api.client.http.HttpRequest
import com.google.api.client.http.HttpRequestFactory
import com.google.api.client.http.HttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import org.springframework.security.access.annotation.Secured
class DataController {
/**
* Be sure to specify the name of your application. If the application name is {#code null} or
* blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
*/
private static final String APPLICATION_NAME = "My app name";
private static final String APPLICATION_ID = "12 digit project number";
/** E-mail address of the service account. */
private static final String SERVICE_ACCOUNT_EMAIL = "12digitproejectnumber-compute#developer.gserviceaccount.com";
/** Global instance of the HTTP transport. */
private static HttpTransport httpTransport;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
def getLicensedInfo() {
try {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/appsmarketplace.license"))
.setServiceAccountPrivateKeyFromP12File(new File("a/valid/path/to/key.p12"))
.build();
credential.refreshToken();
String token = credential.getAccessToken();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl("https://www.googleapis.com/appsmarket/v2/licenseNotification/"+APPLICATION_ID);
HttpRequest request = requestFactory.buildGetRequest(url);
com.google.api.client.http.HttpResponse response = request.execute();
log.debug(response.parseAsString());
return;
} catch (IOException e) {
System.err.println(e.getMessage());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
When making the request to the GAM License API you need to use the same Google Developers Console project that you used for your listing. In the case of an add-on, this is the console project associated with the script.

Android App: Acquire Access Token for Google Drive API

I am writing an Android (version ICS) app. which uploads data to the Google Drive. The app
uses oauth2 to acquire the access token.
First step: acquire authorization token.
String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/drive";
// Step 1
accountManager.getAuthToken(
account, // Account retrieved using getAccountsByType("com.google")
AUTH_TOKEN_TYPE, // Auth Token Type
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnAuthTokenError())); // Callback called if an error occurs
}
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
#Override
public void run(AccountManagerFuture<Bundle> result) {
// Get the result of the operation from the AccountManagerFuture.
Bundle bundle;
try {
bundle = result.getResult();
authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
Log.d(TAG,"authToken:" + authToken);
exchangeToken access = (exchangeToken) new exchangeToken().execute();
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (AuthenticatorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Success. An authorization token is acquired.
Step 2: Exchange authorization token for Access Token.
private class exchangeToken extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new GsonFactory();
String CLIENT_ID = "999999999999.apps.googleusercontent.com";
String CLIENT_SECRET = "axXXXXXXXXXXXXXXX7";
try { // Step 2: Exchange for an access and refresh token
GoogleTokenResponse authResponse = new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, CLIENT_ID, CLIENT_SECRET, authToken, CALLBACK_URL).execute();
accessToken = authResponse.getAccessToken();
Log.d("Get Access","Token:" + accessToken);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Fail. The LogCat shows the following:
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error":"unauthorized_client"
}
I have been able to access "Google Drive" on my Android tablet using the "Drive" app. so
my email account is valid. May be the AUTH_TOKEN_TYPE is incorrect, but the Google Drive
SDK is not clear what it must be. What am I missing?
You do not need to do the second step of exchanging the token. Android grants you an access token directly, it does not grant you an auth code which you would have to exchange for tokens.
This page on the Android documentation explains everything really well.
You know that for using the Drive API your users have to install your app on the Chrome(!) Webstore?
Normally Documents List API is the better choice from Android.