Problems connecting Service Account to Admob API with Google-Auth-Library - node.js

I've been trying to connect to Admob API from an AWS Lambda to extract some values from reports automatically from time to time. I've successfully got google-auth-library-nodejs to a layer and I am trying to use it to connect to Admob API.
I've made sure to give my Service account an Owner role and I've added the necessary GOOGLE_APPLICATION_CREDENTIALS path to the environement variables.
This is the code that I've added to my Lambda:
const {GoogleAuth} = require('google-auth-library');
exports.handler = (event, context, callback) => {
async function main() {
const auth = new GoogleAuth({
scopes: ['https://www.googleapis.com/auth/admob.report'],
});
const client = await auth.getClient();
//console.log("client", JSON.stringify(client));
const url = `https://admob.googleapis.com/v1/accounts`;
const res = await client.request({ url });
console.log("res: ", JSON.stringify(res.data));
}
main().catch(console.error);
};
When I run the code, I get the following error:
ERROR GaxiosError: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
at Gaxios._request (/opt/nodejs/node_modules/gaxios/build/src/gaxios.js:85:23)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at async JWT.requestAsync (/opt/nodejs/node_modules/google-auth-library/build/src/auth/oauth2client.js:350:18)
at async main (/var/task/index.js:97:19) {
response: {
config: {
url: 'https://admob.googleapis.com/v1/accounts',
headers: [Object],
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
responseType: 'json',
method: 'GET'
},
data: { error: [Object] },
headers: {
'alt-svc': 'quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000',
'cache-control': 'private',
connection: 'close',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Wed, 26 Feb 2020 18:41:51 GMT',
server: 'ESF',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin, Referer',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0'
},
status: 401,
statusText: 'Unauthorized',
request: { responseURL: 'https://admob.googleapis.com/v1/accounts' }
},
config: {
url: 'https://admob.googleapis.com/v1/accounts',
headers: {
Authorization: 'Bearer [Removed]',
'User-Agent': 'google-api-nodejs-client/5.10.1',
'x-goog-api-client': 'gl-node/12.14.1 auth/5.10.1',
Accept: 'application/json'
},
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
responseType: 'json',
method: 'GET'
},
code: 401,
errors: [
{
message: 'Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.',
domain: 'global',
reason: 'unauthorized'
}
]
}
I've been trying to find my mistake by searching on google, stack overflow, reading tutorials about connecting to Admob API as well as reading the library's code. I would really appreciate if someone could point me towards a solution.

The problem is you are trying to use a service account where OAuth User Credentials are required. You will need to implement the OAuth 2 Flow where the user enters their Google username and password.
AdMob: Authorization for the request
Refer to the following Google example on how to create a node.js OAuth 2 client.
https://github.com/googleapis/google-auth-library-nodejs#oauth2

Related

Problems with getting Apple Pay payment session

A year ago we implemented ApplePay on the web in our project and everything worked just fine. But now it's unstable and payment can be successful on the third try sometimes. We are facing an ECONNRESET error while requesting POST https://apple-pay-gateway.apple.com/paymentservices/startSession and an error message “Payment not completed” on the client side
Error: read ECONNRESET at TLSWrap.onStreamRead (internal/stream_base_commons.js:209:20) {
errno: -104,
code: 'ECONNRESET',
config: {
url: 'https://apple-pay-gateway.apple.com/paymentservices/startSession',
method: 'post',
data: '{"merchantIdentifier":"merchant.com.xxxxxxxx","displayName":"xxxxxxxxxx","initiative":"web","initiativeContext":"xxxxxxxx.xxx","domainName":"xxxxxxxx.xxx"}',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.19.2',
'Content-Length': 191
}
},
...
response: undefined,
isAxiosError: true,
Client side code:
applePaySession.onvalidatemerchant = async (event) => {
try {
const data = {
url: event.validationURL,
method: 'post',
body: {
merchantIdentifier,
displayName,
initiative: "web",
initiativeContext: window.location.hostname
},
json: true,
}
const merchantSession = await this.$axios.$post('/apple_pay_session', data);
if (merchantSession && merchantSession.merchantSessionIdentifier) {
applePaySession.completeMerchantValidation(merchantSession)
} else {
applePaySession.abort();
}
} catch (error) {
logReqError(error)
applePaySession.abort();
}
};
Server side:
const httpsAgent = new https.Agent({
rejectUnauthorized: false,
keepAlive: true,
cert: fs.readFileSync(`uploads/apple_pay/${id}/certificate.pem`),
key: fs.readFileSync(`uploads/apple_pay/${id}/private.key`)
});
const sessionRes = await axios({
url: request.body.url,
method: request.body.method.toLowerCase(),
data: request.body.body,
headers: {'Content-Type': 'application/json'}, httpsAgent
})
We checked the status of Merchant Domain - it's verified, Apple Pay Payment Processing Certificate and Apple Pay Merchant Identity Certificate are valid. I also checked project code with the official documentation, as well as with other sources.
I hope anyone has had a similar problem. Any code samples or guesses will be helpful anyway

