I have tried to follow the documentation here: https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#service-account to be able to connect to the API and create/upload new builds.
This is currently trying to use the: https://googleapis.dev/dotnet/Google.Apis.AndroidPublisher.v3/latest/api/Google.Apis.AndroidPublisher.v3.html
I believe I have followed through creating a Service account correctly as per the documentation however I am happy to accept I don't really understand how it all pieces together yet. I have given Owner access to the main developer account for this account so I am assuming that is full access.
One different between the above linked example and my implementation is that I choose to use the "recommended key format" when creating a key for my Service Account and used JSON, hence my code example below:
private async Task Run(string packageName, string apiKey)
{
ServiceAccountCredential credential;
await using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = ServiceAccountCredential.FromServiceAccountData(stream);
}
// Create the service.
var service = new AndroidPublisherService(new BaseClientService.Initializer
{
ApplicationName = "App Uploader",
HttpClientInitializer = credential,
ApiKey = apiKey,
});
var appEdit = new AppEdit();
// Fails here:
var insertRequest = await service.Edits.Insert(appEdit, packageName).ExecuteAsync();
}
The //Fails here line throws the following exception:
Google.Apis.Requests.RequestError
The caller does not have permission [403]
Errors [
Message[The caller does not have permission] Location[ - ] Reason[forbidden] Domain[global]
]
I can clearly see that I am not specifying a Scope when creating my credential now and when debugging I see that Scopes is empty. Do I need to be setting this somehow and if so am I able to do it using the JSON key format?
The simplest way of doing this is to use GoogleCredential:
var credential = GoogleCredential.FromFile("clients_secrets.json")
.CreateScoped(/* your scopes here */);
I would expect that to be all you need to do. The GoogleCredential will wrap a ServiceAccountCredential, and it should all just work.
That said, when you don't specify scopes I'd expect it to be generating a self-signed JWT and authenticating with that.
@jskeet wow, thank you for the rapid response! Sadly it looks like I may have wasted your time. Sorry I was trying to tick possible issues off the list as to why it may be failing and it is still failing in the exact same way.
I will go back to the drawing board and try to work out this permission model in more depth.
Thanks again
Not a problem at all - it's always good to get some more information. I would suggest trying list or get calls to start with... those are normally easier to get to work, and then you can move on to insert/edit.
I'll close this issue now as I suspect this isn't actually a library auth issue, but please do add another comment with more details if you'd like us to reopen it.
Really sorry I have found the cause of my issue. I was missing this step:
No problem - thanks for letting us know; it's always nice to hear what worked in the end, and I'm glad the problem is solved :)