finding user on aws cognito throws error cognitoidentityserviceprovider is not defined - amazon-web-services

I am new to AWS services and I am trying out various services provided by AWS. I have this lambda function on which I am trying to find a user with the phone number on AWS Cognito -
const AWS = require('aws-sdk');
async function findCognitoUser(userId) {
console.log('CognitoUser-FindCognitoUser');
var params = {
UserPoolId: 'poolId',
AttributesToGet: [
'phone_number','displayName'
],
Filter: `phone_number = \"${userId}\"`,
};
cognitoidentityserviceprovider.listUsers(params, function(err, data) {
if (err) {
return 'ERROR OCCURED';
}
else {
return data.Users[0].displayName;
}
});
}
module.exports = findCognitoUser;
I do get an error saying cognitoidentityserviceprovider is not defined
Here is the error on CloudWatch -
"errorType": "ReferenceError",
"errorMessage": "cognitoidentityserviceprovider is not defined",
"stack": [
"ReferenceError: cognitoidentityserviceprovider is not defined",
" at findCognitoUser (/var/task/user-queries/findCognitoUser.js:13:5)",
" at Runtime.exports.handler (/var/task/index.js:14:19)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
CODE UPDATED -
const AWS = require('aws-sdk');
async function findCognitoUser(userId) {
console.log(userId);
var csp = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
var params = {
UserPoolId: 'poolid',
AttributesToGet: [
'phone_number','given_name'
],
Filter: `phone_number = \"${userId}\"`,
};
csp.listUsers(params, function(err, data) {
console.log(data);
if (err) {
return 'ERROR OCCURED';
}
else {
return data.Users[0].given_name;
}
});
}
module.exports = findCognitoUser;

Related

AWS Lambda not Pulling Data from DynamoDB and returning in on AWS Lex

I am trying to pull and display data from DynamoDb by using AWS Lambda function and have it display on AWS Lex. It is returning the if portion with the word "undefined" in the place where the data should be. The information is in the DynamoDB database. I am mainly using AWS servers and building this serverless Lex bot application.
AWS code Segments
const AWS = require('aws-sdk');
const db = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
function getExamSchedule(exam2, table){
return new Promise(function(resolve){
var info = 0;
var params = {
TableName: table,
FilterExpression: "#key = :data",
ExpressionAttributeNames: {
"#key": "Resource",
},
ExpressionAttributeValues:{
":data": exam2
}
};
db.scan(params, function(err, data){
if(err){
console.log("Error: " + err);
info = 0;
} else {
console.log("Success", data);
info = {"ClassID" :data.Items[0].ClassID, "ExamDate " :data.Items[0].ExamDate,
"ExamEndTime:" :data.Items[0].ExamEndTime, "ExamLocation" :data.Items[0].ExamLocation,
"ExamStartTime" :data.Items[0].ExamStartTime};
}
resolve(info);
});
});
}
This is the portion where the issue might be occurring.
exports.handler = async (event, context, callback) => {
var exam2 = event.currentIntent.slots.ClassID;
var info = await getExamSchedule(exam2, "Final_Exams");
var res;
// if (info !== 0)
if(info != null){
res =`The exam information for ${exam2} is ${info.ClassID} Date: ${info.ExamDate}
End time: ${info.ExamEndTime} Location: ${info.ExamLocation} Start time: ${info.ExamStartTime}`;
} else {
res = `The exam is not entered into our database, please look for another exam.`;
}
callback(null, {
"dialogAction": {
"type":"Close",
"fulfillmentState": "Fulfilled",
"message":{
"contentType": "PlainText",
"content": res
}
}
});
};
Could you perhaps share some of the logs and/or stack traces that you encounter when running the code?

Failed use apigwManagementApi.postToConnection in $connect route

I want to return connectionId to a client after the client connect to aws websocket.
I'm using apigwManagementApi.postToConnection to send a response to a client, but I always get an absurd error message.
I already try to debug & search in google, but I can't find a solution for this.
patch.js
require('aws-sdk/lib/node_loader');
var AWS = require('aws-sdk/lib/core');
var Service = AWS.Service;
var apiLoader = AWS.apiLoader;
apiLoader.services['apigatewaymanagementapi'] = {};
AWS.ApiGatewayManagementApi = Service.defineService('apigatewaymanagementapi', ['2018-11-29']);
Object.defineProperty(apiLoader.services['apigatewaymanagementapi'], '2018-11-29', {
get: function get() {
var model = {
"metadata": {
"apiVersion": "2018-11-29",
"endpointPrefix": "execute-api",
"signingName": "execute-api",
"serviceFullName": "AmazonApiGatewayManagementApi",
"serviceId": "ApiGatewayManagementApi",
"protocol": "rest-json",
"jsonVersion": "1.1",
"uid": "apigatewaymanagementapi-2018-11-29",
"signatureVersion": "v4"
},
"operations": {
"PostToConnection": {
"http": {
"requestUri": "/#connections/{connectionId}",
"responseCode": 200
},
"input": {
"type": "structure",
"members": {
"Data": {
"type": "blob"
},
"ConnectionId": {
"location": "uri",
"locationName": "connectionId"
}
},
"required": [
"ConnectionId",
"Data"
],
"payload": "Data"
}
}
},
"shapes": {}
}
model.paginators = {
"pagination": {}
}
return model;
},
enumerable: true,
configurable: true
});
module.exports = AWS.ApiGatewayManagementApi;
index.js
const AWS = require('aws-sdk');
require('./patch.js');
exports.handler = async(event) => {
const connectionId = event.requestContext.connectionId;
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: event.requestContext.domainName + '/' + event.requestContext.stage
});
await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: connectionId }).promise();
return {};
};
client.js
const WebSocket = require('ws');
const ws = new WebSocket('wss://****');
ws.on('open', () => {
console.log('connected ===================>')
ws.on('message', data => console.warn(`From server: ${data}`));
});
Error in cloudwatch
{
"errorMessage": "410",
"errorType": "UnknownError",
"stackTrace": [
"Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)",
"Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:52:8)",
"Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)",
"Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)",
"AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)",
"/var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)"
]
}
I don't know why, but if I'm trying in a custom route, this code can work.
Does anyone know how to solve this?
I'd suggest to look into this example from AWS, there is on connect response for subprotocol confirmation, but I think any payload can be provided.
The most important bit is the route integration settings in the template, basically, the following two lines in the route integration properties:
IntegrationMethod: POST
ConnectionType: INTERNET
then response will be sent to the connected client.
The only way I've found to make this work is to use a DynamoDB table to store connections, then set up a trigger from the table back to a Lambda function.
There are a few catches though. This Lambda function wont work like your index.js file above. You'll have to use NPM install --save aws-sdk on a folder with your index.js file, zip it and upload it to the lambda function, so that the SDK is localized.
You will also need to set up a user with proper access and put the credentials into a your Lambda function.
Note, if you see a 410 error, that means the connection is no longer there, so you're going in the right direction at that point.
const AWS = require('aws-sdk');
require('./patch.js');
var log = console.log;
AWS.config.update({
accessKeyId: "YOURDATAHERE",
secretAccessKey: "YOURDATAHERE"
});
let send = undefined;
function init() {
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: "HARDCODEYOURENDPOINTHERE"
});
send = async (connectionId, data) => {
await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: `${data}` }).promise();
}
}
exports.handler = async (event, context) => {
init();
console.log('Received event:', JSON.stringify(event, null, 2));
for (const record of event.Records) {
//console.log(record.eventID);
console.log(record.eventName);
console.log('DynamoDB Record: %j', record.dynamodb);
if(record.eventName == "INSERT"){
var connectionId = record.dynamodb.NewImage.connectionId.S;
try{
await send(connectionId, connectionId);
}catch(err){
log("Error", err);
}
log("sent");
}
}
return `Successfully processed ${event.Records.length} records.`;
};

