Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential

Viewed 6611

I have a console app written with C# on the top of .NET Core 2.2 framework.

I am trying to use my app to connect Google My Business API to create posts.

But every time I try to call the REST API I get the following error

Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.

The code worked previously, but for some odd reason, it stopped!

Hereis an example where I get authentication token and then call the API to get a list of Google accounts.

var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
{
    ClientId = "Client ID",
    ClientSecret = "Client Secret",
}, new[] { "https://www.googleapis.com/auth/plus.business.manage" }, "google username", CancellationToken.None);

using (var client = new HttpClient())
{   
    //client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", credential.Token.AccessToken);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var c = await client.GetAsync("https://mybusiness.googleapis.com/v4/accounts");
    var accountContentss = await c.Content.ReadAsStringAsync();
    c.EnsureSuccessStatusCode();
    var accountContent = await c.Content.ReadAsStringAsync();
}

I am able to authenticate and get the access token with no issue. However, the second call to the API fails for some reason.

How can I correctly call Google API? Beside the AccesToken, is there something else that should get passed in the header?

1 Answers

It turned out to be that GoogleWebAuthorizationBroker.AuthorizeAsync() was returning an expired token! It would have been very helpful if the API returned a message stating that the token is expired instead!

To fix the issue, instead of accessing the AccessToken manually (i.e, credential.Token.AccessToken), I used await Credential.GetAccessTokenForRequestAsync() method to get an access token.

The Credential.GetAccessTokenForRequestAsync() method returns an valid token any time it is called. In other words, if the token is expired, it uses the refresh-token to generate a new one. Otherwise, it return the existing non-expired token.

I change my Authorization header to this

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await Credential.GetAccessTokenForRequestAsync());
Related