Firebase admin - Create Custom token: There is no user record corresponding to the provided identifier - firebase-admin

I'm using firebase admin becasue I want to validate my users in a different server. I have the following code but I'm getting the error
{ code: 'auth/user-not-found',
message: 'There is no user record corresponding to the provided identifier.' } }
Docs
https://firebase.google.com/docs/auth/admin/create-custom-tokens
var uid = user_dict['uid'];
admin.auth().createCustomToken(uid)
.then(function (customToken) {
admin.auth().updateUser(uid, {
//email: user_dict['email'],
emailVerified: true,
displayName: user_dict['displayName'],
photoURL: user_dict['photoURL']
})
.then(function(userRecord) {
response = {
token:customToken
};
res.send(response);
})
.catch(function(error) {
console.log("Error updating user:", error);
res.statusCode = 401;
res.send("Error al actualizar usuario")
});
})
.catch(function (error) {
console.log("Error creating custom token:", error);
res.statusCode = 401;
res.send("El usuario no existe")
});
The wierd part this code is working for 1 user, but not for the rest. Why?
UPDATE
I change my code to this:
var uid = user_dict['uid'];
admin.auth().createCustomToken(uid)
.then(function (customToken) {
admin.auth().getUser(uid)
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully fetched user data:", userRecord.toJSON());
admin.auth().updateUser(uid, {
email: user_dict['email'],
emailVerified: true,
displayName: user_dict['displayName'],
photoURL: user_dict['photoURL']
})
.then(function(userRecord) {
response = {
token:customToken
};
res.send(response);
})
.catch(function(error) {
console.log("Error updating user:", error);
res.statusCode = 401;
res.send("Error al actualizar usuario")
});
})
.catch(function(error) {
console.log("Error fetching user data:", error);
admin.auth().createUser({
uid:uid,
email: user_dict['email'],
emailVerified: true,
displayName: user_dict['displayName'],
photoURL: user_dict['photoURL'],
password:req.body['password']
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
response = {
token:customToken
};
res.send(response);
})
.catch(function(error) {
console.log("Error creating new user:", error);
res.statusCode = 401;
res.send("Error al crear el usuario")
});
});
})
.catch(function (error) {
console.log("Error creating custom token:", error);
res.statusCode = 401;
res.send("El usuario no existe")
});
You can see in the following screenshot carlos#mail is created using the function createUser() and the other email ricardo#mail is not. They don't have the same provider why such a difference?

createCustomToken() accepts arbitrary user ID strings. But updateUser() does not. The UID passed to updateUser() must already exist in the Firebase project. You need to call createUser() to first create those user accounts in Firebase.

Related

DynamoDB.putitem not adding paramaters to DynamoDB table?

My lambda function uses the method
ddb.putItem(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log("SUBMITTED DATA"); // successful response
});
with my params being correctly formatted to my table. No error is shown in my logs, however "SUBMITTED DATA" does not appear in the logs either, and the data is not put into my DynamoDB table. Any idea on what might be causing this problem? Heres my complete function:
const TrackHabitIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'TrackHabitIntent';
},
handle(handlerInput) {
ddb.putItem(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log("SUBMITTED DATA"); // successful response
});
const speechText = "That's awesome! I'll add today to your streak of 4 days";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
}};
exports.handler = function (event, context) {
if (!skill) {
skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
HelpIntentHandler,
HelpMeIntentHandler,
TrackHabitIntentHandler,
NewHabitIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.create();
}
return response;
};
Thanks
Please check this code to add data in dynamoDB that can help you.
let putParams = {
TableName: tableName,
Item: {
'Id': {
S: Id
},
'name': {
S: name
}
},
ConditionExpression: 'attribute_exists(Id)'
};
dynamoDb.putItem(putParams, function (err, data) {
if (err) {
console.log('failure:put data from Dynamo error', err);
reject(err);
} else {
console.log('success:put data from Dynamo data');
resolve(data);
}
});

