securitymeteoraccounts

How to secure Accouts.createUser() with Collection2 (server-side)


I'm new to Meteor and I have a little question about Collection2 and Accounts.

Currently, a user can create an account. This is handled by a Template event (client-side) which calls a Meteor method. This method is defined client-side and server-side.

Client-side, I do some UI stuff (nothing important) while server-side I'm creating the account.

Here is my server-side Meteor method :

Meteor.methods({

    'registerUser': function (user) {
        Accounts.createUser(user);
    }

});

I also use Collection2 package to check data before inserting or updating document :

Schema = {};

Schema.UserProfile = new SimpleSchema({
    name: {
        type: String,
        optional: false,
        label: "Name"
    }
});

Schema.User = new SimpleSchema({
    username: {
        type: String,
        optional: true,
        label: "Username"
    },
    emails: {
        type: Array,
        optional: true
    },
    "emails.$": {
        type: Object
    },
    "emails.$.address": {
        type: String,
        regEx: SimpleSchema.RegEx.Email,
        label: "Email address"
    },
    "emails.$.verified": {
        type: Boolean
    },
    createdAt: {
        type: Date
    },
    profile: {
        type: Schema.UserProfile,
        optional: true
    },
    services: {
        type: Object,
        optional: true,
        blackbox: true
    }
});

Meteor.users.attachSchema(Schema.User);

Okay so here I am. My problem is about getting potential errors returned by Collection2 while creating the user (server-side). Something like this :

Meteor.methods({

    'registerUser': function (user) {
        Accounts.createUser(user, (err, res) => {
            if(err) return err;
        });
        return true;
    }

});

But Meteor does not support yet callback for Accounts.createUser(). So even if I use Collection2, my user can submit bad inputs.

The question is : Is it possible to use Collection2 with Accounts in this case and how ?

Thanks for everything ! :)


Solution

  • When you call Accounts.createUser you do not pass it an object with the schema as those found in the Meteor.users Collection. You pass an options object with the specified fields:

    Options
    username String
    A unique name for this user.

    email String
    The user's email address.

    password String
    The user's password. This is not sent in plain text over the wire.

    profile Object
    The user's profile, typically including the name field.

    Called from the client this method does have a callback:

    callback Function
    Client only, optional callback. Called with no arguments on success, or with a single Error argument on failure.

    Don't create a Schema for the User object.

    You could use your Schema.UserProfile to validate what is passed in the profile parameter though, and the best place to do this would be inside a accountsServer.validateNewUser callback on the server.

    Accounts.validateNewUser(function (user) {
      if(Match.test(user.profile, Schema.UserProfile))
        return true;
      throw new Meteor.Error(403, "Invalid UserProfile");
    });