Change CloudFront response using lambda#Edge - request

I have been trying to use lambda#edge to add the CloudFront-viewer-country header to my response, I managed to trigger the function and its working, but I can't see any logs in cloudWatch, cloudWatch is only logging the test which is done on the function page not the real test that got trigged by visiting the website, I googled how to find the logs and found out that its in cloudWatch of the nearest region that received the request, but I could not find any.
I have tried two methods to change my response one of them was on stack overflow answers: https://stackoverflow.com/questions/48633610/how-do-i-get-cloudfront-viewer-country-to-appear-in-response-headers
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
if(request.headers['cloudfront-viewer-country'])
{
response.headers['cloudfront-viewer-country'] = request.headers['cloudfront-viewer-country'];
}
return callback(null,response);
};
This method when gets tested from the lambda page it works, but when I test by accessing the website I get 503 server error: The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions.
So can someone help in these permissions, please note that I have the following policy on my s3 bucket which static hosts my website:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::outfityard-app-client/*"
}
]
}
The other method that I have tried was using the following function in my lambda:
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const uri = request.uri === "/index.html" ? "/" : request.uri;
var countryCode = null;
if(headers["cloudfront-viewer-country"]) {
countryCode = headers["cloudfront-viewer-country"][0].value;
}
console.log(`Country detected: '${countryCode}'`);
if (countryCode !== "US") {
const response = {
status: "200",
statusDescription: "Found",
headers: {
["cache-control"]: [
{
key: "Cache-Control",
value: "no-cache, no-store, private"
}
],
["cloudfront-viewer-country"]: [
{
key: "cloudfront-viewer-country",
value: countryCode
}
]
}
};
callback(null, response);
} else {
callback(null, request);
}
};
This method is returning the expected response but nothing gets loaded from my website which I don't understand why! here is the response headers that I received:
Content-Type →text/html
Content-Length →1217
Connection →keep-alive
Server →CloudFront
Date →Fri, 16 Aug 2019 11:37:19 GMT
X-Cache →LambdaExecutionError from cloudfront
Via →1.1 9891f2220bf61a27cb1f26085ab3703d.cloudfront.net (CloudFront)
X-Amz-Cf-Pop →CDG3-C2
X-Amz-Cf-Id →D542SzvAsMYAXIOcBUwHWEB5_lAf41t1wWULh6LcXwagAvjFRvH5nA==
I have used the following and its working fine but I don't know if its the right way to do it:
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
const value = request.headers['cloudfront-viewer-country'][0].value;
const key = request.headers['cloudfront-viewer-country'][0].key;
response.headers['cloudfront-viewer-country'] = [{key: key, value: value}];
return callback(null,response);
};

Related

Github Login (oAuth ) from react- chrome extension

I am building a simple chrome extension which will make some simple API calls.
For this, I need the user to be logged in with a Github Account, however, if I set up a new oAuth app on github, I need to add Homepage URL and Authorization callback URL which, as far as I understand, we don't have from a Chrome Extension popup.
IMPORTANT: I don't want to use firebase. All I need is to be able to get the user code, which I can process in my backend after to get the token and all the rest.
Need you help here ! :-)
Here is my background file
const GITHUB_AUTHORIZATION_UL = "https://github.com/login/oauth/authorize";
const CLIENT_ID = encodeURIComponent("xxxx");
const SCOPE = encodeURIComponent("user:email");
let user_signed_in = false;
function create_auth_endpoint() {
let endpoint_url = `${GITHUB_AUTHORIZATION_UL}
?client_id=${CLIENT_ID}
&scope=${SCOPE}`;
return endpoint_url;
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'login') {
chrome.identity.launchWebAuthFlow({
url: create_auth_endpoint(),
interactive: true
}, (response) => {
console.log(response)
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError)
console.log("Could not authenticate.");
sendResponse('fail');
} else {
user_signed_in = true;
sendResponse('success');
}
});
return true;
} else if (request.message === 'logout') {
user_signed_in = false;
sendResponse('success');
}
});
And my login handler from popup.tsx
const handleLogin = () => {
chrome.runtime.sendMessage({ message: 'login' }, function (response) {
console.log(response)
if (response === "success") {
window.close();
}
});
Manifest:
{
"name": "test ext",
"description": "test ext",
"version": "1.0.0",
"manifest_version": 3,
"icons": {
"16": "favicon-32.png",
"48": "favicon-32.png",
"128": "favicon-32.png"
},
"action": {
"default_popup": "popup.html",
"default_title": "test ext",
"default_icon": "favicon-32.png"
},
"permissions": ["storage", "identity"],
"options_page": "options.html",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}
]
}
I tried with various options for the requested url for github such as : http://chrome-extension://CHROME_ID/popup.html
=> This fails directly.
Interestingly, if I just input https://www.google.com, I have a popup with the github login, then I am directly to google and it fail.
However, the extension authorization is added as "accepted" in my github account.
Here is my log from the background for response :
{message: 'The user did not approve access.'}eventhough I approved it. Once I am redirected to the popup with www.google.com it fails

Alexa Proactive Events API returns 403 for unicast type -- No enablement for clientId

I am using Amazon's Alexa skills API and proactive events API to send notifications to my Alexa skill. I am able to send notification with multicast, but it does not work for delivery type "Unicast"
I am getting HTTP status code: 403 and error message as:
"No enablement for clientId:amzn-*********"
I have followed the Alexa skills proactive API documentation
When sending notification to endpoint
https://api.amazonalexa.com/v1/proactiveEvents/stages/development
I obtain the accesstoken using skill credentials and add the accesstoken as bearer token to the request.
Note: I have already enabled the skill from https://alexa.amazon.in and
I got the Amazon userId, apiAccesstoken, and consentToken. I stored them in my database (mongoDB).
I use the Amazon userId to send the notification
<pre>
<code>
var uuid = require('node-uuid');
var accessToken = "This`enter code here` token will be obtained from amazon oauth api.";
var userId = "amzn1.ask.account.AH2ZEP5WGJGAEPWPOG3Getc.....";
var uuid = require('node-uuid');
var referenceId = uuid.v4();
var now = new Date();
var expiresOn = addMinutes(now, 300);
var eventData = {
"timestamp": new Date(),
"referenceId": uuid,
"expiryTime": expiresOn,
"event": {
"name": "AMAZON.MessageAlert.Activated",
"payload": {
"state": {
"status": "UNREAD",
"freshness": "NEW"
},
"messageGroup": {
"creator": {
"name": "Andy"
},
"count": 5,
"urgency": "URGENT"
}
}
},
"localizedAttributes": [
{
"locale": "en-US",
"MessageAlert": "UNREAD"
},
{
"locale": "en-GB",
"MessageAlert": "UNREAD"
}
],
"relevantAudience": {
"type": "Unicast",
"payload": {
"user": userId
}
}
};
var opt = {
data: eventData,
token: accessToken
}
sendRequest(opt, function(err, ret, code) {
console.log("err : ",JSON.stringify(err, null, 2));
console.log("ret : ",JSON.stringify(ret, null, 2));
console.log("code : ",JSON.stringify(code, null, 2));
});
function sendRequest(options, callback) {
var data = options.data;
var token = options.token;
var headers = {
"Content-Type": "application/json",
"Authorization":"Bearer "+token
};
var opt = {
url: "https://api.amazonalexa.com/v1/proactiveEvents/stages/development",
method: "POST",
headers: headers,
body: JSON.stringify(data)
};
request(opt, function(error, response, body){
var statusCode = (response && response.statusCode) ? response.statusCode : "";
if(error) {
return callback(error);
} else if(body) {
try {
var result = JSON.parse(body);
return callback(null, result, statusCode);
} catch(e) {
console.log("e.message : ",e.message);
return callback(null, body, statusCode);
}
} else {
return callback(null, body, statusCode);
}
});
}
</code>
</pre>
The result should be HTTP status code with 202.
But I receive the HTTP status code 403 and the error message as:
"No enablement for clientId: *************"

SalesForce Create Lead Rest Api

My task is pretty simple, all i have to do is to create records in the lead section of the salesforce. I have created a free account and i am not able to figure it out that, what is https://yourinstance.saleforce.com in the below rest api:
https://yourinstance.salesforce.com/services/data/v39.0/sobjects/Lead
Body JSON:
{
"body": {
"Salutation": "Mr.",
"FirstName": "H",
"LastName": "Sam",
"Company": "Samosto"
}
}
Header:
Authorization: Bearer 00D0o0000015jPn!ARgAQPiIGhuYGUG_c0HDKNR0hxTX9zS82Fv1lIuqn4rapFJHPR422gLyi10rF8Auukb._hj9pj532DP7IajQV36lyKpUNEXdxvL
Content-Type: application/json
Sforce-Auto-Assign: TRUE
Any help will be highly appreciated!
This is the URL you have for the organization you want to login to. Since most of the orgs are using their own Domain names in guides or examples you will see this "https://yourinstance.saleforce.com" being used.
You can simply take it from the URL while logged in Salesforce or go to Setup -> quick search "My Domain" and you will see the domain name.
It is a good thing to check it from here as the generic URL can also be blocked as a login option.
fwiw i think the API has changed to Account. This is working for me
// to run:
// node create_new_account.js --config ./config_na150_scan_email_app.json
//
// links:
// https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_create.htm
const axios = require("axios");
const qs = require("qs");
const yargs = require("yargs");
const argv = yargs
.command('create_account', 'test creating salesforce leads', {
config: {
description: 'config',
alias: 'c',
type: 'string',
}
})
.help()
.alias('help', 'h')
.argv;
let { salesforce, scanResultsURL } = require(argv.config);
const auth_data = qs.stringify({"username": salesforce.username,
"password": salesforce.password + salesforce.security_token,
"grant_type": "password",
"client_id": salesforce.consumer_key,
"client_secret": salesforce.customer_secret,
"redirect_uri": salesforce.redirect_uri});
console.log("auth data", auth_data)
const auth_config = {
method: "post",
url: salesforce.oauth2_uri,
data: auth_data,
headers: {"Content-Type": "application/x-www-form-urlencoded"}
}
const action_url = "https://na<TBD>.salesforce.com/services/data/v51.0/sobjects/Account"
console.log('action url', action_url)
data = {
"Name" : "test Salesforce account API"
}
async function createAccout() {
// "get" token
axios(auth_config).then(function (response) {
auth_header = {"Authorization": "Bearer " + response["data"]["access_token"]}
action_config = {
method: "post",
url: action_url,
headers: auth_header,
data: data
}
// use valid token to send email
axios(action_config).then(function (response) {
console.log("action response", response["data"]); // TODO rm
}).catch(function (error) {
console.log("authenticated passed, action failed")
console.log("action error", error); // TODO something
})
}).catch(function (error) {
console.log("action token error", error); // TODO something
})
}

how to get value from response from Microsoft cogntive services

I am making a http request to "Microsoft cogntive services" ; and I am getting a proper answer, but I am failing to get the value out of the response.
Here is my script:
'use strict';
const request = require('request');
// Replace <Subscription Key> with your valid subscription key. const subscriptionKey = 'xyz'; // here my API key
// You must use the same location in your REST call as you used to get your // subscription keys. For example, if you got your subscription keys from // westus, replace "westcentralus" in the URL below with "westus". const uriBase = 'https://westeurope.api.cognitive.microsoft.com/face/v1.0/detect';
const imageUrl =
'https://images.unsplash.com/photo-1534559529872-1a83a6cbc03d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=56820e7b0db7b8a7f10804cd157f61ef&w=1000&q=80'
// Request parameters. const params = {
'returnFaceId': 'true',
'returnFaceLandmarks': 'false',
'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise' };
const options = {
uri: uriBase,
qs: params, // json: true, // dies nachtäglich eingefügt ev. löschen
body: '{"url": ' + '"' + imageUrl + '"}',
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key' : subscriptionKey
} };
request.post(options, (error, response, body) => { if (error) {
console.log('Error: ', error);
return; } let jsonResponse = JSON.stringify(JSON.parse(body), null, ' '); console.log('JSON Response\n'); console.log(jsonResponse); });
and here the response that I get:
[ {
"faceId":"f469c0b3-fbb8-4238-a52a-54fd515a2bca",
"faceRectangle":{
"top":327,
"left":253,
"width":426,
"height":426
},
"faceAttributes":{
"smile":0.005,
"headPose":{
"pitch":0,
"roll":0.7,
"yaw":-4.4
},
"gender":"female",
"age":23,
"facialHair":{
"moustache":0,
"beard":0,
"sideburns":0
},
"glasses":"NoGlasses",
"emotion":{
"anger":0,
"contempt":0,
"disgust":0,
"fear":0,
"happiness":0.005,
"neutral":0.994,
"sadness":0.001,
"surprise":0
},
"blur":{
"blurLevel":"low",
"value":0
},
"exposure":{
"exposureLevel":"goodExposure",
"value":0.64
},
"noise":{
"noiseLevel":"low",
"value":0
},
"makeup":{
"eyeMakeup":true,
"lipMakeup":true
},
"accessories":[
],
"occlusion":{
"foreheadOccluded":false,
"eyeOccluded":false,
"mouthOccluded":false
},
"hair":{
"bald":0.02,
"invisible":false,
"hairColor":[
{
"color":"blond",
"confidence":0.99
},
{
"color":"gray",
"confidence":0.74
},
{
"color":"other",
"confidence":0.35
},
{
"color":"brown",
"confidence":0.31
},
{
"color":"red",
"confidence":0.15
},
{
"color":"black",
"confidence":0.06
}
]
}
} } ]
Now would I would like to do it to get the value for "faceID" or faceAttributes.gender or faceAttributes.age
I have tried that with the following commands, but I always get the following errors.
i.e.
console.log(jsonResponse.faceId);
log-message:
script.js.facedetect_node: undefined
i.e.
console.log(jsonResponse.faceId[0]);
log-message:
uncaught exception: Cannot read property '0' of undefined
i.e.
console.log(jsonResponse.faceAttributes[0]);
i.e.
console.log(jsonResponse.faceAttributes.age[0]);
log-message
TypeError: Cannot read property '0' of undefined
I guess you have already seen that I am quite a newbie - for this reason I would highly appreciate if you have an idea how I can get the mentioned values out of this json.
cu
schroedinger

Can't get my Facebook messenger bot to respond with response from my service

I have made an Api.Ai bot and integrated it with both Slack and Facebook Messenger. When I write to it, it answers with the responses set up in Api.Ai for both Slack and Facebook Messenger, but on the fulfillment part, when Api.Ai makes a call to my service, it works fine in Slack, but I get no response from Facebook Messenger.
The format of the message I return from my service:
{
"contextOut": [
{
"lifespan": 2,
"name": "weather",
"parameters": {
"city": "Rome"
}
}
],
"data": {
"facebook": {
"message": {
"text": "Great success!"
},
"recipient": {
"id": "1454102654663349"
}
},
"slack": {
"attachments": [
{
"color": "#00A399",
"title": "Hello world!",
"title_link": "https://www.mywebsite.se"
}
],
"text": "Horray! Great success! :)"
}
},
"displayText": "Whatever!!",
"followupEvent": {
"followupEvent": {
"data": {
"parameter": "<parameter_value>"
},
"name": "<event_name>"
}
},
"source": "mywebsite.se",
"speech": "Whatever!?"
}
The Facebook recipient id comes from the request made to my service.
request.result.contexts[0].parameters.Facebook_sender_id
I have verified my webhook under the product settings tab in the Facebook app.
I have subscribed my app to the page using my page access token.
I have checked the following events under webhooks: messages, messaging_postbacks
I'm logged in as the admin user of the app, when trying the bot in Facebook.
I'm out of ideas, there must be something I've missed?
EDIT:
I've set up an Azure Function as my webhook for testing purposes.
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
var request = await req.Content.ReadAsAsync<ApiAiMessage>();
log.Info($"Incoming: {JsonConvert.SerializeObject(request)}");
var slack_message = new {
text = $"Horray! Great success! :)",
attachments = new[] {
new {
title = "Hello world!",
title_link = "https://www.mywebsite.se",
color = "#00A399"
}
}
};
var facebook_message = new {
recipient = new {
id = $"{request.result.contexts[0].parameters.Facebook_sender_id}"
},
message = new {
text = "Great success!"
}
};
var response = new
{
data = new
{
facebook = facebook_message,
slack = slack_message
},
speech = "Whatever!?",
displayText = "Whatever!!",
contextOut = new[] {
new {
name = "weather",
lifespan = 2,
parameters = new {
city = "Rome"
}
}
},
source = "mywebsite.se",
followupEvent = new {
followupEvent = new {
name = "<event_name>",
data = new {
parameter = "<parameter_value>"
}
}
}
};
log.Info($"Outgoing: {JsonConvert.SerializeObject(response)}");
return req.CreateResponse(HttpStatusCode.OK, response, new MediaTypeHeaderValue("application/json"));
}
Where are you actually sending the API.ai response back to Facebook Messenger? This requires some FB specifics like the 'page token' and the fact it works for Slack but not FB makes me believe it's just something simple left out like this. Here's an example in javascript of what the call would look like
function callSendAPI(messageData) {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {
access_token: config.FB_PAGE_TOKEN
},
method: 'POST',
json: messageData
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
if (messageId) {
console.log("Successfully sent message with id %s to recipient %s",
messageId, recipientId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
} else {
console.error("Failed calling Send API", response.statusCode, response.statusMessage, body.error);
}
});
}

Resources