How to destroy google drive token after task done? - c#

I am able to authenticate and perform actions on google drive using credential I got after authentication but this token is there for long long time. it says expires-in : 3600 so it should expire in 1hour but when I tried it after a month it uses that token and it worked.
My requirement is after authentication and whatever task is being performed get complete, it should again ask for authentication to user if user initiate the program again. so basically I don't want token to be stored in client's system. Expires-in is not working for me as token get refreshed and is not asking again for Authentication.
below is my code which I am using :
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "<myid>.apps.googleusercontent.com",
ClientSecret = "<Mysecret>"
},
new[] { DriveService.Scope.Drive },
"user",
CancellationToken.None).Result;
// Create the service using the client credentials.
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "sampleapp"
});
*****some task performed*********
now after this "some task" I want token to be destroy.
Please help.

From release 1.8.2 (http://google-api-dotnet-client.blogspot.com/2014/05/announcing-release-of-182.html) which was just released earlier today, we support token revocation. It revokes the token and also deletes it form the data store.
All you have to do is the following:
await credential.RevokeTokenAsync(CancellationToken.None);
As simple as that.
UPDATE:
Read more about token revocation in the Google APIs client library for .NET in this blogpost: http://peleyal.blogspot.com/2014/06/182-is-here.html

The reason that you user is not getting asked again is because you are passing a refresh token, you just didn't know it.
Normal when I do this I use the following code:
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "<myid>.apps.googleusercontent.com",
ClientSecret = "<Mysecret>"
},
new[] { DriveService.Scope.Drive },
"user",
CancellationToken.None,
FileDataStore("Drive.Auth.Store")).Result;
What happens then is a file with my refresh token is stored in the user %AppData% directory with the name Drive.auth.store.
{
"access_token":"ya29.IgA23NyW3rF0xxoAAACFPgYzOm9Bm1Vixr-ti9crN5LvEr0W_gjtUQWOCy9QHw",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"1/OGUwUcl92Abo-7LAsuC0tsp_FWxhOW_freUyKncNalI",
"Issued":"2014-05-26T20:34:07.447+02:00"
}
Now your code is slightly diffrent you arent sending FileDataStore("Drive.Auth.Store"). I hadn't tried not sending it before so I had to test this. It appears that by default GoogleWebAuthorizationBroker.AuthorizeAsync stores the refresh token for you just like it would if you used FileDataStore. The name appears to be a default Tasks.Auth.Store.
So what is happening is that every time your user runs your application the Client lib is auto loading that file for you.
How to fix it:
The ugly way would be to randomly change "User" (timestamp or something), if that is different then it will automatically prompt for authentication again. You will need to check the file in %appdata% i have no idea if its going to create a new one every time they run your application or if its just going to over wright the old one. Its probably not a good idea to keep creating crap files on the users PC.
The nice way. Create your own implementation of Idatastore that just doesn't save it. You can find a very basic example of that Google Oauth C# at the bottom called stored refresh token Just don't store it anyplace.

Related

C# set access_type = offline for AuthorizeAsync?

I am attempting to change our old rest calls for the .net client libs and I have two-ish questions/issues which are related...
The sample app on this page
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth
uses AuthorizeAsync to get the user to approve the authorization, then you save the credentials somewhere....
At a later point - you want to do some offline stuff, for that., it has the following
UserCredential and AuthorizationCodeFlow take care of automatically
"refreshing" the token, which simply means getting a new access token.
This is done using a long-lived refresh token, which you receive along
with the access token if you use the access_type=offline parameter
during the authorization code flow.
I've marked the two statement in bold that are in question.
How do you set this parameter using the c# client lib? AuthorizeAsync does not take in a accessType flag.
Do you even need to set this (AccessType)? I noticed that after approving the oauth screen - I received both the accessToken and the RefreshToken
Once you have the refresh token - and you need to build the credentials from the saved accesstoken and refreshtoken - do you need manually refresh the access token? or will AuthorizationCodeFlow really take care of this and do I need to remember the refreshed accessToken?
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { BooksService.Scope.Books },
"user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary"));
}
The first thing that you should look at above is "user" this is where you denote different users. FileDataStore stores the credentials by default in %appData% folder on your machine each user will have their own credentials file. I have a full write up on filedatastore.
You don't need to worry about setting it to offline access or requesting a new access token when yours expires the client library will handle all of that for you.

