SendGrid 403 Response for /v3/contactdb/recipients - Permissons needed - node.js

What permissions do I need or what am I doing wrong with this SendGrid API call?
I'm trying to post a new recipient ( /contactdb/recipients ) to Send Grid but keep getting a 403 response:
I get this even when calling the API from the SendGrid Explorer
Contacts API - Recipients
POST -> Add recipients
{
"errors": [
{
"field": null,
"message": "access forbidden"
}
]
}
This makes me think that my API Key doesn't have enough permissions but it has Full Access.
Here is my client code as well.
require("dotenv").config();
const client = require("#sendgrid/client");
exports.handler = function(event, context, callback) {
const body = JSON.parse(event.body);
const email = body.email;
if (!process.env.SENDGRID_API_KEY) {
callback("No API Key");
}
client.setApiKey(process.env.SENDGRID_API_KEY);
const request = {
method: "POST",
url: "/v3/contactdb/recipients",
body: JSON.stringify([{ email }])
};
client
.request(request)
.then(([response, body]) => {
// console.log(response.statusCode);
// console.log(body);
callback(null, response, body);
})
.catch(error => {
// console.log(JSON.stringify(error.response.body.errors));
callback(error);
});
};

Per support:
We have just very recently released a "New Marketing Campaigns"
experience and the endpoints have changed from our "Legacy Marketing
Campaigns".
Try this endpoint:
https://api.sendgrid.com/v3/marketing/contacts
I pulled it from our documentation here:
https://sendgrid.api-docs.io/v3.0/contacts/add-or-update-a-contact

Update
Previous answer does not coordinating the issue directly, sendgrid recently changed their internal api's base url, creating list of recipients which internally are static collections of Marketing Campaigns contacts. This API allows you to interact with the list objects themselves. To add contacts to a list, you must use the Contacts API.
Legacy api :
/v3/contactsdb/lists
New functional variant
/v3/marketing/lists

Related

register webhooks on nodejs when order created

I have a shopify store mystore and I have an nodejs app myapp. I need to do is when something happens on mystore a webhook will be created/registered in my nodejs app. I have tried https://www.npmjs.com/package/#shopify/koa-shopify-webhooks this package but it is not working for me and I don't think that it is the same thing that I want. I just want that when let suppose order is created in store a webhook is registered.
if you just have to register a webhook you can use this code.
You just have to change the webhook topic and the endpoint.
This is for orders/create webhook registration
add shopify-api-node and request-promise packages and require them
const ShopifyAPIClient = require("shopify-api-node");
const request = require("request-promise");
then
const createOrderWebhook = await registerWebhook(yourShopDomain, yourShopAccessToken, {
topic: "orders/create",
address: "Your node app end point" //www.example.com/webhooks/createOrder,
format: "json",
});
add your registerWebhook function
const registerWebhook = async function (shopDomain, accessToken, webhook) {
const shopify = new ShopifyAPIClient({
shopName: shopDomain,
accessToken: accessToken,
});
const isCreated = await checkWebhookStatus(shopDomain, accessToken, webhook);
if (!isCreated) {
shopify.webhook.create(webhook).then(
(response) => console.log(`webhook '${webhook.topic}' created`),
(err) =>
console.log(
`Error creating webhook '${webhook.topic}'. ${JSON.stringify(
err.response.body
)}`
)
);
}
};
for checking the webhook already not created at Shopify you can use following code
const checkWebhookStatus = async function (shopDomain, accessToken, webhook) {
try {
const shopifyWebhookUrl =
"https://" + shopDomain + "/admin/api/2020-07/webhooks.json";
const webhookListData = {
method: "GET",
url: shopifyWebhookUrl,
json: true,
headers: {
"X-Shopify-Access-Token": accessToken,
"content-type": "application/json",
},
};
let response = await request.get(webhookListData);
if (response) {
let webhookTopics = response.webhooks.map((webhook) => {
return webhook.topic;
});
return webhookTopics.includes(webhook.topic);
} else {
return false;
}
} catch (error) {
console.log("This is the error", error);
return false;
}
};
Happy coding :)
You can not create/register a new webhook when the order created.
Webhooks are a tool for retrieving and storing data from a certain event. They allow you to register an https:// URL where the event data can be stored in JSON or XML formats. Webhooks are commonly used for:
Placing an order
Changing a product's price
Notifying your IM client or your pager when you are offline
Collecting data for data-warehousing
Integrating your accounting software
Filtering the order items and informing various shippers about the order
Removing customer data from your database when they uninstall your app

