Firebase Admin SDK - Create user with custom fields - node.js

I've been following the Firebase SDK Admin - Manager User docs and everything went find for me with it's system. Either way, i want to extend my users information with fields such as first name, last name, nacionality, etc etc.
Right now i'm using Vue.JS (fronted), Axios (Http client) and Express.js (server) to manage my project and this is the way i create my users:
Vue.JS createUser method:
createUser() {
axios.post('http://localhost:3000/users',
{
username: this.username,
email: this.email,
firstName: this.firstName,
lastName: this.lastName,
password: this.password,
}).then(r => {
console.log(r)
}).catch(e => {
console.log(e)
})
// createUser
}
Each field: username, email, firstName, etc... got its value form a common HTML Form and they work just fine.
This is my "user create" route on the server side:
router.post('/', function (req, res, next) {
firebase.auth().createUser({
email: req.body.email,
username: req.body.username,
firstName: req.body.firstName,
lastName: req.body.lastName,
emailVerified: false,
password: req.body.password,
disabled: false
}).then(function(userRecord) {
console.log("Successfully created new user:", userRecord.uid);
}).catch(function(error) {
console.log("Error creating new user:", error);
});
});
And this is how i retrieve the users information:
router.get('/', function(req, res, next) {
firebase.auth().listUsers()
.then(function(listUsersResult) {
res.send(listUsersResult.users);
}).catch(function(error) {
console.log("Error listing users:", error);
})
});
The problem is that i can't get the custom fields i added (or they simply does not exists). Here's is a pictures of the data once i get it with the next method:
getItems() {
axios.get('http://localhost:3000/users').then(r => {
this.users = r.data
}).catch(e => {
console.log(e)
})
},
Is there a way to set custom fields on my user creation or (if my process is right) a way to retrieve them?

Firebase users are not customizable, unfortunately you can not add custom fields to the user... check out these docs for the properties of this object. Also check out this question & answer where Frank explains that you need to store any extra info separately... this is typically done in a table (named something like /userDetails) in your database.
FEBRUARY 2022 EDIT:
Since writing this answer, custom user claims are now a thing. It's meant for authentication / rules purposes and not data-storage, so most things should still be kept in the database as originally stated. Note that you CAN access the custom fields client-side.
Keep in mind, this is adding additional data to the ID token that gets sent with EVERY server request, so you should try to limit usage of this to role/permission based things and not, say, image data for a 2nd profile avatar. Read the best practices for custom claims on the official docs.

You can set a user's profile, immediately after creating.
firebase.auth().createUserWithEmailAndPassword(
email,
password,
).then(credential => {
if (credential) {
credential.user.updateProfile({
displayName: username
})
}
}

Related

Create users with email an phone provider using Admin Firebase

How can one create a user with phone number and email as providers in Firebase?
The code presented only sets up the phone number as being the only provider.
admin.auth().createUser({
uid: email,
email: email,
emailVerified: true,
phoneNumber: checkMobileTel(mobileTel)
})
.then(function(userRecord: { uid: any; }) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully created new user:', userRecord.uid);
})
.catch(function(error: any) {
console.log('Error creating new user:', error);
});
I think you are forgetting to add the password field. I hope I could help, happy coding!
password string The user's raw, unhashed password. Must be at least six characters long.

How to add data from instagram api to existing user record?

