I create credentials for google service account from json file as follow:
using var stream = new FileStream(credentialFileName, FileMode.Open, FileAccess.Read);
var credentials = ServiceAccountCredential.FromServiceAccountData(stream);
The service account has Domain-wide Delegation with scopes:
The result is then used to create a DriveService or a SheetsService object.
sheetService = new SheetsService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials
});
driveService = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials
});
I've been succesfully interacting with Google Sheets API. Writing and reading without any issue, it just works fine.
As soon as I try to interact with Google Drive API things don't work because of lack of authentication. This code is an example:
var fileListRequest = DriveService.Files.List();
fileListRequest.Q = $"'{gDriveFolderID}' in parents";
var fileList = await fileListRequest.ExecuteAsync();
I get exception: "The service drive has thrown an exception. HttpStatusCode is Unauthorized. 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"
If instead of authenticating with a service account I authenticate with an ID client OAuth 2.0, which requires me to accept in a browser page, it works. The problem is that this authentication expires.
I Know I could use the refresh token. But it also will expire at some point, and service accounts exist exactly to avoid refreshing authentication when dealing with internal data.
Your code is not complete, you are neither scoping your credentials nor using user impersonation.
var credentials = GoogleCredential.FromFile(credentialFileName)
.CreateScoped(
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets")
// This is the email of the user in the domain where
// the service account has domain wide delegation,
// that you want to manipulate Drive files/Sheets for.
.CreateWithUser("[email protected]");
var sheetService = new SheetsService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials
});
var driveService = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials
});
I'm not certain why it was working for Sheets before though.