Google Drive Api in MVC C# - c#

I'm doing project in MVC C#, and working Google Drive Api.
I was on the site daimto.com and I took the samples and put in my MVC application.
In site https://console.developers.google.com/apis/ and create two credencias:
The license for name Cliente Padrão works locally, the license Site SESMT should run on the server, but to access the page that has the release access, the site is thinking and thinking goes nowhere, it seems caught . My license to use on the server is as follows:
I've looked examples on the internet, but it's all for local application and nothing for Web application. I'm thinking that something is missing.
Question
My page is thinking and thinking goes nowhere and does not show the authorization screen. Funny that in my local environment works
My Code
Autorização
public static DriveService AuthenticateOauth(string clientId, string clientSecret, string userName)
{
string[] scopes = new string[] { DriveService.Scope.Drive, // view and manage your files and documents
DriveService.Scope.DriveAppdata, // view and manage its own configuration data
DriveService.Scope.DriveAppsReadonly, // view your drive apps
DriveService.Scope.DriveFile, // view and manage files created by this app
DriveService.Scope.DriveMetadataReadonly, // view metadata for files
DriveService.Scope.DriveReadonly, // view files and documents on your drive
DriveService.Scope.DriveScripts }; // modify your app scripts
var folder = System.Web.HttpContext.Current.Server.MapPath("/App_Data/GoogleDriveApi");
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, new FileDataStore(folder)).Result;
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "site-sesmt"
});
return service;
}
Controller
public ActionResult Index()
{
string CLIENT_ID = "***.apps.googleusercontent.com";
string CLIENT_SECRET = "***";
DriveService service = GoogleApi.AuthenticateOauth(CLIENT_ID, CLIENT_SECRET, "portalsesmt");
return View();
}

I've encountered a similar problem a few weeks back when I was doing the exact same thing. If you are using Oauth 2.0, you have to enable the Google+ API in Google API Console->Dashboard->Enable API->Google+ API.
At least this solved the problem for me for some reason. I think google changed their APIs or something. Try that out and let me know if it worked.

Related

Workspace Domain-wide Delegation with service account not working for one project, works for others

We have different projects on GCP we use them to access different Google APIs. Most of them for internal use only.
In this particular case, we have 2 projects, both use Service Account and both are allowed on Workspace Domain-wide Delegation on the same scopes. They are almost clones of each other.
I execute a simple request with the same code (Spreadsheet.Get()) with project 1 credentials it works. I execute the same request with project 2 credentials it doesn't work.
Since Workspace Domain-wide Delegation it's activated the spreadsheet its shared to my email and I connect to the API with my email too (works with project 1 so this is not the problem) (impersonating a user)
The only difference it's that one project has OAuth Consent Screen on external (only 100 users cause we use it internally only, anyways..) and the other one it's internal but this has nothing to do with this right?
Where the problem could come from? Do I need to recreate the project that doesn't work?
Here is the error message :
Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested
Edit to answer the comments but this code works depending on the service account we use
Generating the credentials:
internal static ServiceCredential GetApiCredentialsFromJson(string jsonCredentialsPath, string mailToMimic)
{
string jsonCertificate = File.ReadAllText(jsonCredentialsPath);
string privateKey = Regex.Match(jsonCertificate, #"(?<=""private_key"": "")(.*)(?="")").Value.Replace(#"\n", "");
string accountEmail = Regex.Match(jsonCertificate, #"(?<=""client_email"": "")(.*)(?="")").Value;
ServiceAccountCredential.Initializer credentials = new ServiceAccountCredential.Initializer(accountEmail)
{
Scopes = _scopes,
User = mailToMimic
}.FromPrivateKey(privateKey);
return new ServiceAccountCredential(credentials);
}
Using the credentials:
internal GoogleSheetService(ServiceCredential credentials)
{
SheetsService = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials
});
SheetsService.HttpClient.Timeout = TimeSpan.FromSeconds(100);
}
Client ID is allowed on the Drive, Ads and Spreadsheets scopes on the Workspace console.
The answer was simple, but we had to figure it out by ourselves.
The scopes you add in your app when you initialize the client need to be exactly the same scopes you added in the Google Admin wide-delegation page. Even if your app or part of your app don't need them all.
C# example:
private static readonly string[] _scopes = { DriveService.Scope.Drive, SheetsService.Scope.Spreadsheets, SlidesService.Scope.Presentations };
ServiceAccountCredential.Initializer credentials = new ServiceAccountCredential.Initializer(accountEmail)
{
Scopes = _scopes,
User = mailToMimic
}.FromPrivateKey(privateKey);
return new ServiceAccountCredential(credentials);
Here my app only needs SheetsService.Scope.Spreadsheets but I had to add DriveService.Scope.Drive and SlidesService.Scope.Presentations because the same client its used for other apps that need them.