How do I associate data returned from instagram API with an existing user account--so that the instagram profile info can be stored in the same document as the user that made the request?
I'm using node.js, Mongoose with MongoDB, and node-instagram from npm to pull in basic user info from instagram. Users on this site will create an account and then later click a button to connect their account to instagram. I'm able to pull in instagram data and store it on my database but I'm not sure how to associate this data with the local (already existing) account that made the request?
app.get('/auth/instagram/feed', async (req, res) => {
try {
const data = await instagram.authorizeUser(req.query.code,
redirectUri);
const newUserInfo = new User({
username: data.user.username,
full_name: data.user.full_name,
access_token: data.access_token,
});
newUserInfo.save();
res.redirect("/");
} catch (err) {
res.json(err);
}
});
This successfully stores some basic instagram info on the database. Instead of saving a new record, how do I add this data to an existing user's record with email and password info?
I was able to get this to work by just creating a variable before the await line that gets the user id.
I've added my full code below as well as I neglected to include everything in my original post. Please note that the "/auth/instagram/feed" route is called by instagram (if you are confused about where that is coming from). You have to enter this into their URI redirect when signing up for a new API app.
const instagram = new instagramConnect({
clientId: process.env.INSTAGRAM_CLIENT_ID,
clientSecret: process.env.INSTAGRAM_CLIENT_SECRET
});
const redirectUri = 'http://localhost:3000/auth/instagram/feed';
app.get("/instagram-connect", function(req, res){
res.render("instagramConnect");
});
app.get('/auth/instagram', (req, res) => {
res.redirect(instagram.getAuthorizationUrl(redirectUri, { scope: ['basic'] }));
});
app.get('/auth/instagram/feed', async (req, res) => {
try {
const userID = req.user._id;
const data = await instagram.authorizeUser(req.query.code, redirectUri);
User.findOneAndUpdate({_id: userID}, {access_token: data.access_token}, function(err){
if(!err){
res.redirect("/ig-success");
}
});
} catch (err) {
res.json(err);
}
});

How can I add a user with KeystoneJS if I don't have any users?

Sorry if this is an incredibly basic question but I can not find any helpful information out there.
I used the yeoman keystone generator to create a keystone project but MongoDB wasn't working when I ran the generator so the user didn't get created. I can not find any information on how to add the user.
Here is what I tried:
I added this to the routes/views/index.js file so it would get executed when the page loads:
var user = new User({
name: { first:'matt', last:'x' },
email: 'me#m.com',
password: 'password',
isAdmin: true
});
user.save(function (err) {
if (err) {
// handle error
return console.log(err);
}
// user has been saved
console.log(user);
});
This added a user to the database, but I get this error when I try to login:
Sorry, an error occurred loading the page (500)
Must supply api_key
How do I resolve this?
Thanks for any help.
Use the built-in update functionality to add a new user. Add this code to an updates/0.0.2-admins.js file:
var keystone = require('keystone'),
User = keystone.list('User');
exports = module.exports = function(done) {
new User.model({
name: { first: 'Admin', last: 'User' },
password: 'admin',
isAdmin: true
}).save(done);
};
Can you post the full error regarding your API key, though?

Check for existing user using Mongoose

I'm trying to write a middleware function that (when a POST request is made with a username/password) checks to see if the user being created already exists in the database. I don't know if I'm doing this properly though.
User.find({ username: req.body.username }) returns an object which contains (or does not contain) the user if it exists...but how to properly return to exit if a user under the same username is found? Whenever I test this with Mocha, res.body.msg comes up as undefined.
Code:
module.exports = exports = function(req, res, next) {
User.find({ username: req.body.username }, (err, user) => {
if (err) return handleDBError(err, res);
if (user) return res.status(200).json({ msg: 'an account with this username already exists' });
});
next();
};
User Schema:
var userSchema = new mongoose.Schema({
username: String,
authentication: {
email: String,
password: String
}
});
give it a try very initial create a function to get the user response
function findUser(arg, callback) {
/* write your query here */
return callback(pass response here)
}
And then use it where you want
findUser(arg,function(callbackResponse) { /*do something*/ })
Since nodejs is asynchronous, chances are that the response is being sent after you are trying to read it. Make sure to keep the reading process waiting untill response is sent. I personaly use passport for handling that.

sails.js - unique model attribute check

Project:
API over websockets (socket.io)
My goal:
check if a username is unique before storing it
My solution:
Overwrite default createUser function
My problem:
calling User:create doesn't do the validation
code in the user controller:
create: function(req, res, next){
User.findByUsername(req.param('username')).then(function(usr){
if(usr !='')
{
// username already taken
return res.json({'type':'validationError','errorMessage':'Username already taken','usr':usr});
}
else{
// username is unique
User.create( req.params.all(),function userCreated(err,user){
// try to create user
if(err){
console.log(err);
return res.json({
'type':'validationError',
'errorMessage':err}
);
}
res.json(user);
});
}
},
function(err){
// error finding user by username
}
);
I believe approaching the problem in a slightly different way could potentially make this easier for you. You can handle the validation in the model:
attributes: {
username: {
type: 'string',
unique: true
}
}
Then, without overriding anything in the controller you should be able to attempt to create a user via websocket, and handle the error that is returned if you attempt to use a non-unique username.

Resources