AWS Dynamo DB Query

Hi I am trying to query Dynamo DB using lambda below is the code.
exports.handler = function index(event, context, callback) {
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-1"
});
var docClient = new AWS.DynamoDB.DocumentClient();
console.log("Querying ");
var params = {
TableName : "BankApp",
KeyConditionExpression: "#yr = :Value",
ExpressionAttributeValues: {
"#yr": "Test"
},
ExpressionAttributeNames : {
":Value" : {"S" : "TEST" }
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.Account_NUM + ": " + item.ACCOUNT_BAL);
});
}
});
}
But i am getting Error Saying :
Unable to query. Error: {
"message": "ExpressionAttributeNames contains invalid key: Syntax error; key: \":Value\"",
"code": "ValidationException",
"time": "2018-07-17T15:20:40.308Z",
It was my mistake, I was using wrong region.

MissingRequiredParameter: Missing required key 'Message' in params

I'm trying to invoke a code in AWS Lambda. This Lambda code has been configured with my IOT button. On running this code, I don't see any errors. Also,I don't really see the required push notification on my mobile device.
I can see this message in my console : MissingRequiredParameter: Missing required key 'Message' in params
This is my code:
'use strict';
console.log('Loading function');
var AWS = require('aws-sdk');
var sns = new AWS.SNS();
AWS.config.region = 'xxxxx';
const TopicArn = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
exports.handler = function(event, context) {
console.log("\n\nLoading handler\n\n");
console.log('Received event:', event);
const sin =
{
"default": "Start",
"APNS_SANDBOX":"{\"aps\":{\"alert\":\"Start\"}}",
"GCM": "{ \"notification\": { \"text\": \"Start\" } }"
} // for single click
const doub = {
"default": "Stop",
"APNS_SANDBOX":"{\"aps\":{\"alert\":\"Stop\"}}",
"GCM": "{ \"notification\": { \"text\": \"Stop\" } }"
} // for double click
const lon = {
"default": "SOS",
"APNS_SANDBOX":"{\"aps\":{\"alert\":\"SOS\"}}",
"GCM": "{ \"notification\": { \"text\": \"SOS\" } }"
} // for long click
var singleClick = sin[Math.floor(Math.random()*sin.length)];
var doubleClick = doub[Math.floor(Math.random()*doub.length)];
var longClick = lon[Math.floor(Math.random()*lon.length)];
var randomMessage = singleClick;
if(event.clickType == "DOUBLE")
{
randomMessage = doubleClick;
}
if(event.clickType == "LONG")
{
randomMessage = longClick;
}
sns.publish ({
Message: randomMessage,
TopicArn: TopicArn
},
function(err, data) {
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
context.done(null, 'Function Finished!');
});
}
Can someone help me debug this error?
I found the answer. I had to define my variable too as a string using stringify() command or else JSON formatted message cannot be sent.

Parse Server - Missing Push Configuration?

I've been trying to get push notifications to work with my Parse application. I tried to do so my adding the below code into my Parse server.js file but my server does not start up again when this code is contained inside of the file. I have my p12 file available and linked in the code below (on my actual sever) as well so Im not sure what the issue is.
push: {
android: {
senderId: '...',
apiKey: '...'
},
ios: {
pfx: '/file/path/to/XXX.p12',
passphrase: '', // optional password to your p12/PFX
bundleId: '',
production: false
}
}
My server is running on an Amazon EC2 instance as well.
Are you using AWS SNS to use push notification? If so, you can try setting this in your server code:
function sendPhoneNotification() {
AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: '***',
secretAccessKey: '***',
region: 'ap-southeast-1'
});
var sns = new AWS.SNS();
var promise = new Parse.Promise();
sns.createPlatformEndpoint({
PlatformApplicationArn: '***',
Token: "***"
}, function (err, data) {
if (err) {
console.log("Error in endpoint" + err.stack);
//res.error("error stack 1: " + err.stack);
promise.reject(err.stack);
return promise;
}
var endpointArn = data.EndpointArn;
var payload = {
GCM: {
data: {
title: "YOUR TITLE",
message: "HELLO PUSH NOTIFICATION"
}
}
/* APNS: {
aps: {
alert: 'Hello World',
sound: 'default',
badge: 1
}
}*/
};
// payload.APNS = JSON.stringify(payload.APNS);
payload.GCM = JSON.stringify(payload.GCM);
payload = JSON.stringify(payload);
var result = sns.publish({
Message: payload,
MessageStructure: 'json',
TargetArn: endpointArn
}, function (err, data) {
if (err) {
promise.reject(err.stack);
return promise;
}
res.success("push sent " + JSON.stringify(data));
});
});
return promise;
}