PayPal 401 Client Authentication Failed in Sandbox environment with node js sdk

I've followed this guide https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/ and this example https://github.com/paypal/Checkout-Nodejs-SDK/
Here is my code:
import paypalCheckout from '#paypal/checkout-server-sdk';
const environment = new paypalCheckout.core.SandboxEnvironment(
'ACTUAL_CLIENT_ID_FROM_PAYPAL_DASHBOARD',
'ACTUAL_CLIENT_SECRET_FROM_PAYPAL_DASHBOARD'
);
const client = new paypalCheckout.core.PayPalHttpClient(environment);
const request = new paypalCheckout.orders.OrdersCreateRequest();
request.requestBody({
intent: 'CAPTURE',
purchase_units: [
{
amount: {
currency_code: 'USD',
value: `100.00`
}
}
],
});
client.execute(request)
.then((response) => {
console.log(`${JSON.stringify(response)}`);
console.log(`${JSON.stringify(response?.result)}`);
})
.catch((executeError) => {
console.log(`${JSON.stringify(executeError)}`);
});
I get:
{
error: HttpError: {"error":"invalid_client","error_description":"Client Authentication failed"}
at IncomingMessage.<anonymous> (.../node_modules/#paypal/paypalhttp/lib/paypalhttp/http_client.js:136:22)
at IncomingMessage.emit (events.js:388:22)
at endReadableNT (internal/streams/readable.js:1336:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
statusCode: 401,
headers: {
'content-type': 'application/json',
'content-length': '77',
connection: 'close',
date: 'Tue, 29 Jun 2021 01:22:38 GMT',
'cache-control': 'max-age=0, no-cache, no-store, must-revalidate',
'paypal-debug-id': 'c2b.......c7a',
'x-paypal-token-service': 'IAAS',
'strict-transport-security': 'max-age=31536000; includeSubDomains'
},
_originalError: {
text: '{"error":"invalid_client","error_description":"Client Authentication failed"}',
statusCode: 401,
headers: [Object]
}
},
message: '{"error":"invalid_client","error_description":"Client Authentication failed"}'
}
I've searched Google and Stack Overflow but I only find similar issues about switching from sandbox to live.
My code isn't working in sandbox environment.

the problem of unauthorized in IBM watson assistant Nodejs

I tried the API v1 and v2 of IBM Watson assistant to creat a new conversion.
But it gived me always the samr error code 401 Unauthorized: Access is denied due to invalid credentials.
i don't know what happened, thanks in advance for your answers.
{ Unauthorized: Access is denied due to invalid credentials.
at RequestWrapper.formatError (E:\Documents\Techniques\Desktop\front_back_end\version-watson\node_modules\ibm-watson\node_modules\ibm-cloud-sdk-core\lib\requestwrapper.js:218:21)
at E:\Documents\Techniques\Desktop\front_back_end\version-watson\node_modules\ibm-watson\node_modules\ibm-cloud-sdk-core\lib\requestwrapper.js:206:29
at process._tickCallback (internal/process/next_tick.js:68:7)
name: 'Unauthorized',
code: 401,
message: 'Access is denied due to invalid credentials.',
body: '{"code":401,"error":"Unauthorized"}',
headers:
{ 'x-backside-transport': 'FAIL FAIL',
'content-type': 'application/json',
'x-dp-transit-id': 'gateway01-1474836587',
'x-global-transaction-id': '7ecac92c5d14b5ae57e8386b',
'strict-transport-security': 'max-age=31536000;',
'x-dp-watson-tran-id': 'gateway01-1474836587',
'content-length': '37',
'x-edgeconnect-midmile-rtt': '82',
'x-edgeconnect-origin-mex-latency': '110',
date: 'Thu, 27 Jun 2019 12:25:18 GMT',
connection: 'close' } }
const AssistantV1 = require('ibm-watson/assistant/v1');
const service = new AssistantV1({
version: '2019-02-28',
iam_apikey: '{apikey}',
url: '{url}'
});
service.message({
workspace_id: '{workspace_id}',
input: {'text': 'Hello'}
})
.then(res => {
console.log(JSON.stringify(res, null, 2));
})
.catch(err => {
console.log(err)
});
I am not sur that for Version2 the session-id is correct or not. But the API v1 doesn't need the session_id, it gives the same error code too.

how to read data from apiResponse in Nodejs typescript?

I want to read data from a googleapis call. I am using async-await. But I am not sure how to read the data that I am getting back.
async function makeCall(params:String){
const apiResponse = await goopleapi.particular.get(params);
console.log(`not really sure how to read -- ${apiResponse}`;
// problem is the log prints [object Object].
}
How do I get the log from printing [object Object] to the actual content of the response? Ultimately I want to read the json that comes back -- how do I do that? Thanks.
In case it's important. I am using Firebase as a back-end with Typescript
udpate 1
The api in question is for billing. As in https://www.googleapis.com/auth/androidpublisher. I am calling .purchases.products.get. And when I try to parse the response with JSON.parse(apiResponse), I get the error:
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
at getItem (/srv/lib/index.js:31:69)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:145:8)
documentation: https://developers.google.com/android-publisher/api-ref/purchases/products/get
update 2
Here is the apiResponse that I need to parse into json. I tried using JSON.parse(apiResponse) but got an error:
{ config:
{ url: 'https://www.googleapis.com/androidpublisher/v2/applications/mypath',
method: 'GET',
paramsSerializer: [Function],
headers:
{ 'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/2.0.0 (gzip)',
Authorization: 'Bearer somecode',
Accept: 'application/json' },
params: {},
validateStatus: [Function],
retry: true,
responseType: 'json' },
data:
{ kind: 'androidpublisher#productPurchase',
purchaseTimeMillis: '111222333',
purchaseState: 0,
consumptionState: 1,
developerPayload: '',
orderId: 'some string',
purchaseType: 0 },
headers:
{ 'alt-svc': 'quic=":111"; ma=33445566; v="a string"',
'cache-control': 'private, max-age=0, must-revalidate, no-transform',
connection: 'close',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Fri, 14 Jun 2019 12:40:12 GMT',
etag: '"some string"',
expires: 'Fri, 14 Jun 2019 12:40:12 GMT',
server: 'GSE',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block' },
status: 200,
statusText: 'OK' }
The error is still the same as in "update 1"
Template strings will call toString on the parts. You need to do
console.log('You need to pass it as a parameter', apiResponse)
If you want to print the actual object to the console.
The object has already been parsed. The error is from passing json to JSON.parse() which expects a string.
[object Object] is returned from the objects toString() method in a template literal, to avoid this:
console.log('Some string',apiResponse);
if theres still a problem try console.log(JSON.stringify(apiResponse))

How to find api-key and password for ibm-watson for Watson Assistant API working with nodejs

I'm trying to access my assistant but I'm getting a 404 Not Found error when inserting the iam_api_key and the url provided in the dahsboard.
And I can't find the password in the dahsboard.
I'm working with Node.js. I've tried to create other service credentials but nothing worked
{
username: '{api-key}',
password: '{password}', // I can't find this
// OR even
iam_apikey: '{api-key}'
url: '{url}',
version: '{version}',
disable_ssl_verification: true,
}
{ Not Found: Resource not found
{ ... }
at
at process._tickCallback (internal/process/next_tick.js:188:7) name: 'Not Found', code: 404, message: 'Resource not found',
body: '{"error":"Resource not found","code":404}', headers: {
'x-backside-transport': 'FAIL FAIL',
'content-type': 'application/json; charset=utf-8',
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS',
'access-control-allow-headers': 'Content-Type, Content-Length, Authorization, X-Watson-Authorization-Token, X-WDC-PL-OPT-OUT,
X-Watson-UserInfo, X-Watson-Learning-Opt-Out, X-Watson-Metadata',
'access-control-max-age': '3600',
'content-security-policy': 'default-src \'none\'',
'x-dns-prefetch-control': 'off',
'x-frame-options': 'SAMEORIGIN',
'strict-transport-security': 'max-age=31536000;',
'x-download-options': 'noopen',
'x-content-type-options': 'nosniff',
'x-xss-protection': '1; mode=block',
'x-global-transaction-id': '{x-global-transaction-id}',
'x-dp-watson-tran-id': '{x-dp-watson-tran-id}',
'x-dp-transit-id': '{x-dp-transit-id}',
'content-length': '41',
'x-edgeconnect-midmile-rtt': '124',
'x-edgeconnect-origin-mex-latency': '142',
date: 'Wed, 19 Jun 2019 20:38:08 GMT',
connection: 'close' } }
You have to use either the api key OR the username / password combination. The API docs for IBM Watson Assistant have code samples for Node.js:
const AssistantV2 = require('ibm-watson/assistant/v2');
const assistant = new AssistantV2({
version: '{version}',
iam_apikey: '{apikey}',
url: '{url}'
});
Use this code as well. It's working on me. I added serviceUrl and headers. Make sure to add the correct service URL according to the assistant URL.
const assistant = new AssistantV2({
version: "2019-02-28",
authenticator: authenticator,
url: process.env.WATSON_ASSISTANT_URL,
serviceUrl: "https://api.us-south.assistant.watson.cloud.ibm.com",
headers: {
"X-Watson-Learning-Opt-Out": "true",
},
});
Refer more - https://cloud.ibm.com/apidocs/assistant-v2?code=node#endpoint-cloud

Resources