I am working on google Play Billing Library in my android project but still getting Permission denied Error I contacted to google play team they said there is no issue in api access , may be the error is coming from GCP .. so i have added many other permission to check either api is working or not but still getting permission deny.. Kotlin Android Code
FirebaseFunctionsException.Code.PERMISSION_DENIED
this are the permission of Gcp
and this operation is triggering permission error TypeScript Code
static fromServiceAccount(playApiServiceAccount: any, firebaseApp: app.App): PlayBilling {
// Initialize Google Play Developer API client
const jwtClient = new google.auth.JWT(
playApiServiceAccount.client_email, //service account email
null,
playApiServiceAccount.private_key, //service account private key
['https://www.googleapis.com/auth/androidpublisher'], // Auth scope for Play Developer API
null
);
const playDeveloperApiClient = google.androidpublisher({
version: 'v3',
auth: jwtClient
});
return this.fromApiClient(playDeveloperApiClient, firebaseApp);
}
Related
Overview
I am getting an error insufficient permission scopes when running customers.create GCP Channel API, but I can't tell what extra permissions/scopes I need to grant my service account.
I have a node.js provisioning some GCP Resources, where one of the main goals is to automatically create a new Billing Subaccount in GCP.
The latest documenation for this suggests creating a customer, them creating entitlements from there. (A customer is passed into the "create entitlements" method).
Expected Results
Execution of the create customer method should have a successful out of a customer object.
Actual Results
When I implement the create customer I get an error:
UnhandledPromiseRejectionWarning: Error: 7 PERMISSION_DENIED: Request had insufficient authentication scopes.
at Object.callErrorFromStatus ...
My implementation
Authentication : service account credential file
I have a service account with an exported key/credential file I use to successfully authenticate other GCP API calls in my application such as projects.create() and projects.serviceAccounts.create() - so I am confident that my service account authentication is set up correctly as far as the node application goes.
Service account authentication in code:
const auth = new google.auth.GoogleAuth({
keyFile: 'MyServiceAccountKey.json',
scopes: [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/apps.order',
'https://www.googleapis.com/auth/cloud-billing'
],
});
Service Account Permissions (Granted at folder level)
Permissions contained within the "Customer Billing Admin" Role:
Channel API Method Execution :
const {CloudChannelServiceClient} = require('#google-cloud/channel').v1;
async function CreateCustomer(options){
const channelClient = new CloudChannelServiceClient();
const authClient = await auth.getClient();
const request = {
parent : "accounts/XXXXX-XXXXX-MYACCOUNT",
customer : {
"name": "Customer Test 1",
},
}
const response = await channelClient.createCustomer(request);
console.log(response);
}
Resolution thoughts
Using the GCP APIs I've found that sometimes I just need to add additional permissions to my service account in the IAM page on the GPC console, and other time I needed to include more scopes in the authentication object in my code. This refercence for the accounts.customers.create says the required scope for this api is https://www.googleapis.com/auth/apps.order, which I have included in my code - so I am at a loss as to what permissions/scopes I am missing. From what I can tell, service account authorization should work with this API.
I have added google cloud service account in a project and its working. But the problem is that after an hour(i think), I get this error:
The API returned an error: TypeError: source.hasOwnProperty is not a function
Internal Server Error
and I need to restart the application to make it work.
Here in this StackOverflow post, I found this:
Once you get an access token it is treated in the same way - and is
expected to expire after 1 hour, at which time a new access token will
need to be requested, which for a service account means creating and
signing a new assertion.
but didn't help.
I'm using Node js and amazon secret service:
the code I have used to authorize:
const jwtClient = new google.auth.JWT(
client_email,
null,
private_key,
scopes
);
jwtClient.authorize((authErr) =>{
if(authErr){
const deferred = q.defer();
deferred.reject(new Error('Google drive authentication error, !'));
}
});
Any idea?
hint: Is there any policy in AWS secret to access a secret or in google cloud to access a service account? for example access in local or online?
[NOTE: You are using a service account to access Google Drive. A service account will have its own Google Drive. Is this your intention or is your goal to share your Google Drive with the service account?]
Is there any policy in AWS secret to access a secret or in google
cloud to access a service account? for example access in local or
online?
I am not sure what you are asking. AWS has IAM policies to control secret management. Since you are able to create a Signed JWT from stored secrets, I will assume that this is not an issue. Google does not have policies regarding accessing service accounts - if you have the service account JSON key material, you can do whatever the service account is authorized to do until the service account is deleted, modified, etc.
Now on to the real issue.
Your Signed JWT has expired and you need to create a new one. You need to track the lifetime of tokens that you create and recreate/refresh the tokens before they expire. The default expiration in Google's world is 3,600 seconds. Since you are creating your own token, there is no "wrapper" code around your token to handle expiration.
The error that you are getting is caused by a code crash. Since you did not include your code, I cannot tell you where. However, the solution is to catch errors so that expiration exceptions can be managed.
I recommend instead of creating the Google Drive Client using a Signed JWT that you create the client with a service account. Token expiration and refresh will be managed for you.
Very few Google services still support Signed JWTs (which your code is using). You should switch to using service accounts, which start off with a Signed JWT and then exchange that for an OAuth 2.0 Access Token internally.
There are several libraries that you can use. Either of the following will provide the features that you should be using instead of crafting your own Signed JWTs.
https://github.com/googleapis/google-auth-library-nodejs
https://github.com/googleapis/google-api-nodejs-client
The following code is an "example" and is not meant to be tested and debugged. Change the scopes in this example to match what you require. Remove the section where I load a service-account.json file and replace with your AWS Secrets code. Fill out the code with your required functionality. If you have a problem, create a new question with the code that you wrote and detailed error messages.
const {GoogleAuth} = require('google-auth-library');
const {google} = require('googleapis');
const key = require('service-account.json');
/**
* Instead of specifying the type of client you'd like to use (JWT, OAuth2, etc)
* this library will automatically choose the right client based on the environment.
*/
async function main() {
const auth = new GoogleAuth({
credentials: {
client_email: key.client_email,
private_key: key.private_key,
},
scopes: 'https://www.googleapis.com/auth/drive.metadata.readonly'
});
const drive = google.drive('v3');
// List Drive files.
drive.files.list({ auth: auth }, (listErr, resp) => {
if (listErr) {
console.log(listErr);
return;
}
resp.data.files.forEach((file) => {
console.log(`${file.name} (${file.mimeType})`);
});
});
}
main()
I'm trying to generate AdSense reports on web app hosted on node.js.
Since it's a server-to-server communication i need to use service account.
I followed this guide, but i always getting error:
{
domain: "global"
message: "User does not have an AdSense account."
reason: "noAdSenseAccount"
}
also tried this JSON Web Tokens Guide but also getting error above.
What i got:
The Adsense Management API is enabled.
Service account credentials are created
Added service account email address to google AdSense User Management
Tested in the Google API Explorer and it works just fine
screenshot
NOTE: its status stuck on "pending".
Here is the code i'm trying to connect and retrieve data with:
const googleAuth = require('google-auth-library');
const GOOGLE_KEYS = require(path.join(__dirname, '/credentials/jwt.keys.json'));
this.jwtClient = new googleAuth.JWT(
GOOGLE_KEYS.client_email,
null,
GOOGLE_KEYS.private_key,
['https://www.googleapis.com/auth/adsense'],
);
this.jwtClient.authorize(async (err: any, tokens: any) => {
if (err) throw new Error(err);
this.jwtClient.setCredentials(tokens);
const url = `https://www.googleapis.com/adsense/v1.4/accounts`;
const listData = await this.jwtClient.request({url})
.catch((err: any) => {
console.log(err, 'error');
res.status(500).json(err)
});
res.status(200).json(data);
});
My questions is:
1. Why is it stuck on "pending" status?
2. Is there a way to acceess API using service account credentials?
3. If yes which way i can achieve it?
The AdSense API doesn't support Service Accounts[1], so you'll need to make OAuth credentials using the Web App flow[2].
I was using googleapis library and successfully authenticate my Service Account credentials using JWT. Then I found out google-cloud library, which has specific modules for Prediction API, but failed to authenticate the same Service Account credentials.
I don't use Google Computing Engine or App Engine and working in local developement
I follow code in documentation:
var key = require('./MY_SERVICE_ACCOUNT_CREDENTIALS.json')
var prediction = require('#google-cloud/prediction')({
projectId: 'MY_PROJECT_ID',
credentials: key
})
prediction.getModels((err, models) => {
if (err) {
console.log(err)
return
}
console.log('Models:', models)
})
and it returns:
{ ApiError: Access to project denied: user requires read permissions.
at [here goes stack trace]
code: 401,
errors:
[ { domain: 'global',
reason: 'authError',
message: 'Access to project denied: user requires read permissions.',
locationType: 'header',
location: 'Authorization' } ],
response: undefined,
message: 'Access to project denied: user requires read permissions.' }
I don't know where it goes wrong and I'm not sure if I would need to authenticate with googleapis and integrate it with google-cloud or etc. It's also lack of samples
So I know this is a couple of months old but the error is pretty self explanatory but I also ran into this issue myself.
Essentially your service key isn't given the proper permissions in order to read (or write) information from your project. Look for your service account under IAM & Admin in the Google Cloud Console and add Project → Editor and/or Project → Viewer to the service account you've created. Make sure you press "Save" once you've added those permissions and wait about 20 seconds for those permissions to reflect.
I'm trying out a (node.js) sample app to authenticate against Google API and then make a Google Drive request. The sample I am trying to run is from the github readme of the googleapis node.js library using jwt:
var jwtClient = new googleapis.auth.JWT(
'123...xyz#developer.gserviceaccount.com',
'./key.pem',
null,
['https://www.googleapis.com/auth/drive'],
'my.personal#gmail.com');
jwtClient.authorize(function(err, tokens) {
if (err) {
console.log(err);
return;
}
// Make an authorized request to list Drive files.
drive.files.list({ auth: jwtClient }, function(err, resp) {
// handle err and response
});
});
Authentication fails with:
{ error: 'unauthorized_client',
error_description: 'Unauthorized client or scope in request.' }
I'm not 100% sure about the 'my.personal#gmail.com'. Using my Client ID, I receive the error 'Invalid impersonation prn email address.'.
I have created service account client ID, service email and certificate fingerprints according to documentation. Do I have to specify additional things? Is my scope incorrect? If it is, what should it be?
Google Drive API is enabled in the Google Developer Console. I also activated the trial account.
Ugh, after trying many things, the result is rather simple: doing the above sample without 'impersonate'-email it just worked. Code:
var jwtClient = new googleapis.auth.JWT(
'123...xyz#developer.gserviceaccount.com',
'./key.pem',
null,
['https://www.googleapis.com/auth/drive']);
The example from the readme is available as a complete file inside examples (here).