Search code examples
.netgoogle-apigoogle-oauthgdatagoogle-api-dotnet-client

GoogleWebAuthorizationBroker does not automatically return new access token from refresh token


I use the GoogleWebAuthorizationBroker class form .Net Client library which stores an access token and a refresh token in the file storage, like this :

            UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
               new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret },
                                 scopes, "XXXXXX", CancellationToken.None
            ,new FileDataStore("XXXXXX")
                                ).Result;

If works, but after one hour, when the acces token is invalid, when launching the AuthorizeAsync again, the access tokens returned in the "credential" object is not renewed, as it should be (I cheked the values in the debug mode and the acces token is still the same, not renewed). Even the browser does not launch to ask user for granting permission (i use it for the Google contacts API).

I use OAuth2 with .Net google client library to authentificate, since is much simplier than then authentification with the gdata library. Nevertheless I use the old gdata lib to update gmail contacts (the new contact API does not allow YET contact data modification).

Is there a problem with mixing those APIs ? Should i autentificate with the gdata library ?

Thanx.


Solution

  • Nope it is arguably the easiest way to authenticate to a gdata api is to use the discovery library for authentication.

    You haven't shown how you are applying the access token to your gdata request but I am going to assume that's working fine.

    The thing is that the discovery library the one containing "GoogleWebAuthorizationBroker" uses FileDatastore to refresh your access token. It does it when it needs it. You aren't making any requests using it so it never bothers to refresh your access token. The easiest way of doing this is to make a dummy request using a discovery api. I normally just use the people api.

    People.get sending a parameter of 'me' just gets some dummy info on the currently authenticated user. If the access token has expired then it will fetch you a new one.

    I am going to dig around in the library a little I am wonder why we don't have a force refresh access token method for times like this.

    Update:

    you will need to add the scope PlusService.Scope.PlusMe or https://www.googleapis.com/auth/plus.login.

    var service = new PlusService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Google Plus Authentication Sample",
                });
    
    // dummy call to api to refresh the auth token if needed.
    var refresh = service.People.Get("me").Execute();
    

    Update2:

    After a bit of digging around in the client library I found that there is a method for forcing an update of the access token

    var m = credential.GetAccessTokenForRequestAsync();
    

    Unfortunately its going to be an hour before I can verify that it works. The background code checks if the current access token has expired or not before trying to refresh it so I need to wait for one to expire.