Why do I receive 402 code for request when implementing Digital Goods Purchase for Actions on Google?

My Assistant app gets a status of PEMISSION_DENIED with a message saying that
the caller does not have permission
I have followed all instructions here by this person: Digital Goods Implementation
I have created APK, managed SKU (valid status) items, Android app that became published (valid status), enabled Actions API from Google API Console and made a service account key for my project, and released my Assistant app for beta to test it. The Connect App status is connected and the toggle is on. I think everything required is completed but the error message does not get fixed, which means I cannot receive purchasable items I prepared in my Google Developer Console.
const createJwtClient = () => {
const scopes = [
"https://www.googleapis.com/auth/actions.purchases.digital"
];
return new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes,
null
);
};
const packageName = 'com.myproject.name'
const getSkus = (tokens, conv) => {
return new Promise((resolve, reject) => {
const url = `https://actions.googleapis.com/v3/packages/${packageName}/skus:batchGet`;
const convId = conv.request.conversation.conversationId;
const param = {
conversationId: convId,
skuType: "SKU_TYPE_IN_APP",
ids: [
"item-id1",
"item-id2"
]
};
request.post(url, {
auth: {
bearer: tokens.access_token
},
json: true,
body: param
}, (err, httpResponse, body) => {
if (err) {
reject(err);
} else {
const statusCode = httpResponse.statusCode;
const statusMessage = httpResponse.statusMessage;
console.log(`${statusCode}: ${statusMessage}`);
console.log(JSON.stringify(body));
resolve(body);
}
});
});
};
I expect I get purchasable items as JSON, but my request to fetch SKU seems to fail.
But I do receive access_token from JWT request using my service account key.
Could you point out something that is wrong??
First, make sure your testing email is different from the Play Console Admin's email. Second, ensure you've added managed products and subscriptions to the Google Play Console (see below) The Actions on Google Github sample has been recently updated as well and the Kotlin APK has all the specifics in the 'Getting Started' section of the readme.

How to know authenticated email of an user who authenticated with his google account for my app