How to make a Google Home Graph request using a Service Account?

I want to create a Desktop Application which would control Google Home Devices. For the past couple of hours I've been struggling with the Google Homegraph authentication process.
I created a Service Account and added the JSON file to the project's file. I am creating the credentials this way:
string[] Scopes = { HomeGraphServiceService.Scope.Homegraph };
using (FileStream stream = new FileStream("ServiceCredentials.json", FileMode.Open, FileAccess.ReadWrite))
{
ServiceCred = ServiceAccountCredential.FromServiceAccountData(stream);
GoogleCredential credentials = GoogleCredential.FromServiceAccountCredential(ServiceCred).CreateScoped(Scopes);
var service = new HomeGraphServiceService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "Test Application"
});
}
To create any request, I need to provide a AgentUserId. Any ID from the ServiceCred or the service itself (ApiKey) results in an exception with a code 400 error. The credentials (of type GoogleCredential) don't have any sort of Id that I can provide.
How to make a request with a Service Account to get devices from the Google Home Graph?
Another thing is, when I try to add the HomeGraphServiceService.Scope.Homegraph scope anywhere in the Google Project - API Playground, this Application - it results in a code 400 error - Invalid Scope on the OAuth page.

Google Shopping API using OAuth 2 method for authentication

I am trying to create a console app that will be executed by a scheduled task to create products for sale on Google Shopping. From what I have read OAuth 2 is the method of Authentication I should be using.
In the Google Developer Console I have created a Project and got back a Project Id. I have enabled the Content API for Shopping, Created a Client Id for native application which gives me the Client Id, Client Secret and Redirect URIS. (not sure what the Redirect URIS are all about?)
In my C# code I have:
string clientId = "27127807975-j71ghj7<=== MY CLIENT ID from console ===>apps.googleusercontent.com"; // Provided in the APIs Console
string clientSecret = "WFM<== My Secret from console ==>osVg"; // Provided in the APIs Console
string scope = "https://accounts.google.com/o/oauth2/auth";
string redirectUri = "urn:ietf:wg:oauth:2.0:oob";
OAuth2Parameters parameters = new OAuth2Parameters()
{
ClientId = clientId,
ClientSecret = clientSecret,
RedirectUri = redirectUri,
Scope = scope
};
string authorizeUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
However the URL returned from this call gives this error when loaded in browser, (I read I need to load this url in a browser to get an Access Code returned):
Error: invalid_client
no application name
Would really like to know what I am doing wrong here or maybe a link to some example code that posts a product to Google Shopping if anyone knows of any.

Transfer ownership of Google Drive documents