How to configure a Website that auth's for YouTube credentials to be used by console application?

Ultimately, I am trying to upload a YouTube video on behalf of a user who has authorized my site / application to do so.
I have a website where a user authorizes the website to use the user's YouTube credentials. The website then properly stores the credentials after the user has authorized (YouTube Data API v3). The problem is, these credentials are desired to be used by a server process, which for all purposes would be considered a console application.
When adding credentials to my project on the Google API Manager, however, I can either do a Web Browser, Web Server, (and others) OR "other UI (Windows)". But I cannot do BOTH. I believe I need both because the user authorizes through the website, but the console process uses the credentials.
But even if I have an answer for that above, how do I pass the USER'S credentials to the console app using the sample code that they show in the samples?
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
);
}
It seems like this code is used more for storing the credentials somewhere on the Windows file system to be retrieved later, like a cache. But I'm storing these "authorized" values in a database already, and would like to retrieve them and act on the behalf of that user.
I hope this makes sense, and I apologize if it rambled.
Background:
The Google .NET client library by default stores the credentials for the users in %AppData% the field where you have "user" is how its is storing it.
Example:
UserCredential credential;
using (var stream = new FileStream(clientSecretsJsonFilePath
,FileMode.Open
,FileAccess.Read))
{
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { DriveService.Scope.Drive, DriveService.Scope.DriveFile },
"LookIAmAUniqueUser",
CancellationToken.None,
new FileDataStore("Drive.Auth.Store")
).Result;
}
Assuming the user clicks accept on the authentication request screen, a new file will be created in that directory with the following structure:
Google.Apis.Auth.OAuth2.Responses.TokenResponse-LookIAmAUniqueUser.TokenResponse-LookIAmAUniqueUser
Each user will have their own file you change a user by changing the "LookIAmAUniqueUser" value.
Solution one:
Identify your users differently so that you know you are loading me vs you. Just by changing the "user" parameter, it will load the one needed or ask the user for authentication if it can't find it.
Solution two:
By default the library uses FileDataStore that's why I have it in mine and you don't have it in yours. If you are storing the credentials someplace else say the refresh token in the database along with your user information. You can create your own implementation of IDataStore which will load the credentials from there.
My article on FileDataStore might help you understand what its doing. Google .NET – FileDataStore demystified sorry I haven't had time to create a article on creating an implementation of IDataStore, however I might have an example or two laying around depends really on where you are storing those credentials

Authenticate Youtube API on a Worker process C#

I'm running a process without UI that retrieves uploaded videos from youtube. On a develpement machine it authenticates on user behalf and it works.
The problem is when process is running on a server: browser window doesn't fire for user to let use his account (it should only require to do it once).
Event viewer shows no errors whatsoever. Service accounts doesn't seem to work with youtube, with API key is too less permissions and
oath is the only way to authenticate and get broadcasted videos. Or am I wrong?
So the question is: How to run a service as a single user and retrieve his videos without UI?
private async Task Run()
{
try
{
UserCredential credential;
using (var stream = new FileStream(StartPath + "\\client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeReadonly, YouTubeService.Scope.Youtube },
"user",
CancellationToken.None,
new FileDataStore("Store")
);
}
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = this.GetType().ToString()
});
....
}
I have also tried:
String serviceAccountEmail = "e-mail";
var certificate = new X509Certificate2(HostingEnvironment.MapPath("~/Content/key.p12"), "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { YouTubeService.Scope.Youtube, YouTubeService.Scope.YoutubepartnerChannelAudit, YouTubeService.Scope.YoutubeUpload }
}.FromCertificate(certificate));
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "api",
});
The YouTube Data API lets you incorporate functions normally executed on the YouTube website into your own website or application. The lists below identify the different types of resources that you can retrieve using the API. The API also supports methods to insert, update, or delete many of these resources.
This reference guide explains how to use the API to perform all of these operations. The guide is organized by resource type. A resource represents a type of item that comprises part of the YouTube experience, such as a video, a playlist, or a subscription. For each resource type, the guide lists one or more data representations, and resources are represented as JSON objects. The guide also lists one or more supported methods (LIST, POST, DELETE, etc.) for each resource type and explains how to use those methods in your application.
The following requirements apply to YouTube Data API requests:
Every request must either specify an API key (with the key parameter) or provide an OAuth 2.0 token.
Your API key is available in the Developer Console's API Access pane for your project.
You must send an authorization token for every insert, update, and delete request. You must also send an authorization token for any request that retrieves the authenticated user's private data.
In addition, some API methods for retrieving resources may support parameters that require authorization or may contain additional metadata when requests are authorized. For example, a request to retrieve a user's uploaded videos may also contain private videos if the request is authorized by that specific user.
The API supports the OAuth 2.0 authentication protocol. You can provide an OAuth 2.0 token in either of the following ways:
Use the access_token query parameter like this: ?access_token=oauth2-token
Use the HTTP Authorization header like this: Authorization: Bearer oauth2-token
Complete instructions for implementing OAuth 2.0 authentication in your application can be found in the authentication guide.
So I've managed to make a work around that situation by creating console application program that does the thing.
Authentication mechanism moved into console application and passed the results to the service. In a service made a call into that application every n seconds. This solution worked like a charm. Ugly one, but it worked. Now i can give application access to profile data and use it where I want to.
If anyone will have a better solution I would be glad to read it.

