8

I have a .NET application that is using Google Drive to access the user's file. I am able to get the authorization code, and I have been able to exchange the authorization code by the AccessToken and the RefreshToken. The issue is that I cannot refresh the access token, and it expires after an hour.

Similar to this question: How to generate access token using refresh token through google drive API? except that I am working in .NET (using the Google.APIs... DLLs).

I am aware of this: https://developers.google.com/accounts/docs/OAuth2InstalledApp#refresh however, I am expecting some sort of method available in the IAuthorizationState or OAuth2Authenticator object to allow me refresh the access token.

Please advise. Thanks.

Please note that using this code I am able to get the Access Token. It is just that I am expecting this code to be inside the Google API.

    public class OAuth2AccessTokenReponse
    {
        public string access_token;
        public int expires_in;
        public string token_type; 
    }
    public static string refreshAccessToken()
    {
        using (System.Net.WebClient client = new System.Net.WebClient())
        {
            byte[] response = client.UploadValues("https://accounts.google.com/o/oauth2/token", new System.Collections.Specialized.NameValueCollection(){
                {"client_id", ClientID},
                {"client_secret", ClientSecret},
                {"refresh_token", "XXXXX"},
                {"grant_type", "refresh_token"}
            });
            string sresponse = System.Text.Encoding.Default.GetString(response);
            OAuth2AccessTokenReponse o = (OAuth2AccessTokenReponse) Newtonsoft.Json.JsonConvert.DeserializeObject(sresponse, typeof(OAuth2AccessTokenReponse));
            return o.access_token;        
        }
    }
Community
  • 1
  • 1
rufo
  • 5,158
  • 2
  • 36
  • 47

2 Answers2

8

I studied a more suitable sample: the Tasks.WinForms.NoteMgr of the GoogleApisSample... and with it I found the solution.

The solution is in the code below. The key part of it is calling arg.RefreshToken(state);

Thanks.

    public static Authentication.IAuthenticator UseSavedAuthorization()
    {          

        var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
        provider.ClientIdentifier = ClientID;
        provider.ClientSecret = ClientSecret;

        OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(provider, getState);

        auth.LoadAccessToken();

        return auth;             
    }


public static IAuthorizationState getState(NativeApplicationClient arg)
    {
        IAuthorizationState state = new AuthorizationState(new[] { TasksService.Scopes.Tasks.GetStringValue(), 
                DriveService.Scopes.DriveFile.GetStringValue() , DriveService.Scopes.Drive.GetStringValue()
        });
        state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);

        state.RefreshToken = "<refresh token previously saved>";        
        arg.RefreshToken(state); 

        return state; 
    }`
rufo
  • 5,158
  • 2
  • 36
  • 47
0

If you are using the .NET client library (http://code.google.com/p/google-api-dotnet-client/), you don't have to take care of that. The library will automatically request a new access token for you when needed using the refresh token you retrieved the first time.

Claudio Cherubino
  • 14,896
  • 1
  • 35
  • 42
  • I am using the library. My project is an "installed application". In my testing it didn't work. I was able to access the application the first out (opening/closing my app worked during that time). After the hour the application was denied access because of this issue. Do you have a working sample doing this? I am using the Task.SimpleOAuth2 sample (expanding it of course). – rufo Jul 12 '12 at 19:33
  • You only get a refresh token the first time the user grants access to your app so you have to store it for future use. I guess the second time you tried the app, you only retrieved an access token (and had no stored refresh token) so there was no way to request a new access token after its expiration. Google Drive has a complete sample, but it is not an installed app: https://developers.google.com/drive/examples/dotnet – Claudio Cherubino Jul 12 '12 at 19:48
  • Claudio, yes - I got the refresh token the first time and saved it. Next time I tried to use it (by setting the state.RefreshToken = {my refresh token}, and using the authorization.LoadAccessToken(). That didn't work. Note: I also looked at the DrEdit.Net sample and it seems to me that they are doing what I am doing. Please note that my workaround code from above works (so I do have the correct refreshtoken). Thanks for your help. – rufo Jul 12 '12 at 20:22
  • BTW: I can live with this. It is just that it would be more convenient to automatically refresh as you say it should. And also, it makes me afraid if I am doing something fundamentally wrong. In my opinion the Google samples are good, but they have too many dependencies (like they have internal classes to save the ClientID and ClientSecret, etc). I simplified the Task.SimpleOAuth2 to remove additional dependencies as much as possible (ie: to keep the "core" that does the authentication). Everything is working, except this detail. – rufo Jul 12 '12 at 20:29
  • Claudio, I found the solution - see my answer. Thanks for your help. – rufo Jul 12 '12 at 20:59