AWS Cognito Identity JS: Forget/Remember/Do Not Remember Device - javascript

I'm working with the AWS Cognito Identity JS SDK (https://github.com/aws/amazon-cognito-identity-js) and I'm trying to set up a few buttons to test the setDeviceStatusRemembered, setDeviceStatusNotRemembered, and forgetDevice functionality but I keep getting an error saying:
MissingRequiredParameter: Missing required key 'DeviceKey' in params
Here is an implementation of one of the functions:
forgetDevice = function(){
var cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
cognitoUser.getSession(function(err, session) {
if (err) {
alert(err);
signOut();
return;
}
console.log('session validity: ' + session.isValid());
cognitoUser.forgetDevice({
onSuccess: function (result) {
console.log('call result: ' + result);
},
onFailure: function(err) {
alert(err);
}
});
});
}
}
If I change up the function like this:
forgetDevice = function(cognitoUser){
cognitoUser.forgetDevice({
onSuccess: function (result) {
console.log('call result: ' + result);
},
onFailure: function(err) {
alert(err);
}
});
}
and I call the function from the cognitoUser.authenticateUser success callback function, passing cognitoUser as argument into the forgetDevice function above everything works perfectly.
From looking at the session object in the first implementation it appears that the session object does not contain the DeviceKey property so the cognitoUser.forgetDevice() call fails.
What I'm trying to figure out is, should I just be calling the setDeviceStatusRemembered, setDeviceStatusNotRemembered, and forgetDevice functions on login, or should I be able to call them any time within my application? Hopefully that makes sense. Any help would be greatly appreciated. Thanks!

Does this help:
Note that if device tracking is enabled for the user pool with a setting that user opt-in is required, you need to implement an onSuccess(result, userConfirmationNecessary) callback, collect user input and call either setDeviceStatusRemembered to remember the device or setDeviceStatusNotRemembered to not remember the device.
http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-device-tracking.html
Also can you attempt calling getCachedDeviceKeyAndPassword to populate the deviceKey in the CognitoUser object?

Related

How to authenticate user with AWS Cognito in Vue.js using Javascript

I am facing the issue that I cannot fully undertsand how to call a function that uses a callback and get the results of the callback returned in a way where the data from the response becomes available to a Vue application.
async loginUser(username, password) {
AWS.config.update({region : region});
const payload = {
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: clientId,
AuthParameters : {
USERNAME: username,
PASSWORD: password
}
}
var cognito = new AWS.CognitoIdentityServiceProvider();
return cognito.initiateAuth(payload, function(err,data) {
if (err) {
alert("Error: " + err);
return null;
}
else {
tokenData = data["AuthenticationResult"];
console.log(tokenData);
return tokenData;
}
})
}
I want the tokenData to be what is returned when calling loginUser, but no matter what I try to do the data from the cognito.initiateAuth, that should be used in my application to validate a sign in, will just be null and not usable.
Hope you guys can help!
Thanks
I tried different solutions using promises, async/await, while loops trying to wait for the response to contain data, but nothing seems to work. I can see the data being printed correctly in the callback, but how do it get this data to pass on to the return of loginUser.

How to make sure AMQP message is not lost in case of error in subscriber with rhea?