.NET gmail API Authentication (without user interaction)

I am trying to authneticate gmail api using c# console application.
I am using.net sdk of Google api and the code i am using to authorize the api is as follows :
UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "clientId",
ClientSecret = "clientsecret"
},
new[] { GmailService.Scope.GmailModify },
"user",
CancellationToken.None, null);
But the above code open a browser window to ask for permission to access the service, I need to avoid this authentication activity as I need to schedule ".exe" file of the project on Azure
You're confusing between authorization and authentication.
Authorization is a one time process and you cannot authorize without user authorizing your app to do whatever you're meaning to do. It is a one time process.
What you're doing in the code is authorization. It will definitely open a browser for the user to authorize your app. Once you authorize your app, then for next time, all you need to do is authenticate. Authentication doesn't require this manual user process.
All you have to do is to use the UserCredential you receive from the Google from the next time you need it.
Store the credential you receive from the service somewhere and use it next time to initialize the Service
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential, //your stored credential
ApplicationName = "App",
});
However you may need to refresh the Credential token (which expires every 60 minutes). It should automatically refresh, but you can refresh it manually everytime you need it by making a check.
if (credential.Token.IsExpired)
var returnBool = await credential.RefreshTokenAsync(cancellationToken);

Get UserCredential of Google Drive API using Refresh token, ClientId and ClientSecret in ASP.net/C#

I was able to get a RefreshToken by following the instruction given in this link : How do I authorise a background web app without user intervention? (canonical ?).
Now I need user credential for getting driveservice object. I have searched a lot but cant find a exact solution.
I can get access token using refresh token, ClientId and ClientSecret following this link :Using OAuth 2.0 for Web Server Applications - offline.
But after that how can I get user credential using that AccessToken? Or any direct way for getting credential using refresh token. Any example or suggestion.
Thanks!
You might want to try using the Client Lib for this instead of that. All you need to do is run the following code once. The refresh token will be created by FileDataStore and stored in your %appData% directory. The next time it runs it wont prompt you for authentication because it will have it already. You could also create your own implementation of iDataStore to store the refresh token where ever you like. I like current directory LocalFileDatastore.cs.
//Scopes for use with the Google Drive API
string[] scopes = new string[] { DriveService.Scope.Drive,
DriveService.Scope.DriveFile};
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential =
GoogleWebAuthorizationBroker
.AuthorizeAsync(new ClientSecrets { ClientId = CLIENT_ID
, ClientSecret = CLIENT_SECRET }
,scopes
,"SingleUser"
,CancellationToken.None
,new FileDataStore("Daimto.GoogleDrive.Auth.Store")
).Result;
Code ripped from Google Drive API C# tutorial.

Categories

Resources