I am integrating google authentication for my app for creating calender events.
const {google} = require('googleapis');
const SCOPES = ['https://www.googleapis.com/auth/calendar','https://www.googleapis.com/auth/userinfo.email']
I have used the above scopes in authentication and generated the url and sent to the client. Authentication got success and i am able to receive code and generating token.
But with the code, I need the authenticated user's email, whoever signed in. Is there any way/example to know how to get user's email?. I searched in google for finding solution. But i didn't get that. Help me to know about this.
After you have received the token, you need to make a HTTP request to the userinfo endpoint using that token to get the required user info.
You can get the url for that endpoint from the discovery document which can be found at https://accounts.google.com/.well-known/openid-configuration.
The current url to get user info is https://openidconnect.googleapis.com/v1/userinfo.
If you do a calendar get on the users primary calendar. All users have a primary calendar
request
GET https://www.googleapis.com/calendar/v3/calendars/primary
response
{
"kind": "calendar#calendar",
"etag": "\"JWPyaEfg9X1jMhlHCcI4tl2h6uo/AxePbI13h8-KuIOLek\"",
"id": "xxxx#gmail.com",
"summary": "xxx#gmail.com",
"timeZone": "Europe/Copenhagen",
"conferenceProperties": {
"allowedConferenceSolutionTypes": [
"eventHangout"
]
}
}
Both Id and summary will be the users email address. By doing it this way you will not need to request the https://www.googleapis.com/auth/userinfo.email scope
Node guesss
Note: I am not a node.js developer this is a wild guess you will have to work this out
function listEvents(auth) {
const calendar = google.calendar({version: 'v3', auth});
calendar.about.get({
calendarId: 'primary'
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const results = res;
if (results ) {
console.log(results.id);
} else {
console.log('No upcoming events found.');
}
});

Authenticate with Azure AD with Node

I have a Native Client Application setup in my Azure Active Directory environment. I am trying to write a Node app for Utility purposes to interact with the Azure Management APIs. My challenge is just authenticating my app. At this time, I have:
let azure = {
clientId: '[only-for-my-eyes]',
key: '[only-for-my-eyes]',
tenantDomain: 'mydomain.onmicrosoft.com',
tenantId: '[only-for-my-eyes]'
};
let authenticationRequest = {
url: `https://login.microsoftonline.com/${azure.tenantDomain}/oauth2/v2.0/authorize`,
headers: {
'Content-Type':'application/x-www-form-urlencoded'
},
formData: {
response_type: 'code',
response_mode: 'form_post',
grant_type:'client_credentials',
resource: 'https://management.azure.com',
client_id: azure.clientId,
client_secret: azure.key
}
};
request.post(authenticationRequest, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
} else {
console.log(response.statusCode);
console.log(response.statusMessage);
}
});
When the above runs, the 200 status code block is executed. But, it just prints out a bunch of HTML. If I'm looking at it correctly, it looks like the HTML of the login screen. I'm trying to get an access token that I can pass to the management APIs.
What am I missing?
Why not just use ARMClient? All the nasty token business is taken care of.
From https://www.npmjs.com/package/armclient:
Initialization:
// ES5
var ArmClient = require('armclient');
var client = ArmClient({
subscriptionId: '111111-2222-3333333',
auth: ArmClient.clientCredentials({
tenantId: '444444-555555-666666666',
clientId: '777777-888888-999999999',
clientSecret: 'aaaabbbbbccccc' // or servicePrincipalPassword
})
});
Get resources in your subscription:
client.get('https://management.azure.com/subscriptions/111-222-333-444/resourceGroups/lab/providers/Microsoft.Automation/automationAccounts', { 'api-version': '2015-10-31' })
.then((res) => {
console.log(res.body);
console.log(res.headers);
})
.catch((err) => {
console.log(err);
});
I believe that particular endpoint is intended for a GET with those given parameters, not a POST. I suspect what you're seeing is probably just the generic error message:
Sorry, but we’re having trouble signing you in.
We received a bad request.
What you are trying to do is to call the authorization page with a POST request. You don't have to send a POST (or GET) request here, you must redirect your user to that authorization URL.
In addition, you must have a redirect URI (I don't see it in your azure object). This redirect URI is a callback to your application. For the rest of my answer, let say it is stored in azure.redirectUri
let url = 'https://login.microsoftonline.com/${azure.tenantDomain}/oauth2/v2.0/authorize?response_type=code&response_mode=form_post&client_id={azureclient_id}&resource=https%3A%2F%2Fmanagement.azure.com&redirect_uri={azure.redirectUri}'
response.writeHead(302, {
'Location': url
});
response.end();
The user will be redirected to the authorization page and will have to accept (or deny) your application request. Then the user is redirected back to your Node.js application (azure.redirectUri).
As your response_mode is form_post, if the user accepted your application request, you will receive the authorization code in the body parameters.
With that code your application will be able to get an access token by calling the token endpoint.

Retrieve info for specific user's ID

I do my PHD work dedicated to Social Network Analysis.
As tools was selected Node JS and Facebook API
Now what I can do is retrieve user's ID's with the additional info, but to build graph I need lists of the user's friends.
I have Heroku App but I'm totally disappointed what to do with te APP_ID to get information needed to build data.
Where I should start?
There are some Node.js packages available for this purpose.
Third party SDKs for Facebook
This is very useful, in case you want to write the same code and share between your server (nodejs) and the client (FB JS-SDK)
In order to start, you need to have access_tokens from users, you want information from. (Through FB App)
FB.login(function(response) {
if (response.authResponse) {
var res = response.authResponse;
FB.api('/me', function(response) {
registerUser({ "fb_user_id": res.userID, //register user in your database
"access_token": res.accessToken
}, function() {
//handle here after registration
});
});
} else {
//handle reject in requested fields
}
}, { scope: 'email,friends_about_me'});
//you can set scope field according to your use.
Refer to this for extended profile properties that can be used in scope field.
Once you get access_tokens, you can use them with one of the third party SDK above.
For example with facebook-node-sdk,
This sdk also provides you request access_token api
var FB = require('fb');
var accessToken = FB.getAccessToken();
FB.setAccessToken(accessToken);
FB.api('idHere', { fields: ['id', 'name'] }, function (res) { //you can access fields, access_token has access to
if(!res || res.error) {
console.log(!res ? 'error occurred' : res.error);
return;
}
console.log(res.id);
console.log(res.name);
});
You can also use api function directly with access_token.
FB.api('me', { fields: ['id', 'name'], access_token: 'access_token' }, function (res) {
console.log(res);
}

Resources