Google recaptcha v3 always returning error

Following the instructions I get a valid token from my front end (can see in dev tools):
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// this is what I POST to my API
So in my React front end:
send = (event) => {
event.preventDefault()
this.setState({ busy: true })
window.grecaptcha.ready(() => {
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// successfully get token
const payload = {
token,
name: this.state.name,
to: this.props.to,
email: this.state.email,
message: this.state.message,
}
// now I'm sending the payload to my API
// My API
update(`${api}/contact/`, {
method: 'POST',
body: JSON.stringify(payload)
}, null)
.then(data => {
this.setState({ busy: false, result: 'Email sent' });
})
.catch(error => {
this.setState({ busy: false, error: error.message });
});
})
})
}
my API controller
async function verifyCaptcha(token) {
return await axios.post('https://www.google.com/recaptcha/api/siteverify', {
secret: process.env.CAPTCHA_PKEY,
response: token
})
}
async function contact({ token, to, name, email, message }) {
const result = await verifyCaptcha(token)
if (!result || !result.data || !result.data.success) {
// always get an error here
throw new Error('Invalid captcha')
}
let targetEmail = 'default#emailaddress'
if (to !== 'admin') {
const user = await User.findOne({ username: to }, { email }).exec()
if (!user) {
throw new Error('User does not exist')
}
targetEmail = user.email
}
// rest of send
}
On my API POST endpoint sends to https://www.google.com/recaptcha/api/siteverify with the body of:
{
secret: process.env.CAPTCHA_PKEY,
response: token
}
Yet I always get "missing-input-response", "missing-input-secret" error. Is this because v3 is new? Still bugs?
Realised in the documentation it states "post params" not post body haha.

Sails.JS Socket in Overridden Actions of the Controller

I've overridden an action in the controller that was generated from a blueprint API in Sails.JS.
I used the create action. Now I can't get a Sails.JS socket event from that action anymore, however, other actions are working fine.
io.socket.on('posts', function gotHelloMessage(data) {
console.log('Post!', data);
});
io.socket.get('/posts', function gotResponse(body, response) {
console.log('Posts: ', body);
})
What's the way to implement so that the create action also generates the event with my newly implemented actions?
create: function(req, res) {
if (
!_.has(req.body, "title") ||
!_.has(req.body, "body") ||
!_.has(req.body, "category")
) {
return res.serverError("No field should be empty.");
}
var uploadPath = "../../assets/posts";
return req
.file("thumbnail")
.upload({ dirname: uploadPath }, async function(err, uploadedFiles) {
if (err) return res.serverError(err);
let post;
try {
post = await Posts.create({
title: req.body.title,
body: req.body.body,
category: req.body.category,
thumbnail:
uploadedFiles.length === 0
? ""
: uploadedFiles[0].fd.split("/").reverse()[0]
}).fetch();
return res.json({ result: post });
} catch (err) {
return res.json({ error: err });
}
});
}

Image is not defined (Firebase storage - React Native)

The problem:
I am able to successfully upload an image to firebase storage, but when I try to sign-out, then sign-in again, I am stucked on the log-in page. and after few minutes this error appears
This is my code on fetching the image and log-in
if (currentUser != null) {
uid = currentUser.uid;
const db = firebase.firestore();
const docRef = db.collection("users").doc(uid);
console.log("uid")
console.log(uid)
console.log("currentUser")
console.log(currentUser)
console.log("docRef")
console.log(docRef)
docRef.get().then((doc) => {
console.log("doc");
console.log(doc);
if (doc.exists) {
console.log("Document data:", doc.data());
const userData = doc.data();
const imageRef = firebase.storage().ref(`/userProfilePictures/${uid}`).child('profile.jpg');
imageRef.getDownloadURL().then(function(url) {
dispatch({ type: GET_PROFILE_PICTURE, payload: url })
dispatch({ type: GET_USER_DATA, payload: userData});
Actions.home();
}).catch((error) => {
dispatch({type: GET_PROFILE_PICTURE, payload: ''})
console.log(error);
})
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}else {
console.log('something went wrong');
}
})
.catch((error) => {
loginUserFail(dispatch)
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorMessage);
});
After loggin in again, it seems that the user is authenticated, but It can't execute this line docRef.get().then((doc) => { there is no error on the console.log.
And then if you try to reload again, then sign-in again you can see the newly uploaded image.

