We have been trying to create users in our Cognito User Pool but keep getting a rather weird error. The stack trace looks as follows:
{
"errorMessage": "Not Found",
"errorType": "UnknownError",
"stackTrace": [
"Request.extractError (/var/task/node_modules/aws-sdk/lib/protocol/json.js:48:27)",
"Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:105:20)",
"Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)",
"Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)",
"Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)",
"AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)",
"/var/task/node_modules/aws-sdk/lib/state_machine.js:26:10",
"Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)",
"Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)",
"Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:115:18)"
]
}
Here's our code which is executed in Lambda. The Lambda function itself is invoked by API Gateway without proxy integration.
const AWS = require('aws-sdk');
AWS.config.update({
region: "ap-south-1",
endpoint: "https://dynamodb.ap-south-1.amazonaws.com",
});
const docClient = new AWS.DynamoDB.DocumentClient();
const cispClient = new AWS.CognitoIdentityServiceProvider({
region: 'us-east-1'
});
const table = process.env.TABLE_NAME || "User_Info_Test";
exports.newDriverCreated = function (event, context) {
console.log('event: ', event);
// Get username, password
const username = event.username;
const password = event.password;
// Get first and last name
const firstName = event.name;
const lastName = event.family_name;
// Get phone number
const phone = event.phone;
const driverData = {
"TemporaryPassword": password,
"UserAttributes": [
{
"Name": "phone_number",
"Value": phone,
},
{
"Name": "first_name",
"Value": firstName,
},
{
"Name": "family_name",
"Value": lastName,
},
],
"Username": username,
"UserPoolId": 'user-pool-id',
"ValidationData": [
{
"Name": "phone_number",
"Value": phone
}
]
}
cispClient.adminCreateUser(driverData, (err, data) => {
if (err) {
console.error('adminCreateUser error: ', err);
context.done(err);
} else {
console.log('adminCreateUser data: ', data);
context.done(null, data);
}
});
}
The error occurs when we call the adminCreateUser() function. We have absolutely no clue what could be going wrong as we are really new to AWS as a whole.
Any help would be greatly appreciated.
Thanks.
Try mentioning the endpoint when creating the cispClient. It looks like it could be a problem due to an incorrect endpoint. See this and enter link description here. Look here for a list of endpoints.
Related
How do I use the Google Oauth in featherjs with an existing access token? The docs do not give an example on this. The only example is through the browser as shown here.
When going through the browser, http://localhost:3030/oauth/google works ok. I can successfully add the user to my DB. Here is my code:
const { LocalStrategy } = require("#feathersjs/authentication-local");
const { expressOauth } = require("#feathersjs/authentication-oauth");
const { OAuthStrategy } = require("#feathersjs/authentication-oauth");
var uniqid = require("uniqid");
const { AuthenticationService, JWTStrategy } = require('#feathersjs/authentication');
class GoogleStrategy extends OAuthStrategy {
async getEntityData(profile) {
const baseData = await super.getEntityData(profile);
console.log({ profile });
return {
...baseData,
profilePicture: profile.picture,
email: profile.email,
password: uniqid.time(),
};
}
}
module.exports = (app) => {
const authentication = new AuthenticationService(app);
authentication.register("local", new LocalStrategy());
authentication.register('jwt', new JWTStrategy());
authentication.register("google", new GoogleStrategy());
app.use("/authentication", authentication);
app.configure(expressOauth());
};
However if I try using an access token,like so
POST http://localhost:3030/authentication
data: {
"strategy": "google",
"accessToken": "ya29.A0ARrdaM_UJa6idfZr-4taqwkJ6qGBV1Dp9wbxF-wsult8dNPaVNCVg6Fndmrqv7BhRSwxa5gAKllPvbKtsjyxS39WdmWmqkmE42HOsVZaJWHVEttxbebel3zdpD5BSxWtRiG7NuZLNVedMUaK5AdgIRrJk1u"
}
I do not get the google profile, no user is added to my DB and I get this error:
{
"name": "GeneralError",
"message": "401 Unauthorized",
"code": 500,
"className": "general-error",
"data": {},
"errors": {}
}
I have added "google" to my list of authStrategies in default.json
So my question is what do I need to do?
So I found the solution. Thought I might share. Add this to authentication.js
//add this method
async getProfile(authResult) {
const accessToken = authResult.accessToken;
const { data } = await axios
.get(
`https://openidconnect.googleapis.com/v1/userinfo?access_token=${accessToken}`
)
.then((res) => {
return res;
})
.catch((error) => console.log("autherr", error));
return data;
}
i am working on Amazon lex. when i give input to amazon lex its gives me following error
i add lambda function in Fulfillment and from lambda i am getting customer information from MySQL Database
here is my lambda function
const mysql = require('mysql');
var pool = mysql.createPool({ // a connection pool is a cache of database connections maintained so that the connections can be reused when future requests to the database are required
host: process.env.RDS_HOSTNAME,
user: process.env.RDS_USERNAME,
password: process.env.RDS_PASSWORD,
port: process.env.RDS_PORT,
database: process.env.RDS_DATABASE
});
exports.handler = (event, context, callback) => {
let MembershipNumber = event.currentIntent.slots.MembershipNumber;
// allows for using callbacks as finish/error-handlers
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
if (err) throw err;
let sql = "select * from Sales.CustomerTable where MembershipNumber= ? LIMIT 1";
let field = [MembershipNumber];
connection.query(sql,field, function (err, result, fields) {
if (err) {
console.log(err); // an error occurred
context.fail(buildResponse(false));
}
else {
if (result.length === 1) {
//console.log(data.Items[0].Arrival_city);
var FirstName = result[0].FirstName;
var LastName = result[0].LastName;
var Address = result[0].Address;
var PrimaryPhone = result[0].PrimaryPhone;
var SecondaryPhone = result[0].SecondaryPhone;
var Email = result[0].Email;
var Type = result[0].Type;
var MembershipNumber = result[0].MembershipNumber;
var Pin = result[0].Pin;
callback(null, {
"dialogAction": {
"type": "ConfirmIntent",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": FirstName,LastName,Address,PrimaryPhone,SecondaryPhone,Email,Type,MembershipNumber,Pin
}
}
});
}
else {
console.log("Membership Number not found");
callback(null, buildResponse(true, "none"));
}
}
});
});
};
function buildResponse(isSuccess, FirstName, LastName, Address, PrimaryPhone, SecondaryPhone, Email, Type, MembershipNumber, Pin) {
if (isSuccess) {
return {
FirstName: FirstName,
LastName: LastName,
Address: Address,
PrimaryPhone: PrimaryPhone,
SecondaryPhone: SecondaryPhone,
Email:Email,
Type:Type,
MembershipNumber:MembershipNumber,
Pin:Pin,
lambdaResult: "success"
};
}
else {
console.log("Lambda returned error to Connect");
return { lambdaResult: "Error" };
}
}
here is the test event object
{
"messageVersion": "1.0",
"invocationSource": "FulfillmentCodeHook",
"userId": "user-1",
"sessionAttributes": {},
"bot": {
"name": "Sales",
"alias": "sales",
"version": "$LATEST"
},
"outputDialogMode": "Text",
"currentIntent": {
"name": "iamamember",
"slots": {
"MembershipNumber": "78541258"
},
"confirmationStatus": "None"
}
}
i want to integrate this with my contact flow. i don't what is this error about. If anyone of you know help me. Thanks
From the error message, the response JSON from lambda is not matching with what Lex expects. As per the error message, it appears that this line has the problem:
"content": FirstName,LastName,Address,PrimaryPhone,SecondaryPhone,Email,Type,MembershipNumber,Pin
The value of content needs to be a string. However, from your screenshot, this is getting resolved as "content": "alys", "Lastname",...
I believe what you want to do is a concatenation of FirstName, LastName and all the other things you want to return in the content. Use a correct function that will do concatenation of these fields and then put them as comma-separated.
Reference: https://docs.aws.amazon.com/lex/latest/dg/lambda-input-response-format.html
I am writing a O365 Send Mail API using Node. My Node act as a server, Angular and Xamarin act as client(Web and Mobile). I have gone through the documentation. According to that I have included Microsoft SDK and registered my app in Microsoft Azure to get Client ID. Then here comes the mail API code.
Code
const options = {
authProvider,
};
const client = Client.init(options);
const sendMail = {
message: {
subject: "Meet for lunch?",
body: {
contentType: "Text",
content: "The new cafeteria is open."
},
toRecipients: [
{
emailAddress: {
address: "fannyd#contoso.onmicrosoft.com"
}
}
],
ccRecipients: [
{
emailAddress: {
address: "danas#contoso.onmicrosoft.com"
}
}
]
},
saveToSentItems: "false"
};
let res = await client.api('/me/sendMail')
.post(sendMail);
To Create authProvider, I have to scenarios here
Web App that calls web APIs
Mobile app that calls web APIs
I have no idea how to create authProvider. The documentation is confusing. Can someone help me out
You need to put that code in your backend (node.js). Just make a dynamic helper function for sending a mail like this
utils.js
const options = {
authProvider,
};
const client = Client.init(options);
const utils = {};
utils.sendMail = async (to, subject, body, cc, isSave) => {
const mailOptions = {
message: {
subject: subject || '',
body: { ...body },
toRecipients: to,
},
saveToSentItems: `${isSave}`,
};
if (cc) {
mailOptions.message.ccRecipients = cc;
}
const result = await client.api('/me/sendMail').post(mailOptions);
return result;
};
module.exports = utils;
And calling that function like this
const test = async () => {
try {
const to = [
{
emailAddress: {
address: 'fannyd#contoso.onmicrosoft.com',
},
},
];
const cc = [
{
emailAddress: {
address: 'danas#contoso.onmicrosoft.com',
},
},
];
const subject = 'Test';
const body = {
contentType: 'Text',
content: 'The new cafeteria is open.',
};
const saveToSentItems = true;
const result = await utils.sendMail(to, subject, body, cc, saveToSentItems);
return result;
} catch (err) {
console.log(err);
throw err;
}
};
test();
I suggest you put your logic in the backend When you have multiple clients such as android, iOs, PWA then you need to rewrite your code in all 3 platforms, If you put your common business logic to the backend then a single code can serve to all 3 platforms.
I'm using graphql-yoga server, Express, Node.js, Prisma client and Prisma server. And trying to do a post mutation to a GraphQL server using the GraphQL playground. However, I'm getting a persistent error "invalid token" which seems to span from my getUSerId helper function that's called on most Mutation field resolver functions.
Here is a code snippet of the error
{
"data": null,
"errors": [
{
"message": "invalid token",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"post"
]
}
]
}
Here is the code to my resolver function in utils.js
const jwt = require("jsonwebtoken");
const APP_SECRET = "GraphQL-is-aw3some";
function getUserId(context) {
const Authorization = context.request.get("Authorization");
if (Authorization) {
const token = Authorization.replace("Bearer", "");
const { userId } = jwt.verify(token, APP_SECRET);
return userId;
}
throw new Error("Not Authenticated");
}
module.exports = {
APP_SECRET,
getUserId
};
Here is code for my post resolver function
function post(parent, args, context, info) {
const userId = getUserId(context);
return context.prisma.createLink({
url: args.url,
description: args.description,
postedBy: { connect: { id: userId } }
});
}
Here is my mutation in the playground
mutation{
post(
description: "Prisma repalces traditional ORMs"
url: "www.prisma.io"
){
id
}
}
I'm using firebase admin SDK on cloud functions to create users using
admin.auth().createUser({
email: someEmail,
password: somePassword,
})
now I want user to signIn using signInWithEmailAndPassword('someEmail', 'somePassword') but I cannot.
I get the following error
{code: "auth/user-not-found", message: "There is no user record corresponding to this identifier. The user may have been deleted."}
There doesn't seem to be a reason to Stringify/Parse. This worked after I struggled with an unrelated typo...
FUNCTION CALL FROM REACT JS BUTTON CLICK
<Button onClick={() => {
var data = {
"email": "name#example.com",
"emailVerified": true,
"phoneNumber": "+15551212",
"password": "randomPW",
"displayName": "User Name",
"disabled": false,
"sponsor": "Extra Payload #1 (optional)",
"study": "Extra Payload #2 (optional)"
};
var createUser = firebase.functions().httpsCallable('createUser');
createUser( data ).then(function (result) {
// Read result of the Cloud Function.
console.log(result.data)
});
}}>Create User</Button>
And in the index.js in your /functions subdirectory:
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();
// CREATE NEW USER IN FIREBASE BY FUNCTION
exports.createUser = functions.https.onCall(async (data, context) => {
try {
const user = await admin.auth().createUser({
email: data.email,
emailVerified: true,
password: data.password,
displayName: data.displayName,
disabled: false,
});
return {
response: user
};
} catch (error) {
throw new functions.https.HttpsError('failed to create a user');
}
});
Screen shot of console output
In 2022 there still is no method built into the Admin SDK that would allow to create users in the emulator.
What you can do is to use the REST API of the emulator to create users there directly. The API is documented here: https://firebase.google.com/docs/reference/rest/auth#section-create-email-password
Provided you have got and nanoid installed you can use the following code to create users in the emulator.
import { nanoid } from 'nanoid'
import httpClientFor from '../lib/http-client/client.js'
const httpClient = httpClientFor('POST')
export const createTestUser = async ({ email = `test-${nanoid(5)}#example.io`, password = nanoid(10), displayName = 'Tony' } = {}) => {
const key = nanoid(31)
const { body: responseBody } = await httpClient(`http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp?key=${key}`, {
json: {
email,
password,
displayName
}
})
const responseObject = JSON.parse(responseBody)
const { localId: userId, email: userEmail, idToken, refreshToken } = responseObject
return { userId, userEmail, idToken, refreshToken }
}
Please note: As there is no error handling implemented, this snippet is not suitable for production use.
Try like that
And please be ensure that user is created from the panel
admin.auth().createUser({
email: "user#example.com",
emailVerified: false,
phoneNumber: "+11234567890",
password: "secretPassword",
displayName: "John Doe",
photoURL: "http://www.example.com/12345678/photo.png",
disabled: false
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
})
.catch(function(error) {
console.log("Error creating new user:", error);
});
Just in case anyone else comes across this I was able to fix it with the help of this.
Here is a working example inside of an onCreate cloud function:
exports.newProjectLead = functions.firestore
.document('newProjectForms/{docId}')
.onCreate(async (snapshot) => {
const docId = snapshot.id
// this is what fixed it the issue
// stringify the data
const data = JSON.stringify(snapshot.data())
// then parse it back to JSON
const obj = JSON.parse(data)
console.log(obj)
const email = obj.contactEmail
console.log(email)
const password = 'ChangeMe123'
const response = await admin.auth().createUser({
email,
password
})
data
const uid = response.uid
const dbRef = admin.firestore().collection(`clients`)
await dbRef.doc(docId).set({
id: docId,
...data,
uid
}, {
merge: true
})
console.log('New Client Created')
})