google-api-nodejs-client icon indicating copy to clipboard operation
google-api-nodejs-client copied to clipboard

Getting permission denied while getting subscription details from pub/sub events using service account credentials

Open bhavya3024 opened this issue 1 year ago • 3 comments

Hi there, I used google cloud pub/sub api to receive messages using the endpoint url, here I was able to receive events in the backend, but when I tried getting subscription details using the service account credentails, I got permission denied. It worked successfully when tried using OAuth redirecting to the browser, but I need to handle it in the backend to store/modify subscription details in the database, so OAuth2 doesn't seem to be viable option.

I have tried the following code snippet.

require('dotenv').config();
(async () => {
    const subscription = {
        message: {
            data: '<sample-subscription>',
            messageId: '10553462436995277',
            message_id: '10553462436995277',
            publishTime: '2024-02-27T12:30:55.34Z',
            publish_time: '2024-02-27T12:30:55.34Z'
        },
        subscription: '<subscription-id>',
    };

    const decodedData = Buffer.from(subscription.message.data, 'base64').toString('utf-8');
    console.log(decodedData);
    const {
        subscriptionNotification: { purchaseToken, subscriptionId },
        packageName,
    } = JSON.parse(decodedData);

    console.log(JSON.parse(decodedData));

    const { google } = require('googleapis');

    const androidpublisher = google.androidpublisher({
        version: 'v3',
        auth: new google.auth.JWT({
            keyFile: './creds.json', // service account creds, i saw in the google console that it has owner permissions
            scopes: ['https://www.googleapis.com/auth/androidpublisher'],
        }),
    });
    const response = await androidpublisher.purchases.subscriptions.get({
        packageName: packageName,
        subscriptionId: subscriptionId,
        token: purchaseToken,
    });
    console.log(response);
})();

The error I am getting is:

{  
status: 401,
  code: 401,
  errors: [
    {
      message: 'The current user has insufficient permissions to perform the requested operation.',
      domain: 'androidpublisher',
      reason: 'permissionDenied'
    }
  ],
}

these are permissions I saw in the google cloud console. image

Don't know what to do in this case! Thanks in advance! @proppy @dazuma @jskeet @hansoksendahl @andrelaszlo

bhavya3024 avatar Feb 28 '24 13:02 bhavya3024

Hi @bhavya3024! Not sure why I'm tagged in this issue, but I'd never complain about being mentioned in the same sentence as Jon Skeet 😉

I'm not using the nodejs client library, but here are some ideas:

  • Check your quotas
  • Is the scope correct? I would have guessed that you need ["https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/pubsub"]
  • Use Application Default Credentials (ADC) instead. If you do this and deploy to GCP (Cloud Run or Cloud Functions for example) you don't have to mess around with credentials at all, which is nice.

By the way, Owner is generally too broad for service accounts - to consume Pub/Sub messages, the SA needs the Pub/Sub Subscriber (roles/pubsub.subscriber)) role on the subscription at least.

andrelaszlo avatar Mar 05 '24 19:03 andrelaszlo

Hi @andrelaszlo I use AWS Lambda in backend, if I try to use ADC config file and use them inside lambda, will it work ?

bhavya3024 avatar Mar 06 '24 06:03 bhavya3024

Hi @andrelaszlo I use AWS Lambda in backend, if I try to use ADC config file and use them inside lambda, will it work ?

Something like that, yeah. I think you can fetch secrets from AWS Secret Manager and store them in GOOGLE_APPLICATION_CREDENTIALS for example. Use a service account key though.

andrelaszlo avatar Mar 06 '24 10:03 andrelaszlo