Alexa app working locally, returning early on Lambda

So I have multiple calls chained all working and posting the update to a google spreadsheet when I run locally, but when I try and run it on Lambda it just returns early without any errors.
skillService.intent("sampleIntent", {
...
},
function(request,response){
var name = request.slot("NAME");
var category = request.slot("CATEGORY");
var event = request.slot("EVENT");
// slot used for any parts of conversation
var stepValue = request.slot('STEPVALUE');
var sampleHelper = getHelper(request);
// If it hasn't started, see if the user gave some slots and start from that step
if(!sampleHelper.started){
sampleHelper.determineStep(name, category, event);
}
sampleHelper.started = true;
// Did they provide all the necessary info?
if(sampleHelper.completed()){
// Handles reading out the menu, etc
return sampleHelper.updateSheet(response);
}
);
and here's what updateSheet looks
SampleHelper.prototype.updateSheet = function(resp){
var name = this.observance[0].steps[0].value;
var category = this.observance[0].steps[1].value;
var event = this.observance[0].steps[2].value;
console.log("about to auth.");
return authorize(JSON.stringify(this.access_token))
.then(function(auth){
console.log("passed auth");
return getColumns(auth, name, category).then(function(){
console.log("get columns");
return updateSheet(auth,name,category,event).then(function(){
console.log("finished updating");
return resp.say("Successfully logged for " + name + " a " + category + " of " + event).send();
});
}).catch(function(err){
console.log("failed columns");
return resp.say(err).send();
});
})
.catch(function (err) {
console.log("Auth err: ", err);
return resp.say("There was an error authenticating. Please check your Alexa app for how to reconnect your google account.").send();
});
};
my local terminal ouput:
AWS output using the exact same JSON for the request:
My node versions are both 6.10 and I have both alexa-app-server/my app using alexa-app: "^4.0.0"
local response:
{
"version": "1.0",
"response": {
"directives": [],
"shouldEndSession": true,
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Successfully logged</speak>"
}
},
"sessionAttributes": {},
"dummy": "text"
}
Lambda's empty:
{
"version": "1.0",
"response": {
"directives": [],
"shouldEndSession": true
},
"sessionAttributes": {}
}
So with help of an awesome friend at PSU I figured it out.
I was actually returning my code and when Lambda sees that return it kills the function. When running on your local machine, it'll return, but not kill the process and therefore the rest of the code will still run.
To solve this, I wrapped everything in a promise and then returned that with a .then()
// Did they provide all the necessary info?
if(sampleHelper.completed()){
// Handles reading out the menu, etc
return sampleHelper.updateSheet(response).then(function(data){
return response.say("Successfully logged for " + sampleHelper.getName() + " a " + sampleHelper.getCategory() + " of " + sampleHelper.getEvent()).send();
}).catch(function(err){
console.log(err);
return response.say("error").send();
});
}
and the updateSheet:
return new Promise(function(resolve, reject) {
authorize(JSON.stringify(access_token))
.then(function (auth) {
console.log("passed auth");
getColumns(auth, name, category).then(function () {
console.log("get columns");
updateSheet(auth, name, category, event).then(function () {
console.log(new Date().getTime());
resolve("worked");
});
}).catch(function (err) {
console.log("failed columns");
throw "Failed columns";
// return resp.say(err).send();
});
})
.catch(function (err) {
throw err;
console.log("Auth err: ", err);
return resp.say("There was an error authenticating. Please check your Alexa app for how to reconnect your google account.").send();
});
});

Resources