Search code examples
c#oauth-2.0google-oauth

How do I use a refresh token to get a new access token for Google SpreadsheetsService


I'm trying to build an application which reads and writes to a private Google Spreadsheet. For this I need to use Google OAuth2.0 .

My problem is that I lose access after 1 hour. I assume this means that the refresh token is not being used correctly. Here is my code for handling authentication:

public static SpreadsheetsService AuthenticateOauth(string clientId, string clientSecret, string userName)
    {

        string[] scopes = new string[] { DriveService.Scope.Drive,  // view and manage your files and documents
                                         DriveService.Scope.DriveAppdata,  
                                         DriveService.Scope.DriveAppsReadonly,   
                                         DriveService.Scope.DriveFile,   
                                         DriveService.Scope.DriveMetadataReadonly,   
                                         DriveService.Scope.DriveReadonly,   
                                         "https://spreadsheets.google.com/feeds",
                                         "https://docs.google.com/feeds"

        };  


        try
        {
            // 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 = clientId, ClientSecret = clientSecret }
                                                                                         , scopes
                                                                                         , userName
                                                                                         , CancellationToken.None
                                                                                         , new FileDataStore("MY.APP.Auth.Store")).Result;

            SpreadsheetsService service = new SpreadsheetsService(My App");
            var requestFactory = new GDataRequestFactory("My App");

            requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
            service.RequestFactory = requestFactory;

            return service;
        }
        catch (Exception ex)
        {


            Console.WriteLine(DateTime.Now.ToString("HH:mm") + ": An authentication error occurred: " + ex.InnerException);
            return null;

        }

    }

How do I go about making the refresh token being used correctly?


Solution

  • You are using the current Google .NET client library to authenticate. When you create a service, it normally will automatically refresh your access token when needed. However, you are sending an access token to an old Gdata library, which doesn't automatically refresh it.

    If you create a drive service and run a dummy request against it once an hour it will refresh your access token for you when needed.

    var service = new DriveService(new BaseClientService.Initializer() {HttpClientInitializer = credential,
                                                                                ApplicationName = "Drive API Sample",});
    
    // Dummy request example:
    FilesResource.ListRequest list = service.Files.List();
    list.MaxResults = 1;
    list.Q = "title=dummysearch";
    FileList dummyFeed = list.Execute();
    // End of Dummy request