Trying to authenticate the Google coordinate api. Tried the Service acount authentication usisng service account and posted stack flow with this question. Found this anwer and quite describes my question.
What the problem now is the library used is deprecated. Not able to execute the solution said.
var auth = new OAuth2Authenticator<WebServerClient> (provider, GetAuthorization);
// Create the service.
var service = new CoordinateService(new BaseClientService.Initializer()
{
Authenticator = auth
});
can anybody suggest a way to achieve the above code. I have installed the new version for Google APIs OAuth2 Client Library. But didn't found any similar code.
I am able to do the read the api using the below code snippet
using Google.Apis.Auth.OAuth2;
using Google.Apis.Coordinate.v1;
using Google.Apis.Coordinate.v1.Data;
using Google.Apis.Services;
using (var stream = new FileStream(System.Web.HttpContext.Current.Server.MapPath(#"../client_secret.json"), FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
new[] { CoordinateService.Scope.Coordinate },
"user", CancellationToken.None);
}
// Create the service.
var service = new CoordinateService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "test",
});
//builds with time last day 12 am
var locationReq = service.Location.List(teamId, workerMail, (ulong)DateTime.Today.AddDays(-1).ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
var locationResult = locationReq.Execute();
but this method reuires a redirection for the first time. I can't do that in my scenario. so need an offline solution.
Need to authenticate using a browser instance first and can reuse same "refresh token" for all other requests. We can provide a custom folder location to store the "auth token" and the library will use stored token from that folder. Modified source code pasted below:
using (var stream = new FileStream(#"client_secret.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
new[] { CoordinateService.Scope.Coordinate },
"user", CancellationToken.None,new FileDataStore(folder));
}
MG
It looks like you are using a very old version of the library (pre GA).
I recommend you to download the latest Coordinate API, which is available in NuGet - https://www.nuget.org/packages/Google.Apis.Coordinate.v1/.
Then, follow the get started and the OAuth 2.0 pages. You should find all the right documentation there, if something is missing - let us know. Open an issue in our issue tracker.
Related
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.
I'm curious how authentication on a Linux headless server works without an internet browser in C# for their Sheetsv4 API. All the code snippets they have on their getting started page have reference to GoogleWebAuthorizationBroker, which doesn't work without a web-browser. I've seen references to GoogleAuthorizationCodeFlow, but I'm not sure if this is what I'm looking for - nor how you would be intended to use it. My current code is bellow-
UserCredential Credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(Stream).Secrets,
new string[1] { SheetsService.Scope.SpreadsheetsReadonly },
"user",
CancellationToken.None,
new FileDataStore(GreetFurConfiguration.TokenFile, true)
).Result;
What I would want is for a link to be generated and, from there, to be able to paste the token into the console, as this is how other Google APIs handle this authentication (Go, NodeJS) which I have used before and seem to work well.
If there is any better way to handle this authentication though that is more suitable for a .NET workflow, that would be suitable as well. I can't manage to find any examples of how you'd get a OAuth2 token for the life of me though without having access to a web browser on the host machine.
EDIT: I'd be looking for https://github.com/googleapis/google-api-dotnet-client/blob/master/Src/Support/Google.Apis.Auth/OAuth2/PromptCodeReceiver.cs
However, I can't find any documentation on how to use this class.
The GoogleWebAuthorizationBroker.AuthorizeAsync allows you to send which code receiver you want The one you are looking for is PromptCodeReceiver.
private const string PathToCredentialFile = "/home/linda/development/creds/client.json";
static async Task Main(string[] args)
{
var scope = new[] {AnalyticsReportingService.Scope.AnalyticsReadonly};
var credPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
await using (var stream = new FileStream(PathToCredentialFile, FileMode.Open, FileAccess.Read))
{
// Requesting Authentication or loading previously stored authentication for userName
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scope,
"userName",
CancellationToken.None,
new FileDataStore(credPath, true),
new PromptCodeReceiver()).Result;
Console.WriteLine($"AccessToken: {credential.Token.AccessToken}");
}
Output:
Please visit the following URL in a web browser, then enter the code shown after authorization:
https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=1XXXXX.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics.readonly
Please enter code:
4/1AY0e-g6L3ASB0lEhWNkh4lDc4nl5k0xV177o38taWFzEzKBv3H24ZC4zQAM
Access toekn: ya29.a0AfH6SMB8ZhpZJgKkpMfbiflxeOF_o6Gzs6fxIuPI25Vewbp7NgVAfJp8EX6K5zgielRrYaSFjqwKIY8MoCuCDbPeF5-2w6_WRnauWqtpleqk2zjqmkHgpfNwbpO8n7VmHVSF9Mgn3YOZRl
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.
I am retriving a token through an website, then I save the token, and refresh token in a database. Then I am writing .net program that uploads video's located on our server to youtube. My problem is to get the program I am making, use the stored token. I am using one of google's examples to upload the video. But the program should use the already saved token, instead os asking for new credentials.
The current code is this.
UserCredential credential;
//credential.UserCredential(,"",)
using (var stream = new FileStream("client_secrets.json", 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
);
}
Console.WriteLine("HER");
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
});
So instead I would like to use an already saved token.
Any help, or a pointer in the right direction would be great. Thanks.
You would use GoogleAuthorizationCodeFlow instead of GoogleWebAuthorizationBroker in order to use the refresh token. See the answer here.
I would like to use the YouTube API to upload videos to a corporate account in a non-interactive program. I was trying to achieve upload without prompting for authentication and authorization (since there is no interactive user). I would appreciate if someone could validate the following assertions:
It is not possible to use Simple API Access to upload videos.
For OAuth, it is not possible to use "Use service accounts to call Google APIs on behalf of your application instead of an end-user." As described in Justin Smith's Blog post. This would have been my desired solution. Here is the code I tried to do this with. It executes, but always returns as "unauthorized" (401):
public async Task AnnounceAsync(Recording recording)
{
const string emailAddress =
"xxxxxxx.gserviceaccount.com";
const string keyFile = #"C:\Temp\xxxxxxx-privatekey.p12";
var key = new X509Certificate2(keyFile, "notasecret", X509KeyStorageFlags.Exportable);
var client = new AssertionFlowClient(GoogleAuthenticationServer.Description, key)
{
ServiceAccountId = emailAddress,
Scope = YoutubeService.Scopes.Youtube.GetStringValue()
};
var auth = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
var youtube = new YoutubeService(new BaseClientService.Initializer {Authenticator = auth});
var video = new Video
{
Snippet = new VideoSnippet
{
Title = recording.Title,
Description = recording.Description,
CategoryId = "22"
},
Status = new VideoStatus
{
PrivacyStatus = "public",
}
};
using (var fileStream = new FileStream(recording.Path, FileMode.Open))
{
var videosInsertRequest = youtube.Videos.Insert(video, "snippet,status", fileStream, "video/*");
videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;
await Task.Run(() => videosInsertRequest.Upload());
}
}
So, I have concluded that I need to use the "Installed Application" API access methodology to move through the OAuth login process interactively at least once myself, save the refresh token and then use that refresh token in the future to get new access tokens? I know I can make this work, but it seems awkward. Is there any gotchas to be aware of if I go down this road?
Further questions:
Any future support planned to allow Service Account OAuth use with the YouTube API?
Could my program use the "mobile upload" feature to email videos to its YouTube account?
Thanks in advance for your input.
At the moment you can't use service accounts. From the doc:
https://developers.google.com/youtube/v3/docs/errors
error/unauthorized/youtubeSignupRequired
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.
The YouTube API blog post:
http://apiblog.youtube.com/2011/10/introducing-google-account-support-and.html
introducing Google Account support also discusses the youtubeSignupRequired error in more detail. Although the blog post explains the error for API version 2.1, the meaning of the error is still applicable.
the "mobile upload" feature to email videos seems to work
Service accounts are a moving target. But you are correct, if you can get a refresh token, then you should be good to go.