So I have designed a basic Publisher-Subscriber model using rhea in JS that takes an API request for saving data in DB and then publishes it to a queue.
From there a subscriber(code added below) picks it up and tries to save it in a DB. Now my issue is that this DB instance goes through a lot of changes during development period and can result in errors during insert operations.
So now when the subscriber tries to push to this DB and it results in an error, the data is lost since it was dequeued. I'm a total novice in JS so is there a way to make sure that a message isn't dequeued unless we are sure that it is saved properly without having to publish it again on error?
The code for my subscriber:
const Receiver = require("rhea");
const config = {
PORT: 5672,
host: "localhost"
};
let receiveClient;
function connectReceiver() {
const receiverConnection = Receiver.connect(config);
const receiver = receiverConnection.open_receiver("send_message");
receiver.on("connection_open", function () {
console.log("Subscriber connected through AMQP");
});
receiver.on("error", function (err) {
console.log("Error with Subscriber:", err);
});
receiver.on("message", function (element) {
if (element.message.body === 'detach') {
element.receiver.detach();
}
else if (element.message.body === 'close') {
element.receiver.close();
}
else {
//save in DB
}
}
receiveClient = receiver;
return receiveClient;
}
You can use code like this to explicitly accept the message or release it back to the sender:
try {
save_in_db(event.message);
event.delivery.accept();
} catch {
event.delivery.release();
}
See the delivery docs for more info.

Promise either never get called, or is rejected (Parse JS SDK)

I am trying to write a function that add or edit some fields on a User object.
The problem come when I try to save the user, if I use user.save, the Promise is rejected with error 206 UserCannotBeAlteredWithoutSessionError.
However, if I get the session id (and documentation about that is scarce), the promise never get resolve, nor rejected. The app seems to just jump to the callback.
My function:
function update(user, callback) {
let query = new Parse.Query(Parse.User);
query.equalTo("username", user.email);
query.find().then(
(users) => {
if(users.length === 0) {
callback('Non existent user');
} else {
let user = users[0];
// user.set('some', 'thing');
console.log('save');
user.save(/*{
sessionToken: user.getSessionToken()
}*/).then(
(test) => {
console.log('OK - ' + test);
callback();
}, (err) => {
console.log('ERR- ' + require('util').inspect(err));
// console.log(callback.toString());
callback(error.message);
}
);
}
},
(error) => {
callback(error.message);
}
);
}
Called with:
var async = require('async'),
baas = require('./baas.js');
async.waterfall([
(callback) => {
callback(null, {
email: 'user#test.com',
password: 'password'
});
},
(user, callback) => {
console.log('connect');
baas.connect(() => { //Initialize the connection to Parse, and declare use of masterKey
callback(null, user);
});
},
(user, callback) => {
console.log('update');
baas.update(user, (err) => {
callback(err);
});
}
], (err) => {
console.log('Error: ' + err);
});
The logs become:
Without session token:
connect
update
save
ERR- ParseError { code: 206, message: 'cannot modify user sA20iPbC1i' }
With session token:
connect
update
save
I do not understand how it is possible that the promise just callback without printing anything, nor why no error are raised anywhere.
Edit:
Following #user866762 advice, I tried to replace the query with Parse.User.logIn and use the resulting User object.
While this solution give me a sessionToken, the end result is the same, parse crash if I don t provide the session token, or give me a error if I do.
According to the Parse Dev guide:
...you are not able to invoke any of the save or delete methods unless the Parse.User was obtained using an authenticated method, like logIn or signUp.
You might also try becoming the user before saving, but I have my doubts that will work.
When you're "get[ting] the session id" my guess is that you're really breaking something. Either Parse is having a heart attack at you asking for the session token, or when you're passing it in save you're causing something there to explode.

Parse.com Cloud code Error: success/error was not called when trying to update a user

ive never used cloud code/javascript and I am trying to write some parse cloud code to find a user using a objectId passed in to the cloud function, and then update that users relation that holds friends and finally save that user.
below is the function im using:
Parse.Cloud.define("addFriendToFriendsRelation", function(request, response) {
Parse.Cloud.useMasterKey();
var fromUserObjectId = request.params.fromUserObjectId;
var acceptingUser = request.params.user;
var query = new Parse.Query(Parse.User);
// find the user the request was from using the objectId
query.get(fromUserObjectId, {
success: function(user) {
var fromUser = user
var relation = fromUser.relation("friends");
relation.add(acceptingUser);
fromUser.save({
success: function() {
response.success("Successfully saved the users relation")
},
error: function() {
response.error("Save failed");
}
});
},
error: function() {
response.error("Save failed");
}
});
});
I managed to piece this together using the Parse docs. but Im really not following it to well. Never used javascript and am finding the syntax confusing.
then im calling the function with
//fromUser is a PFUser object defined further up
[PFCloud callFunctionInBackground:#"addFriendToFriendsRelation" withParameters:#{#"fromUserObjectId" : fromUser.objectId} block:^(id object, NSError *error) {
}
however whenever this function is called I get a success/error was not called error. Though im calling response.success and response.error in the function so I dont know why that is? Can anyone lend a hand?
edit: after doing some more searching it looks like response.success and response.error should only be called once each, so I modified my function to look like this:
arse.Cloud.define("addFriendToFriendsRelation", function(request, response) {
Parse.Cloud.useMasterKey();
var fromUserId = request.params.fromUserObjectId;
console.log("fromUserId:");
console.log(fromUserId);
var acceptingUser = request.params.user;
console.log("acceptingUser:")
console.log(acceptingUser);
var query = new Parse.Query(Parse.User);
query.get(fromUserId, {
success: function(user) {
console.log("found user:");
console.log(user);
var fromUser = user;
var relation = fromUser.relation("friends");
relation.add(acceptingUser);
console.log("added accepting user to relation");
fromUser.save({
success: function() {
response.success("successfully saved user")
},
error: function() {
response.error("error saving user");
}
});
console.log("found a user");
},
error: function() {
console.log("error finding user");
}
});
});
An old question, but since it's been up-voted, maybe answering can help someone else :).
First off, there is an error in how you are saving fromUser.
fromUser.save({ success: ...
If you look at the api you can see that it should be of the form:
fromUser.save(null, { success: ...
But the larger problem that kept you from finding your bug is that errors are getting eaten 'cause you are using the old style method of dealing with async code instead of using promises.
Below, I have re-written to use promises. Note:
I always return promise generating calls (there are other options for catching errors in async code, but start with this.)
Put a .catch at the end. The .catch is effectively the same things as .then(null, response.error) but either way, it is imperative that there is final backstop to catch errors. In your code above, the error was in a success block, that was running async, so when there was an error, it failed with no one to hear it :).
Parse.Cloud.define("addFriendToFriendsRelation", (request, response) => {
const fromUserId = request.params.fromUserObjectId;
console.log("fromUserId:", fromUserId);
const acceptingUser = request.user;
console.log("acceptingUser:", acceptingUser)
new Parse.Query(Parse.User);
.get(fromUserId, { useMasterKey: true })
.then((fromUser) => {
console.log("found fromUser:", fromUser);
const relation = fromUser.relation("friends");
relation.add(acceptingUser);
console.log("added accepting user to relation");
return fromUser.save(null, { useMasterKey: true })
})
.then(response.success)
.catch(response.error);
});

Why is my Meteor app logging to server but not client?

I'm building a meteor app that hooks into the twitter api and I've had no luck so far getting it to work. I'm using the twit package to make the call on the server side, and it logs the data to the server console, but when the client console goes to log it there is no data.
The client doesn't throw an error, it runs the console.log in the else statement for the result parameter, but it comes through as undefined. It's as if the result callback runs before the data comes back, but my understanding of the Meteor.call method is that it's supposed to wait until it hears back from the server before it runs.
What am I doing wrong here?
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to testing.";
};
Template.hello.recentFollows = function () {
return Session.get("recentFollows");
};
Template.hello.events({
'click #fetchButton': function () {
console.log("Recent tweets from stream!");
userName = "josiahgoff";
Meteor.call('getBananaTweets', function(err, result) {
if(err) {
console.log("error occurred on receiving data on server. ", err);
} else {
console.log("result: ", result);
Session.set("recentFollows", result);
}
});
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
Twit = new TwitMaker({
consumer_key: '******',
consumer_secret: '******',
access_token: '******',
access_token_secret: '******'
});
});
Meteor.methods({
getBananaTweets: function () {
Twit.get('search/tweets', { q: 'banana since:2011-11-11', count: 1 }, function(err, result) {
if (err) {
console.log("Error", err);
return err;
} else {
console.log(result);
return result;
}
});
}
});
}
You are using return in your server code in a place where it must not be used: in an asynchronous call-back. The Twit.get call returns immediately and the function ends (with no return value). So the client doesn't receive anything. Some time later the Twit.get comes back, but the return in that case goes nowhere.
This is a pretty common question. The solution is to wrap your Twit.get call into a fiber in some shape or form to make it synchronous. See for instance this answer: Iron Router Server Side Routing callback doesn't work

Categories

Resources