2

I have an installed c# app with code working that gets the authorization code and exchanges it for an access token. I am storing off the refresh token. I know at some point I need to use it to get a new access token. Let's assume that I am periodically calling the following method to monitor the files that have been shared with my Drive account.

   /// <summary>
   /// Retrieve a list of File resources.
   /// </summary>
   /// <param name="service">Drive API service instance.</param>
   /// <returns>List of File resources.</returns>
   public static List<File> retrieveAllFiles(DriveService service) {
      List<File> result = new List<File>();
      FilesResource.ListRequest request = service.Files.List();
      request.Q = "sharedWithMe and trashed=false";
      do {
         try {
            FileList files = request.Fetch();

            result.AddRange(files.Items);
            request.PageToken = files.NextPageToken;
         } catch (Exception e) {
            Console.WriteLine("An error occurred: " + e.Message);
            request.PageToken = null;
         }
      } while (!String.IsNullOrEmpty(request.PageToken));
      return result;
   }
}

I assume that at some point the call to service.Files.List() is going to fail. How do I know it has failed due to an expired access token and what is the code to use the refresh token? I already have some code (below) that I gleaned from here to use the refresh token. Will this method get called when the access token expires?

    private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
   {
      // If we already have a RefreshToken, use that
      if (!string.IsNullOrEmpty(RefreshToken))
      {
         state.RefreshToken = RefreshToken;
         if (arg.RefreshToken(state)) {
            mTextBox.Text = "RF: " + RefreshToken;
            return state;
         }
      }
      // authCode is a TextBox on the form
      var result = arg.ProcessUserAuthorization(mTextBox.Text, state);
      RefreshToken = state.RefreshToken;
      return result;
   }
Community
  • 1
  • 1
charles young
  • 2,269
  • 2
  • 23
  • 38

4 Answers4

2

An access token will expire after 1 hour - after that time you will begin to receive "401 Invalid Credentials" errors when you make calls against a Google API.

I'm not familiar with the .NET Google API Client library - the Java and Python libraries will automatically make a request for a new access token when this occurs, depending on how you are creating the DriveService object. I would expect the .NET library to have similar semantics.

aeijdenberg
  • 2,427
  • 1
  • 16
  • 13
  • The access token typically expires in 1 hour, but don't hard code this value. Always use the expires_in parameter, and only as a hint. – mariuss Jun 06 '13 at 16:34
  • So when I catch the exception in retrieveAllFiles is where I would put the code to refresh the token? Can you be more explicit? – charles young Jun 06 '13 at 17:22
  • How exactly are you creating the DriveService object? Again, not familiar with .NET Google libraries, but the pattern for the Java / Python libraries is that you: (1) Create a Credentials object (that contains the refresh token), (2) You use the Credentials object to create an authorized HTTP object, that is, an object that makes HTTP requests which takes care of catching 401s and getting new access tokens for you, then (3) Create a service object (like DriveService) and pass that HTTP object to it. The .NET library may be similar - the DriveService object might take care of this for you. – aeijdenberg Jun 06 '13 at 18:20
2

If someone still have Problems with refreshing the AccessToken, maybe this can help you finding a solution:

            Google.GData.Client.RequestSettings settings = new RequestSettings("<AppName>");
            Google.GData.Client.OAuth2Parameters parameters = new OAuth2Parameters()
            {
                ClientId = "<YourClientId>",
                ClientSecret = "<YourClientSecret>",
                AccessToken = "<OldAccessToken>", //really necessary?

                RedirectUri = "urn:ietf:wg:oauth:2.0:oob",
                RefreshToken = "<YourRefreshToken>",
                AccessType = "offline",
                TokenType = "refresh",
                Scope = "https://www.google.com/m8/feeds/" //Change to needed scopes, I used this for ContactAPI
            };
            try
            {
                Google.GData.Client.OAuthUtil.RefreshAccessToken(parameters);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
1

When to use the refresh token:

From what I understand you use the refresh token when you do not wish to authenticate your app each time it boots. This is extremely useful for debugging during application development (as manual authentication can get annoying after a while).

How to use the refresh token:

In the most basic sense:

public static GOAuth2RequestFactory RefreshAuthenticate(){
    OAuth2Parameters parameters = new OAuth2Parameters(){
        RefreshToken = "<YourRefreshToken>",
        AccessToken = "<AnyOfYourPreviousAccessTokens>",
        ClientId = "<YourClientID>",
        ClientSecret = "<YourClientSecret>",
        Scope = "https://spreadsheets.google.com/feeds https://docs.google.com/feeds",
        AccessType = "offline",
        TokenType = "refresh"
    };
    string authUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
    return new GOAuth2RequestFactory(null, "<YourApplicationName>", parameters);
}

You would use this method in other code with a service, perhaps like this

GOAuth2RequestFactory requestFactory = RefreshAuthenticate();
SpreadsheetsService service = new SpreadsheetsService("<YourApplicationName>");
service.RequestFactory = requestFactory;

Hope this helps!

strudelheist
  • 49
  • 1
  • 5
0

Spent the last two days figuring out how to use and renew the access token using the refresh token. My answer is posted in another thread here:

How Google API V 3.0 .Net library and Google OAuth2 Handling refresh token

Community
  • 1
  • 1
Ogglas
  • 62,132
  • 37
  • 328
  • 418