How can we customize templates for the login flow?
For some apps, the off-the-shelf login templates provided by the various useraccounts UI packages will work as-is, but most apps will want to customize some of the presentation. There’s a simple way to do that using the template replacement functionality of the aldeed:template-extension package.
First, figure out which template you want to replace by looking at the source code of the package. For example, in the useraccounts:unstyled package, the templates are listed in this directory on GitHub. By squinting at the file names and looking for some of the HTML strings, we can figure out that we might be interested in replacing the atPwdFormBtn template. Let’s take a look at the original template:
<template name="atPwdFormBtn">
<button type="submit" class="at-btn submit {{submitDisabled}}" id="at-btn">
{{buttonText}}
</button>
</template>
Once you’ve identified which template you need to replace, define a new template. In this case, we want to modify the class on the button to work with the CSS for the rest of the app. There are a few things to keep in mind when overriding a template:
- Render the helpers in the same way the previous template did. In this case we are using buttonText.
- Keep any id attributes, like at-btn, since those are used for event handling.
Here’s what our new override template looks like:
<template name="override-atPwdFormBtn">
<button type="submit" class="btn-primary" id="at-btn">
{{buttonText}}
</button>
</template>
Then, use the replaces function on the template to override the existing template from useraccounts:
Template['override-atPwdFormBtn'].replaces('atPwdFormBtn');
How can we use the aldeed:template-extension package?
With the aldeed:template-extension package, the built-in templates or sub-templates of any user-accounts UI package may be replaced by custom templates. The purpose is to create more sophisticated or specialized layouts or styling. In case of input fields the option template (see Form Fields Configuration) can be directly used without the need to rely on aldeed:template-extension package.
Here is a simple example of a template you can use for a field of type 'select':
<template name="customSelectTemplate">
<select id="at-field-{{_id}}" name="at-field-{{_id}}" data-something="{{options.someOption}}">
{{#each select}}
<option value="{{value}}">{{text}}</option>
{{/each}}
</select>
</template>
Custom properties that hold information about the look of the form may be attached to the options object of a field. It may then be used to change the output while looping the fields. Adding a divider might look like this:
AccountsTemplates.addField({
_id: "address",
type: "text",
// Options object with custom properties for my layout. At the moment, there are
// no special properties; it is up the developer to invent them
options: {
// Put a divider before this field
dividerBefore: true
}
});
<template name="appAtInput">
{{#if options.dividerBefore}}<hr>{{/if}}
{{> Template.dynamic template=templateName}}
</template>
Template.appAtInput.replaces("atInput");
How can we configure login service providers?
First, add the service configuration package:
meteor add service-configuration
Then, in your app:
ServiceConfiguration.configurations.upsert(
{ service: "weibo" },
{
$set: {
clientId: "1292962797",
loginStyle: "popup",
secret: "75a730b58f5691de5522789070c319bc"
}
}
);
Login service configuration is sent from the server to the client over DDP when your app starts up; you may not call the login function until the configuration is loaded. The function Accounts.loginServicesConfigured() is a reactive data source that will return true once the login service is configured; you should not make login buttons visible or active until it is true.
Ensure that your $ROOT_URL matches the authorized domain and callback URL that you configure with the external service (for instance, if you are running Meteor behind a proxy server, $ROOT_URL should be the externally-accessible URL, not the URL inside your proxy).
What is the purpose of Accounts.ui.config(options)?
Configure the behavior of {{> loginButtons}}.
Accounts.ui.config({
requestPermissions: {
facebook: ['user_likes'],
github: ['user', 'repo']
},
requestOfflineToken: {
google: true
},
passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL'
});
This must be inside the isClient block. passwordSignupFields:
- USERNAME_AND_EMAIL: both username and email are mandatory
- USERNAME_AND_OPTIONAL_EMAIL: username is mandatory, email is optional
- USERNAME_ONLY: username is mandatory, email is not displayed
- EMAIL_ONLY: email address is mandatory and is used as the username as well.
See http://docs.meteor.com/api/accounts.html#Accounts-ui-config
What happens when we use {{> loginButtons}}?
Then simply add the {{> loginButtons}} helper to an HTML file. This will place a login widget on the page. If there is only one provider configured and it is an external service, this will add a login/logout button. If you use accounts-password or use multiple external login services, this will add a “Sign in” link which opens a dropdown menu with login options. If you plan to position the login dropdown in the right edge of the screen, use {{> loginButtons align="right"}} in order to get the dropdown to lay itself out without expanding off the edge of the screen.
To configure the behavior of {{> loginButtons}}, use Accounts.ui.config.
accounts-ui also includes modal popup dialogs to handle links from sendResetPasswordEmail, sendVerificationEmail, and sendEnrollmentEmail. These do not have to be manually placed in HTML: they are automatically activated when the URLs are loaded.
If you want to control the look and feel of your accounts system a little more, we recommend reading the useraccounts section of the Meteor Guide.
How can we group fields?
Grouping fields together is a special problem in regard to layout. The issue is creating some container markup while iterating over the fields (the templating engine of Meteor doesn't allow outputting an opening tag inside a loop without closing it in the same iteration). A solution to the problem is demonstrated in this gist (Semantic UI version).
How can we change CSS rules for atForm?
The main atForm is build up of several pieces, appearing and disappearing based on configuration options as well as the current internal status. Each of these blocks is wrapped inside a div with class at-<something>: this should made your life easier if you're trying to write your own CSS rules to change templates' appearance.
Social login buttons (button.at-social-btn) have an id in the form at-<servicename> and name <servicename>.
Input fields for the password service form are wrapped inside a div with class at-input. The same div gets classes has-error, has-success, and has-feedback in case of negative validation result, positive validation and validation with feedback respectively. The input element itself has id and name in the form at-field-<field_id>. Note: has-error, has-success, and has-feedback names might change from framework to framework. These are valid for the unstyled and bootstrap versions…
Below is a html snapshot of an over-complete atForm taken from the unstyled version in which you can find all elements possibly shown under different configurations and circumstances.
<div class="at-form">
<!-- Title -->
<div class="at-title">
<h3>Create an Account</h3>
</div>
<!-- Social Buttons for Oauth Sign In / Sign Up-->
<div class="at-oauth">
<button class="at-social-btn" id="at-facebook" name="facebook">
<i class="fa fa-facebook"></i> Sign in with Facebook
</button>
<button class="at-social-btn" id="at-twitter" name="twitter">
<i class="fa fa-twitter"></i> Sign in with Twitter
</button>
</div>
<!-- Services Separator -->
<div class="at-sep">
<strong>OR</strong>
</div>
<!-- Global Error -->
<div class="at-error">
<p>Login forbidden</p>
</div>
<!-- Global Resutl -->
<div class="at-result">
<p>Email Sent!</p>
</div>
<!-- Password Service -->
<div class="at-pwd-form">
<form role="form" id="at-pwd-form" novalidate="">
<!-- Input -->
<div class="at-input">
<label for="at-field-username">
Username
</label>
<input type="text" id="at-field-username" name="at-field-username" placeholder="Username" autocapitalize="none" autocorrect="off">
</div>
<!-- Input with Validation Error -->
<div class="at-input has-error">
<label for="at-field-email">
Email
</label>
<input type="email" id="at-field-email" name="at-field-email" placeholder="Email" autocapitalize="none" autocorrect="off">
<span>Invalid email</span>
</div>
<!-- Input with Successful Validation -->
<div class="at-input has-success">
<label for="at-field-password">
Password
</label>
<input type="password" id="at-field-password" name="at-field-password" placeholder="Password" autocapitalize="none" autocorrect="off">
</div>
<!-- Forgot Password Link -->
<div class="at-pwd-link">
<p>
<a href="/forgot-password" id="at-forgotPwd" class="at-link at-pwd">Forgot your password?</a>
</p>
</div>
<!-- Form Submit Button -->
<button type="submit" class="at-btn submit disabled" id="at-btn">
Register
</button>
</form>
</div>
<!-- Link to Sign In -->
<div class="at-signin-link">
<p>
If you already have an account
<a href="/sign-in" id="at-signIn" class="at-link at-signin">sign in</a>
</p>
</div>
<!-- Link to Sign Up -->
<div class="at-signup-link">
<p>
Don't have an account?
<a href="/sign-up" id="at-signUp" class="at-link at-signup">Register</a>
</p>
</div>
<!-- Link to Privacy Policy and Terms of use -->
<div class="at-terms-link">
<p>
By clicking Register, you agree to our
<a href="/privacyPolicy">Privacy Policy</a>
and
<a href="/termsOfUse">Terms of Use</a>
</p>
</div>
</div>
How can we configure third party login services?
Normally, if you have not configured a social account with, e.g.,
// Set up login services
Meteor.startup(function() {
// Add Facebook configuration entry
ServiceConfiguration.configurations.update(
{ "service": "facebook" },
{
$set: {
"appId": "XXXXXXXXXXXXXXX",
"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
},
{ upsert: true }
);
// Add GitHub configuration entry
ServiceConfiguration.configurations.update(
{ "service": "github" },
{
$set: {
"clientId": "XXXXXXXXXXXXXXXXXXXX",
"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
},
{ upsert: true }
);
});
3rd party login buttons are not shown. To allow display buttons with, e.g., 'Configure Foobook', simply add the packages service-configuration and accounts-ui with:
meteor add service-configuration
meteor add accounts-ui
At the moment the UI for service configuration is not supported and the one provided by accounts-ui will be shown!
How can we customize routes for the login flow?
In addition to having control over the templates, you’ll want to be able to control the routing and URLs for the different views offered by useraccounts. Since Flow Router is the officially recommended routing option for Meteor, we’ll go over that in particular.
First, we need to configure the layout we want to use when rendering the accounts templates:
AccountsTemplates.configure({
defaultTemplate: 'Auth_page',
defaultLayout: 'App_body',
defaultContentRegion: 'main',
defaultLayoutRegions: {}
});
In this case, we want to use the App_body layout template for all of the accounts-related pages. This template has a content region called main. Now, let’s configure some routes:
// Define these routes in a file loaded on both client and server
AccountsTemplates.configureRoute('signIn', {
name: 'signin',
path: '/signin'
});
AccountsTemplates.configureRoute('signUp', {
name: 'join',
path: '/join'
});
AccountsTemplates.configureRoute('forgotPwd');
AccountsTemplates.configureRoute('resetPwd', {
name: 'resetPwd',
path: '/reset-password'
});
Now, we can easily render links to our login page like so:
<div class="btns-group">
<a href="{{pathFor 'signin'}}" class="btn-secondary">Sign In</a>
<a href="{{pathFor 'join'}}" class="btn-secondary">Join</a>
</div>
Note that we have specified a password reset route. Normally, we would have to configure Meteor’s accounts system to send this route in password reset emails, but the useraccounts:flow-routing package does it for us. Read more about configuring email flows.
You can find a complete list of different available routes in the documentation the useraccounts:flow-routing.
What is the purpose of the accounts-base package?
This package is the core of Meteor’s developer-facing user accounts functionality. Specifically, it provides:
- A users collection with a standard schema, accessed through Meteor.users, and the client-side singletons Meteor.userId() and Meteor.user(), which represent the login state on the client.
- A variety of helpful other generic methods to keep track of login state, log out, validate users, etc. Visit the Accounts section of the docs to find a complete list.
- An API for registering new login handlers, which is used by all of the other accounts packages to integrate with the accounts system. There isn’t any official documentation for this API, but you can read more about it on the MeteorHacks blog.
Usually, you don’t need to include accounts-base yourself since it’s added for you if you use accounts-password or similar, but it’s good to be aware of what is what.
What is the purpose of the atForm template?
There is only one template which is used to reactively draw appropriate sign in, sign up, forgot password, reset password, change password, and enroll account forms! It is atForm and can be used anywhere you wish like this:
{{> atForm}}
Its design is as transparent as possible, making it play nicely with themes and your CSS customizations! Also, it is not wrapped inside any container so that you can put it anywhere, including complex multi-column layouts. In case you wish to lock the template to a particular state, you can specify that via the state parameter:
{{> atForm state='signUp'}}
This will prevent the template from changing its content. See internal states for more details…
Well, actually there is many templates, used inside atForm… …plus one another: atNavButton which can be used inside navbars to get a basic sign-in sign-out button which changes text and behaviour based on the user status (to get it working you should set up at least a signIn route).
How should we use the AccountsTemplates.configure function?
There are basically two different ways to interact with AccountsTemplates for basic configuration:
- AccountsTemplates.configureRoute(route_code, options);
- AccountsTemplates.configure(options);
These functions should be called in top-level code, not inside Meteor.startup(). There is no specific order for the above calls to be effective, and you can call them more than once, possibly in different files. The only other requirement is to make exactly the same calls on both the server and the client. The best thing is to put everything inside a file shared between both. I suggest you use something like lib/config/at_config.js
AccountsTemplates.configure({
// Behavior
confirmPassword: true,
enablePasswordChange: true,
forbidClientAccountCreation: false,
overrideLoginErrors: true,
sendVerificationEmail: false,
lowercaseUsername: false,
focusFirstInput: true,
// Appearance
showAddRemoveServices: false,
showForgotPasswordLink: false,
showLabels: true,
showPlaceholders: true,
showResendVerificationEmailLink: false,
// Client-side Validation
continuousValidation: false,
negativeFeedback: false,
negativeValidation: true,
positiveValidation: true,
positiveFeedback: true,
showValidating: true,
// Privacy Policy and Terms of Use
privacyUrl: 'privacy',
termsUrl: 'terms-of-use',
// Redirects
homeRoutePath: '/home',
redirectTimeout: 4000,
// Hooks
onLogoutHook: myLogoutFunc,
onSubmitHook: mySubmitFunc,
preSignUpHook: myPreSubmitFunc,
postSignUpHook: myPostSubmitFunc,
// Texts
texts: {
button: {
signUp: "Register Now!"
},
socialSignUp: "Register",
socialIcons: {
"meteor-developer": "fa fa-rocket"
},
title: {
forgotPwd: "Recover Your Password"
},
},
});
What is the purpose of AccountsTemplates.logout()?
Should be used in place of Meteor.logout(). This function invokes the onLogoutHook specified in the optional configuration. Also note that AccountsTemplates.logout() is invoked when logging out using the atNavButton.
AccountsTemplates.logout();
How can we secure a specific template?
If you want to secure a specific template, you could add that template like this:
{{> ensureSignedIn template="myTemplate"}}
and that will render the default fullPageAtForm template from your chosen User Accounts templates package (bootstrap, materialize, etc). Once signed in, it'll render myTemplate instead of the accounts form. If you want to declare a custom sign in template instead of fullPageAtForm, you would do this:
{{> ensureSignedIn template="myTemplate" auth="myLoginForm"}}
That custom auth template just needs to include > atForm somewhere in it. The only reason you'd use this optional feature is if you wanted to modify the layout around the atForm template (like fullPageAtForm does).
In case you're using one of the routing packages useraccounts:iron-routing or useraccounts:flow-routing refer to their documentation for more possibilities.
How can we set up reCaptcha?
To set up reCaptcha:
- obtain API keys
- create a setting file (see below)
- configuration to show the reCaptcha widget (see below)
// Content for the setting file:
{
"public": {
"reCaptcha": {
"siteKey": YOUR SITE KEY
}
},
"reCaptcha": {
"secretKey": YOUR SECRET KEY
}
}
// configuration to show the reCaptcha widget:
AccountsTemplates.configure({
showReCaptcha: true
});
The reCaptcha plugin can likewise be set up with the following complete example:
AccountsTemplates.configure({
reCaptcha: {
siteKey: YOUR SITE KEY,
theme: "light",
data_type: "image"
},
showReCaptcha: true
});
And, in a separate file in the /server folder:
AccountsTemplates.configure({
reCaptcha: {
secretKey: YOUR SECRET KEY.
},
});
See https://github.com/meteor-useraccounts/core/blob/master/Guide.md#recaptcha-setup for various option flags.
How can we detect reactively when a form is being processed?
AccountsTemplates.disabled() returns true when a submitted form is being processed and false once the submission process has been completed (successfully or not). AccountsTemplate.disabled() is reactive and can be used to trigger UI events, such as spinners, "Please wait" messages or to disable input elements, while the form is being processed. The function works irrespectively of form status (signIn, signUp, pwdReset etc.). A typical use-case would be in a template helper:
<template name="myLogin">
{{#if atDisabled}}
Please wait...
{{/if}}
<div class="{{atClass}}">
{{> atForm}}
</div>
</template>
Template.myLogin.helpers({
atDisabled: function() {
return AccountsTemplates.disabled();
},
atClass: function() {
return AccountsTemplates.disabled() ? 'disabled' : 'active';
}
});
How can we configure texts for atForm?
In case you wish to change texts on atForm, you can call:
AccountsTemplates.configure({
texts: {
navSignIn: "signIn",
navSignOut: "signOut",
optionalField: "optional",
pwdLink_pre: "",
pwdLink_link: "forgotPassword",
pwdLink_suff: "",
resendVerificationEmailLink_pre: "Verification email lost?",
resendVerificationEmailLink_link: "Send again",
resendVerificationEmailLink_suff: "",
sep: "OR",
signInLink_pre: "ifYouAlreadyHaveAnAccount",
signInLink_link: "signin",
signInLink_suff: "",
signUpLink_pre: "dontHaveAnAccount",
signUpLink_link: "signUp",
signUpLink_suff: "",
socialAdd: "add",
socialConfigure: "configure",
socialIcons: {
"meteor-developer": "fa fa-rocket",
},
socialRemove: "remove",
socialSignIn: "signIn",
socialSignUp: "signUp",
socialWith: "with",
termsPreamble: "clickAgree",
termsPrivacy: "privacyPolicy",
termsAnd: "and",
termsTerms: "terms",
}
};
The above example asks to change some of the available text configurations. You can specify only a subsets of them leaving default values unchanged.
How can we change form titles for atForm?
In case you wish to change form titles, you can call:
AccountsTemplates.configure({
texts: {
title: {
changePwd: "Password Title",
enrollAccount: "Enroll Title",
forgotPwd: "Forgot Pwd Title",
resetPwd: "Reset Pwd Title",
signIn: "Sign In Title",
signUp: "Sign Up Title",
verifyEmail: "Verify Email Title",
}
}
});
The above example asks to change the title for all possible form states, but you can specify only a subset of them leaving default values unchanged. You can also hide a title by setting it to an empty string. For example with:
AccountsTemplates.configure({
texts: {
title: {
signIn: "",
}
}
});
How can we change button texts for atForm?
In case you wish to change the text appearing inside the submission button, you can call:
AccountsTemplates.configure({
texts: {
button: {
changePwd: "Password Text",
enrollAccount: "Enroll Text",
forgotPwd: "Forgot Pwd Text",
resetPwd: "Reset Pwd Text",
signIn: "Sign In Text",
signUp: "Sign Up Text",
}
}
});
The above example asks to change the button text for all possible form states, but you can specify only a subset of them leaving default values unchanged.
How can we button icons for atForm?
In case you wish to change the icon appearing on the left of social login buttons, you can call:
AccountsTemplates.configure({
texts: {
socialIcons: {
google: "myGoogleIcon",
"meteor-developer": "myMeteorIcon",
}
}
});
to specify a different icon classes to be used for services. By default the icon class is set to fa fa-*service*, but for the "meteor-developer" service for which fa fa-rocket is used. An exception is made for useaccounts:semantic-ui which sets them simply to *service*, which is the correct way to go.
How can we change info text for atForm?
In case you wish to change the info text appearing inside the results box, you can call:
AccountsTemplates.configure({
texts: {
info: {
emailSent: "info.emailSent",
emailVerified: "info.emailVerified",
pwdChanged: "info.passwordChanged",
pwdReset: "info.passwordReset",
pwdSet: "info.passwordReset",
signUpVerifyEmail: "Successful Registration! Please check your email and follow the instructions.",
verificationEmailSent: "A new email has been sent to you. If the email doesn't show up in your inbox, be sure to check your spam folder.",
}
}
});
The above calls simply set all values as the current default ones.
How can we change the input field icons for atForm?
In case you wish to change the icon appearing on the right side of input fields to show their validation status, you can call:
AccountsTemplates.configure({
texts: {
inputIcons: {
isValidating: "fa fa-spinner fa-spin",
hasSuccess: "fa fa-check",
hasError: "fa fa-times",
}
}
});
How can we change error text for atForm?
In case you wish to change the text for errors appearing inside the error box, you can call:
AccountsTemplates.configure({
texts: {
errors: {
accountsCreationDisabled: "Client side accounts creation is disabled!!!",
cannotRemoveService: "Cannot remove the only active service!",
captchaVerification: "Captcha verification failed!",
loginForbidden: "error.accounts.Login forbidden",
mustBeLoggedIn: "error.accounts.Must be logged in",
pwdMismatch: "error.pwdsDontMatch",
validationErrors: "Validation Errors",
verifyEmailFirst: "Please verify your email first. Check the email and follow the link!",
}
}
});
The above calls simply set all values as the current default ones. Note: The above list of errors refers to those set directly by AccountsTemplates only! Errors which comes from the Accounts packages cannot be overwritten (at least not easily…) Please have a look at Form Fields Configuration to learn how to set validation errors on a field basis.
How can we disable client-side account creation?
AccountsTemplates disables by default accounts creation on the client. This is done to use a dedicated method called ATCreateUserServer (sending the password on the wire already hashed as usual…) to create the new users server-side. This way a bulletproof profile fields full validation can be performed. But there is one more parameter to set in case you'd like to forbid client-side accounts creation, which is the following:
- forbidClientAccountCreation - (Boolean, default false) Specifies whether to forbid accounts creation from the client.
This is exactly the same provided by the Accounts object, so this means you need to do:
AccountsTemplates.configure({
forbidClientAccountCreation: true
});
instead of the usual:
Accounts.config({
forbidClientAccountCreation : true
});
How can we customize form fields for atForm?
Every input field appearing inside AccountsTemplates forms can be easily customized both for appearance and validation behaviour. Additional (custom) fields can be added to the sign up and registration forms, and the properties of built-in fields, like email and password can be overridden (see Remove fields).
See https://github.com/meteor-useraccounts/core/blob/master/Guide.md#form-fields-configuration
How can we do custom validation for atForm?
See https://github.com/meteor-useraccounts/core/blob/master/Guide.md#custom-validation
What happens if we do not configure the email package?
The email package is automatically added to the project by the accounts-password package, but if you do not configure the email package, then all messages will be shown in the server console but never actually sent out. Meteor requires the MAIL_URL environment variable to hold the connection string for an SMTP server.
Meteor.startup(function(){
smtp = {
username: 'yourmail@gmail.com',
password: 'yourSecretPassword',
server: 'smtp.gmail.com',
port: 587
};
process.env.MAIL_URL = 'smtp://' + encodeURIComponent(smtp.username) + ':' +
encodeURIComponent(smtp.password) + '@' +
encodeURIComponent(smtp.server) + ':' +
smtp.port;
});
How can we send the "reset password" email?
Use the Accounts.sendResetPasswordEmail function
How can we send the enrollment email?
Use the Accounts.sendEnrollmentEmail function
How can we send the verification email?
Use the Accounts.sendVerificationEmail function.
How can we do some basic customization to the email templates?
Accounts.emailTemplate.siteName = '...';
Accounts.emailTemplate.from = 'Your From Address';
Accounts.emailTemplate.verifyEmail.subject = function (user) {
return 'Confirm you email address, ' + user.username;
};
Accounts.emailTemplates.verifyEmail.text = function(user, url) {
return 'Welcome to ... To verify your email address click on the link below:\n\n' + url;
};
Accounts.emailTemplates.verifyEmail.html = function(user, url) {
return '<h1>Welcome to ...</h1><p>To verify your email address, click on the link below:</p>' + url;
};
Beside verifyEmail, there is also resetPassword, and enrollAccount
What is the purpose of the 'service-configuration' package?
As long as there is NO credential available in the database, any user visiting the application will be able to configure it via the browser. To avoid this, you can add any OAuth credential to the application's source code. In case that there is no credential available in the database yet, these will be automatically inserted. This requires a package called service-configuration to be available:
meteor add service-configuration
Put this in server/server.js:
if (ServiceConfiguration.configurations.find({service: 'facebook'}).count() == 0) {
ServiceConfiguration.configurations.insert({
service: 'facebook',
appId: '...',
secret: '...',
loginStyle: 'popup'
});
}
What is the purpose of Accounts.onCreateUser?
When registering a new user, to extend the default behavior, it is possible to hook into the creation process to add checks or enrich the data stored. This is done using Accounts.onCreateUser() which takes a function as its argument. This function gets called every time a new user is created and enables you to control the content of new user documents. The function itself can make use of two arguments (options and user):
Accounts.onCreateUser(function(options, user) {
user.profile = options.profile;
if (user.services.facebook) {
user.profile.first_name = user.services.facebook.first_name;
user.profile.last_name = user.services.facebook.last_name;
user.profile.gender = user.services.facebook.gender;
}
return user;
});
The options object come from the authentication provider, in this case accounts-password. It comes from the client and should not be trusted.
If you want to add profile information to each new user, you need to place your code in the server/server.js file or inside an isServer block.