Basically my question is this: how do i verify a token from an in app subscription purchase from my app user? I know there are a lot of things to consider, and I tried all of them as far as I am aware, but I still get greeted with the following pesky error in my server-side code.
File "/usr/local/lib/python3.10/site-packages/googleapiclient/http.py", line 938, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 401 when requesting .mycompany.myapp/purchases/subscriptionsv2/tokens/TOKEN_PASSED_IN_FROM_MY_APP?alt=json returned "The current user has insufficient permissions to perform the requested operation.". Details: "[{'message': 'The current user has insufficient permissions to perform the requested operation.', 'domain': 'androidpublisher', 'reason': 'permissionDenied'}]">
I tried everything stated in here as well. ([1.][1])
How can I debug this any further? Does anybody have an idea? If I try the same token the same URL with the google API explorer (right side of this : Method: purchases.subscriptionsv2.get | Google Play Developer API | Google for Developers) it does accept it after I signed in with my developer account (obviously cannot try to sign in with the service account there)
This is very annoying! And I would not know where to look for more help either.. Edit: For example, start by debugging which user is used, and wherein the chain it does not have the correct rights. Maybe I could start by finding out where the credentials are coming from in the below API call, to see which ones are actually used. Anyone know how to obtain that information? Or I could be adding explicit credentials to the api call, using a json key from the service account? All of this is supposed to be automatic, but I must start looking somewhere... Any debug help is appreciated.
service = googleapiclient.discovery.build("androidpublisher", "v3")
# Use the token your API got from the app to verify the purchaseresult = service.purchases().subscriptionsv2().get(packageName=PACKAGENAME, token=token).execute()
Google Play Developer API - "The current user has insufficient permissions to perform the requested operation." - Stack Overflow
Adding some more debug info here:
>> gcloud projects get-iam-policy myproject --flatten='bindings[].members' --format='table(bindings.role)' --filter='bindings.members:MY_SERVICE_ACCOUNT' ;
ROLE
roles/financialservices.admin
And this as well: For debugging the user, I tried to output some more details in my server code:
logger.debug(f"VERGOOGLE: service.http = {service._http.credentials._service_account_email}")
This gives the following output.
VERGOOGLE: service.http = default"
But i would not know if this is correct. I would assume it showing the actual email address of my service account, but this default string might as well be the key to trigger this lookup in GCP.
Making request: GET /computeMetadata/v1/instance/service-accounts/default/?recursive=true
Making request: GET /computeMetadata/v1/instance/service-accounts/[email protected]/token?scopes=https%3A%2F%2Fwww.googleapis%2Fauth%2Fandroidpublisher
Refreshing credentials due to a 401 response. Attempt 1/2.
So do I need to see my service account email passing by here in this GET request? How can I make sure the "default" also has my custom service account email in it?
Basically my question is this: how do i verify a token from an in app subscription purchase from my app user? I know there are a lot of things to consider, and I tried all of them as far as I am aware, but I still get greeted with the following pesky error in my server-side code.
File "/usr/local/lib/python3.10/site-packages/googleapiclient/http.py", line 938, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 401 when requesting https://androidpublisher.googleapis.com/androidpublisher/v3/applications/com.mycompany.myapp/purchases/subscriptionsv2/tokens/TOKEN_PASSED_IN_FROM_MY_APP?alt=json returned "The current user has insufficient permissions to perform the requested operation.". Details: "[{'message': 'The current user has insufficient permissions to perform the requested operation.', 'domain': 'androidpublisher', 'reason': 'permissionDenied'}]">
I tried everything stated in here as well. ([1.][1])
How can I debug this any further? Does anybody have an idea? If I try the same token the same URL with the google API explorer (right side of this : Method: purchases.subscriptionsv2.get | Google Play Developer API | Google for Developers) it does accept it after I signed in with my developer account (obviously cannot try to sign in with the service account there)
This is very annoying! And I would not know where to look for more help either.. Edit: For example, start by debugging which user is used, and wherein the chain it does not have the correct rights. Maybe I could start by finding out where the credentials are coming from in the below API call, to see which ones are actually used. Anyone know how to obtain that information? Or I could be adding explicit credentials to the api call, using a json key from the service account? All of this is supposed to be automatic, but I must start looking somewhere... Any debug help is appreciated.
service = googleapiclient.discovery.build("androidpublisher", "v3")
# Use the token your API got from the app to verify the purchaseresult = service.purchases().subscriptionsv2().get(packageName=PACKAGENAME, token=token).execute()
Google Play Developer API - "The current user has insufficient permissions to perform the requested operation." - Stack Overflow
Adding some more debug info here:
>> gcloud projects get-iam-policy myproject --flatten='bindings[].members' --format='table(bindings.role)' --filter='bindings.members:MY_SERVICE_ACCOUNT' ;
ROLE
roles/financialservices.admin
And this as well: For debugging the user, I tried to output some more details in my server code:
logger.debug(f"VERGOOGLE: service.http = {service._http.credentials._service_account_email}")
This gives the following output.
VERGOOGLE: service.http = default"
But i would not know if this is correct. I would assume it showing the actual email address of my service account, but this default string might as well be the key to trigger this lookup in GCP.
Making request: GET http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/?recursive=true
Making request: GET http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/[email protected]/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fandroidpublisher
Refreshing credentials due to a 401 response. Attempt 1/2.
So do I need to see my service account email passing by here in this GET request? How can I make sure the "default" also has my custom service account email in it?
For those reading this and wondering how to solve this, I did it like this. Of course there are multiple solutions to the same issue.
I added --service-account="myOwnServiceAccount@gcp..." to the yaml file that creates the Cloud Run container. This indeed seems to change the "default" service account into the one I specified, and then I could set the needed roles to this myOwnServiceAccount to make sure it works as expected.