We develop application in C# which need to transfer ownership of all Google Drive documents related to the curtain domain to a single certain user without permission of original owner. We are using trial version of Google Apps business account.
In principal, we need to do this: http://screencast.com/t/effVWLxL0Mr4 but in C# code.
Accourding to the documentation, it is implemented in OAuth2 as superadmin functionality. https://support.google.com/a/answer/1247799?hl=en (1).
But document was deprecated and more over we did not find any API call to do that.
Using account of project creator, it is appeared, that he can not access to all files and can not see files is not shared with him.
In Google Admin Console in manage API client access we added access rights to him to access files without permission to files without permission. Link: screencast.com/t/zU9cc6Psyb. We added routes access routes there according to that document link: trovepromo-tf.trove-stg.com/0m1-sds/support.google.com/a/answer/162106?hl=en and tried again.
It did not work out...
Also, We found out that we need to use service account to have access to all data of all users of the domain, therefore we generated API keys for service account link: screencast.com/t/rNKuz6zchwV in the created project and got authenticated in the application using the following code:
var certificate = new X509Certificate2(#"C:\Temp\key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer("Service account email")
{
User= "admin#domain.com",
Scopes = new[] { DriveService.Scope.Drive }
}.FromCertificate(certificate));
but when we try to get list of folders, we get error :"access_denied", Description:"Requested client not authorized.", Uri:""
Please help us to transfer ownership of one user to another by service account!
Update from 13-08-2014:
Dear, It seems I have problem with user impersonalization.
1) When I use api to connect on behalf of user. During the authentication it redirects to browser and ask permisstion. After that all is completely fine, I can manimulate with folders except one one thing: I can not transfer ownership to him
2) When I use service account without impersonalization, authentication looks like the following:
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(ServiceAccountId)
{
Scopes = new[] { DriveService.Scope.Drive,
DriveService.Scope.DriveAppdata,
DriveService.Scope.DriveFile,
DriveService.Scope.DriveScripts,
DirectoryService.Scope.AdminDirectoryUser,
DirectoryService.Scope.AdminDirectoryGroup,
DirectoryService.Scope.AdminDirectoryOrgunit,
DirectoryService.Scope.AdminDirectoryUserReadonly
},
}.FromCertificate(certificate));
Then I can access to all files shared to service account but (again) I can not transfer the rights.
3) Then I try impersonalize Service account by adding sypeadministrator email account to the user User = myaddress#mydomain.com
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(ServiceAccountId)
{
Scopes = new[] { DriveService.Scope.Drive,
DriveService.Scope.DriveAppdata,
DriveService.Scope.DriveFile,
DriveService.Scope.DriveScripts,
DirectoryService.Scope.AdminDirectoryUser,
DirectoryService.Scope.AdminDirectoryGroup,
DirectoryService.Scope.AdminDirectoryOrgunit,
DirectoryService.Scope.AdminDirectoryUserReadonly
},
User = AdminEmail,
}.FromCertificate(certificate));
Then I have Error:"access_denied", Description:"Requested client not authorized.", Uri:""
How can I impersonalize service account correctly?
Updated 13-08-2014
We found out that basic api for authentication is here: https://developers.google.com/accounts/docs/OAuth2ServiceAccount#creatingjwt
Normally, all what I showed before is an .net implementation of the protocol.
How can we please do impersonalization of of user in .net code. We did not find any working .net implementation of it.
I finally found an answer.
I could impersonalize an account by using the following construction:
Thanks to all, who tried to help me!
var initializer = new ServiceAccountCredential.Initializer(ServiceAccountId)
{
Scopes = scope,
User = AdminEmail1
};
var credential = new ServiceAccountCredential(initializer.FromCertificate(certificate));
var driveService = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName
});

Google Drive API invalid_grant after removing access

I have been writing a desktop application that uses the Google Drive API v2. I have the following code:
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync
(
new ClientSecrets { ClientId = ClientID, ClientSecret = ClientSecret },
new[] { DriveService.Scope.Drive }, "user", CancellationToken.None
)
.Result;
this.Service = new DriveService( new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My Test App",
} );
var request = this.Service.Files.List();
request.Q = "title = 'foo' and trashed = false";
var result = request.Execute();
The first time I ran this code it opened a browser and asked me to grant permissions to the App, which I did. Everything worked successfully until I realized I was using the wrong Google account. At that point I logged into the wrong Google account and revoked access to my App. Now, whenever I run the same code it throws an exception:
Error:"invalid_grant", Description:"", Uri:""
When I examine the service and request objects, it looks like the oauth_token isn't getting created any more.
I know what I did to mess things up, but I can't figure out how to correct it so I can use a different Google account for testing. What do I need to do?
The stored credentials are persisted using StorageDataStore. You can either call the DeleteAsync() method or manually find and delete the file.

Categories