{"version":3,"sources":["meteor://💻app/packages/accounts-base/server_main.js","meteor://💻app/packages/accounts-base/accounts_common.js","meteor://💻app/packages/accounts-base/accounts_server.js"],"names":["module1","module","export","AccountsServer","link","v","Accounts","Meteor","server","users","AccountsCommon","EXPIRE_TOKENS_INTERVAL_MS","CONNECTION_CLOSE_DELAY_MS","constructor","options","_options","connection","undefined","_initConnection","Mongo","Collection","_preventAutopublish","_onLoginHook","Hook","bindEnvironment","debugPrintExceptions","_onLoginFailureHook","_onLogoutHook","DEFAULT_LOGIN_EXPIRATION_DAYS","LOGIN_UNEXPIRING_TOKEN_DAYS","lceName","LoginCancelledError","makeErrorType","description","message","prototype","name","numericError","startup","ServiceConfiguration","Package","loginServiceConfiguration","configurations","ConfigError","userId","Error","user","findOne","config","isServer","__meteor_runtime_config__","accountsConfigCalled","_debug","Object","hasOwnProperty","call","isClient","OAuthEncryption","loadKey","oauthSecretKey","VALID_KEYS","keys","forEach","key","includes","onLogin","func","register","onLoginFailure","onLogout","ddpUrl","DDP","connect","ACCOUNTS_CONNECTION_URL","_getTokenLifetimeMs","loginExpirationInDays","_getPasswordResetTokenLifetimeMs","passwordResetTokenExpirationInDays","DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS","_getPasswordEnrollTokenLifetimeMs","passwordEnrollTokenExpirationInDays","DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS","_tokenExpiration","when","Date","getTime","_tokenExpiresSoon","minLifetimeMs","minLifetimeCapMs","MIN_TOKEN_LIFETIME_CAP_SECS","crypto","default","hasOwn","_server","_initServerMethods","_initAccountDataHooks","_autopublishFields","loggedInUser","otherUsers","_initServerPublications","_accountData","_userObservesForConnections","_nextUserObserveNumber","_loginHandlers","setupUsersCollection","setupDefaultLoginHandlers","setExpireTokensInterval","_validateLoginHook","_validateNewUserHooks","defaultValidateNewUserHook","bind","_deleteSavedTokensForAllUsersOnStartup","_skipCaseInsensitiveChecksForTest","urls","resetPassword","token","absoluteUrl","verifyEmail","enrollAccount","addDefaultRateLimit","currentInvocation","_CurrentMethodInvocation","get","_CurrentPublicationInvocation","validateLoginAttempt","validateNewUser","push","onCreateUser","_onCreateUserHook","onExternalLogin","_onExternalLoginHook","_validateLogin","attempt","each","callback","ret","cloneAttemptWithConnection","e","allowed","error","_successfulLogin","_failedLogin","_successfulLogout","_loginUser","methodInvocation","stampedLoginToken","_generateStampedLoginToken","_insertLoginToken","_noYieldsAllowed","_setLoginToken","_hashLoginToken","setUserId","id","tokenExpires","_attemptLogin","methodName","methodArgs","result","type","methodArguments","Array","from","_loginMethod","fn","tryLoginMethod","_reportLoginFailure","registerLoginHandler","handler","_runLoginHandlers","destroyToken","loginToken","update","$pull","$or","hashedToken","accounts","methods","login","check","arguments","logout","_getLoginToken","logoutOtherClients","fields","tokens","services","resume","loginTokens","newToken","$set","$push","_hashStampedToken","setTimeout","_deleteSavedTokensForUser","_noConnectionCloseDelayForTest","getNewToken","currentHashedToken","currentStampedToken","find","stampedToken","newStampedToken","removeOtherTokens","currentToken","$ne","configureLoginService","Match","ObjectIncluding","service","String","oauth","serviceNames","usingOAuthEncryption","secret","seal","insert","onConnection","onClose","_removeTokenFromConnection","publish","is_auto","_id","profile","username","emails","autopublish","toFieldSelector","reduce","prev","field","selector","addAutopublishFields","opts","apply","forLoggedInUser","forOtherUsers","_getAccountData","connectionId","data","_setAccountData","value","hash","createHash","digest","hashedStampedToken","_insertHashedLoginToken","query","$addToSet","_clearAllLoginTokens","_getUserObserve","observe","stop","myObserveNumber","defer","foundMatchingUser","observeChanges","added","removed","close","Random","_expirePasswordResetTokens","oldestValidDate","tokenLifetimeMs","tokenFilter","$exists","expirePasswordToken","_expirePasswordEnrollTokens","_expireTokens","userFilter","$lt","multi","superResult","expireTokenInterval","clearInterval","insertUserDoc","createdAt","pinEncryptedFieldsToUser","fullUser","defaultCreateUserHook","hook","errmsg","_testEmailDomain","email","domain","restrictCreationByEmailDomain","RegExp","_escapeRegExp","test","tokensToDelete","$unset","$pullAll","loginTokensToDelete","updateOrCreateUserFromExternalService","serviceName","serviceData","serviceIdKey","isNaN","parseInt","setAttrs","removeDefaultRateLimit","resp","DDPRateLimiter","removeRule","defaultRateLimiterRuleId","addRule","clientAddress","clonedAttempt","EJSON","clone","defaultResumeLoginHandler","oldUnhashedStyleToken","resetRangeOr","expireFilter","$and","setInterval","keyIsLoaded","isSealed","open","emailIsGood","length","address","values","allow","modifier","fetch","_ensureIndex","unique","sparse"],"mappings":"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","file":"/packages/accounts-base.js","sourcesContent":["import { AccountsServer } from \"./accounts_server.js\";\n\n/**\n * @namespace Accounts\n * @summary The namespace for all server-side accounts-related methods.\n */\nAccounts = new AccountsServer(Meteor.server);\n\n// Users table. Don't use the normal autopublish, since we want to hide\n// some fields. Code to autopublish this is in accounts_server.js.\n// XXX Allow users to configure this collection name.\n\n/**\n * @summary A [Mongo.Collection](#collections) containing user documents.\n * @locus Anywhere\n * @type {Mongo.Collection}\n * @importFromPackage meteor\n*/\nMeteor.users = Accounts.users;\n\nexport {\n // Since this file is the main module for the server version of the\n // accounts-base package, properties of non-entry-point modules need to\n // be re-exported in order to be accessible to modules that import the\n // accounts-base package.\n AccountsServer\n};\n","/**\n * @summary Super-constructor for AccountsClient and AccountsServer.\n * @locus Anywhere\n * @class AccountsCommon\n * @instancename accountsClientOrServer\n * @param options {Object} an object with fields:\n * - connection {Object} Optional DDP connection to reuse.\n * - ddpUrl {String} Optional URL for creating a new DDP connection.\n */\nexport class AccountsCommon {\n constructor(options) {\n // Currently this is read directly by packages like accounts-password\n // and accounts-ui-unstyled.\n this._options = {};\n\n // Note that setting this.connection = null causes this.users to be a\n // LocalCollection, which is not what we want.\n this.connection = undefined;\n this._initConnection(options || {});\n\n // There is an allow call in accounts_server.js that restricts writes to\n // this collection.\n this.users = new Mongo.Collection(\"users\", {\n _preventAutopublish: true,\n connection: this.connection\n });\n\n // Callback exceptions are printed with Meteor._debug and ignored.\n this._onLoginHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: \"onLogin callback\"\n });\n\n this._onLoginFailureHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: \"onLoginFailure callback\"\n });\n\n this._onLogoutHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: \"onLogout callback\"\n });\n\n // Expose for testing.\n this.DEFAULT_LOGIN_EXPIRATION_DAYS = DEFAULT_LOGIN_EXPIRATION_DAYS;\n this.LOGIN_UNEXPIRING_TOKEN_DAYS = LOGIN_UNEXPIRING_TOKEN_DAYS;\n\n // Thrown when the user cancels the login process (eg, closes an oauth\n // popup, declines retina scan, etc)\n const lceName = 'Accounts.LoginCancelledError';\n this.LoginCancelledError = Meteor.makeErrorType(\n lceName,\n function (description) {\n this.message = description;\n }\n );\n this.LoginCancelledError.prototype.name = lceName;\n\n // This is used to transmit specific subclass errors over the wire. We\n // should come up with a more generic way to do this (eg, with some sort of\n // symbolic error code rather than a number).\n this.LoginCancelledError.numericError = 0x8acdc2f;\n\n // loginServiceConfiguration and ConfigError are maintained for backwards compatibility\n Meteor.startup(() => {\n const { ServiceConfiguration } = Package['service-configuration'];\n this.loginServiceConfiguration = ServiceConfiguration.configurations;\n this.ConfigError = ServiceConfiguration.ConfigError;\n });\n }\n\n /**\n * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere\n */\n userId() {\n throw new Error(\"userId method not implemented\");\n }\n\n /**\n * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere\n */\n user() {\n const userId = this.userId();\n return userId ? this.users.findOne(userId) : null;\n }\n\n // Set up config for the accounts system. Call this on both the client\n // and the server.\n //\n // Note that this method gets overridden on AccountsServer.prototype, but\n // the overriding method calls the overridden method.\n //\n // XXX we should add some enforcement that this is called on both the\n // client and the server. Otherwise, a user can\n // 'forbidClientAccountCreation' only on the client and while it looks\n // like their app is secure, the server will still accept createUser\n // calls. https://github.com/meteor/meteor/issues/828\n //\n // @param options {Object} an object with fields:\n // - sendVerificationEmail {Boolean}\n // Send email address verification emails to new users created from\n // client signups.\n // - forbidClientAccountCreation {Boolean}\n // Do not allow clients to create accounts directly.\n // - restrictCreationByEmailDomain {Function or String}\n // Require created users to have an email matching the function or\n // having the string as domain.\n // - loginExpirationInDays {Number}\n // Number of days since login until a user is logged out (login token\n // expires).\n // - passwordResetTokenExpirationInDays {Number}\n // Number of days since password reset token creation until the\n // token cannt be used any longer (password reset token expires).\n // - ambiguousErrorMessages {Boolean}\n // Return ambiguous error messages from login failures to prevent\n // user enumeration.\n // - bcryptRounds {Number}\n // Allows override of number of bcrypt rounds (aka work factor) used\n // to store passwords.\n\n /**\n * @summary Set global accounts options.\n * @locus Anywhere\n * @param {Object} options\n * @param {Boolean} options.sendVerificationEmail New users with an email address will receive an address verification email.\n * @param {Boolean} options.forbidClientAccountCreation Calls to [`createUser`](#accounts_createuser) from the client will be rejected. In addition, if you are using [accounts-ui](#accountsui), the \"Create account\" link will not be available.\n * @param {String | Function} options.restrictCreationByEmailDomain If set to a string, only allows new users if the domain part of their email address matches the string. If set to a function, only allows new users if the function returns true. The function is passed the full email address of the proposed new user. Works with password-based sign-in and external services that expose email addresses (Google, Facebook, GitHub). All existing users still can log in after enabling this option. Example: `Accounts.config({ restrictCreationByEmailDomain: 'school.edu' })`.\n * @param {Number} options.loginExpirationInDays The number of days from when a user logs in until their token expires and they are logged out. Defaults to 90. Set to `null` to disable login expiration.\n * @param {String} options.oauthSecretKey When using the `oauth-encryption` package, the 16 byte key using to encrypt sensitive account credentials in the database, encoded in base64. This option may only be specifed on the server. See packages/oauth-encryption/README.md for details.\n * @param {Number} options.passwordResetTokenExpirationInDays The number of days from when a link to reset password is sent until token expires and user can't reset password with the link anymore. Defaults to 3.\n * @param {Number} options.passwordEnrollTokenExpirationInDays The number of days from when a link to set inital password is sent until token expires and user can't set password with the link anymore. Defaults to 30.\n * @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to false.\n */\n config(options) {\n // We don't want users to accidentally only call Accounts.config on the\n // client, where some of the options will have partial effects (eg removing\n // the \"create account\" button from accounts-ui if forbidClientAccountCreation\n // is set, or redirecting Google login to a specific-domain page) without\n // having their full effects.\n if (Meteor.isServer) {\n __meteor_runtime_config__.accountsConfigCalled = true;\n } else if (!__meteor_runtime_config__.accountsConfigCalled) {\n // XXX would be nice to \"crash\" the client and replace the UI with an error\n // message, but there's no trivial way to do this.\n Meteor._debug(\"Accounts.config was called on the client but not on the \" +\n \"server; some configuration options may not take effect.\");\n }\n\n // We need to validate the oauthSecretKey option at the time\n // Accounts.config is called. We also deliberately don't store the\n // oauthSecretKey in Accounts._options.\n if (Object.prototype.hasOwnProperty.call(options, 'oauthSecretKey')) {\n if (Meteor.isClient) {\n throw new Error(\"The oauthSecretKey option may only be specified on the server\");\n }\n if (! Package[\"oauth-encryption\"]) {\n throw new Error(\"The oauth-encryption package must be loaded to set oauthSecretKey\");\n }\n Package[\"oauth-encryption\"].OAuthEncryption.loadKey(options.oauthSecretKey);\n options = { ...options };\n delete options.oauthSecretKey;\n }\n\n // validate option keys\n const VALID_KEYS = [\"sendVerificationEmail\", \"forbidClientAccountCreation\", \"passwordEnrollTokenExpirationInDays\",\n \"restrictCreationByEmailDomain\", \"loginExpirationInDays\", \"passwordResetTokenExpirationInDays\",\n \"ambiguousErrorMessages\", \"bcryptRounds\"];\n Object.keys(options).forEach(key => {\n if (!VALID_KEYS.includes(key)) {\n throw new Error(`Accounts.config: Invalid key: ${key}`);\n }\n });\n\n // set values in Accounts._options\n VALID_KEYS.forEach(key => {\n if (key in options) {\n if (key in this._options) {\n throw new Error(`Can't set \\`${key}\\` more than once`);\n }\n this._options[key] = options[key];\n }\n });\n }\n\n /**\n * @summary Register a callback to be called after a login attempt succeeds.\n * @locus Anywhere\n * @param {Function} func The callback to be called when login is successful.\n * The callback receives a single object that\n * holds login details. This object contains the login\n * result type (password, resume, etc.) on both the\n * client and server. `onLogin` callbacks registered\n * on the server also receive extra data, such\n * as user details, connection information, etc.\n */\n onLogin(func) {\n return this._onLoginHook.register(func);\n }\n\n /**\n * @summary Register a callback to be called after a login attempt fails.\n * @locus Anywhere\n * @param {Function} func The callback to be called after the login has failed.\n */\n onLoginFailure(func) {\n return this._onLoginFailureHook.register(func);\n }\n\n /**\n * @summary Register a callback to be called after a logout attempt succeeds.\n * @locus Anywhere\n * @param {Function} func The callback to be called when logout is successful.\n */\n onLogout(func) {\n return this._onLogoutHook.register(func);\n }\n\n _initConnection(options) {\n if (! Meteor.isClient) {\n return;\n }\n\n // The connection used by the Accounts system. This is the connection\n // that will get logged in by Meteor.login(), and this is the\n // connection whose login state will be reflected by Meteor.userId().\n //\n // It would be much preferable for this to be in accounts_client.js,\n // but it has to be here because it's needed to create the\n // Meteor.users collection.\n if (options.connection) {\n this.connection = options.connection;\n } else if (options.ddpUrl) {\n this.connection = DDP.connect(options.ddpUrl);\n } else if (typeof __meteor_runtime_config__ !== \"undefined\" &&\n __meteor_runtime_config__.ACCOUNTS_CONNECTION_URL) {\n // Temporary, internal hook to allow the server to point the client\n // to a different authentication server. This is for a very\n // particular use case that comes up when implementing a oauth\n // server. Unsupported and may go away at any point in time.\n //\n // We will eventually provide a general way to use account-base\n // against any DDP connection, not just one special one.\n this.connection =\n DDP.connect(__meteor_runtime_config__.ACCOUNTS_CONNECTION_URL);\n } else {\n this.connection = Meteor.connection;\n }\n }\n\n _getTokenLifetimeMs() {\n // When loginExpirationInDays is set to null, we'll use a really high\n // number of days (LOGIN_UNEXPIRABLE_TOKEN_DAYS) to simulate an\n // unexpiring token.\n const loginExpirationInDays =\n (this._options.loginExpirationInDays === null)\n ? LOGIN_UNEXPIRING_TOKEN_DAYS\n : this._options.loginExpirationInDays;\n return (loginExpirationInDays\n || DEFAULT_LOGIN_EXPIRATION_DAYS) * 24 * 60 * 60 * 1000;\n }\n\n _getPasswordResetTokenLifetimeMs() {\n return (this._options.passwordResetTokenExpirationInDays ||\n DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS) * 24 * 60 * 60 * 1000;\n }\n\n _getPasswordEnrollTokenLifetimeMs() {\n return (this._options.passwordEnrollTokenExpirationInDays ||\n DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS) * 24 * 60 * 60 * 1000;\n }\n\n _tokenExpiration(when) {\n // We pass when through the Date constructor for backwards compatibility;\n // `when` used to be a number.\n return new Date((new Date(when)).getTime() + this._getTokenLifetimeMs());\n }\n\n _tokenExpiresSoon(when) {\n let minLifetimeMs = .1 * this._getTokenLifetimeMs();\n const minLifetimeCapMs = MIN_TOKEN_LIFETIME_CAP_SECS * 1000;\n if (minLifetimeMs > minLifetimeCapMs) {\n minLifetimeMs = minLifetimeCapMs;\n }\n return new Date() > (new Date(when) - minLifetimeMs);\n }\n}\n\n// Note that Accounts is defined separately in accounts_client.js and\n// accounts_server.js.\n\n/**\n * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n */\nMeteor.userId = () => Accounts.userId();\n\n/**\n * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n */\nMeteor.user = () => Accounts.user();\n\n// how long (in days) until a login token expires\nconst DEFAULT_LOGIN_EXPIRATION_DAYS = 90;\n// how long (in days) until reset password token expires\nconst DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS = 3;\n// how long (in days) until enrol password token expires\nconst DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS = 30;\n// Clients don't try to auto-login with a token that is going to expire within\n// .1 * DEFAULT_LOGIN_EXPIRATION_DAYS, capped at MIN_TOKEN_LIFETIME_CAP_SECS.\n// Tries to avoid abrupt disconnects from expiring tokens.\nconst MIN_TOKEN_LIFETIME_CAP_SECS = 3600; // one hour\n// how often (in milliseconds) we check for expired tokens\nexport const EXPIRE_TOKENS_INTERVAL_MS = 600 * 1000; // 10 minutes\n// how long we wait before logging out clients when Meteor.logoutOtherClients is\n// called\nexport const CONNECTION_CLOSE_DELAY_MS = 10 * 1000;\n// A large number of expiration days (approximately 100 years worth) that is\n// used when creating unexpiring tokens.\nconst LOGIN_UNEXPIRING_TOKEN_DAYS = 365 * 100;\n","import crypto from 'crypto';\nimport {\n AccountsCommon,\n EXPIRE_TOKENS_INTERVAL_MS,\n CONNECTION_CLOSE_DELAY_MS\n} from './accounts_common.js';\n\nconst hasOwn = Object.prototype.hasOwnProperty;\n\n/**\n * @summary Constructor for the `Accounts` namespace on the server.\n * @locus Server\n * @class AccountsServer\n * @extends AccountsCommon\n * @instancename accountsServer\n * @param {Object} server A server object such as `Meteor.server`.\n */\nexport class AccountsServer extends AccountsCommon {\n // Note that this constructor is less likely to be instantiated multiple\n // times than the `AccountsClient` constructor, because a single server\n // can provide only one set of methods.\n constructor(server) {\n super();\n\n this._server = server || Meteor.server;\n // Set up the server's methods, as if by calling Meteor.methods.\n this._initServerMethods();\n\n this._initAccountDataHooks();\n\n // If autopublish is on, publish these user fields. Login service\n // packages (eg accounts-google) add to these by calling\n // addAutopublishFields. Notably, this isn't implemented with multiple\n // publishes since DDP only merges only across top-level fields, not\n // subfields (such as 'services.facebook.accessToken')\n this._autopublishFields = {\n loggedInUser: ['profile', 'username', 'emails'],\n otherUsers: ['profile', 'username']\n };\n this._initServerPublications();\n\n // connectionId -> {connection, loginToken}\n this._accountData = {};\n\n // connection id -> observe handle for the login token that this connection is\n // currently associated with, or a number. The number indicates that we are in\n // the process of setting up the observe (using a number instead of a single\n // sentinel allows multiple attempts to set up the observe to identify which\n // one was theirs).\n this._userObservesForConnections = {};\n this._nextUserObserveNumber = 1; // for the number described above.\n\n // list of all registered handlers.\n this._loginHandlers = [];\n\n setupUsersCollection(this.users);\n setupDefaultLoginHandlers(this);\n setExpireTokensInterval(this);\n\n this._validateLoginHook = new Hook({ bindEnvironment: false });\n this._validateNewUserHooks = [\n defaultValidateNewUserHook.bind(this)\n ];\n\n this._deleteSavedTokensForAllUsersOnStartup();\n\n this._skipCaseInsensitiveChecksForTest = {};\n\n // XXX These should probably not actually be public?\n this.urls = {\n resetPassword: token => Meteor.absoluteUrl(`#/reset-password/${token}`),\n verifyEmail: token => Meteor.absoluteUrl(`#/verify-email/${token}`),\n enrollAccount: token => Meteor.absoluteUrl(`#/enroll-account/${token}`),\n }\n\n this.addDefaultRateLimit()\n }\n\n ///\n /// CURRENT USER\n ///\n\n // @override of \"abstract\" non-implementation in accounts_common.js\n userId() {\n // This function only works if called inside a method or a pubication.\n // Using any of the infomation from Meteor.user() in a method or\n // publish function will always use the value from when the function first\n // runs. This is likely not what the user expects. The way to make this work\n // in a method or publish function is to do Meteor.find(this.userId).observe\n // and recompute when the user record changes.\n const currentInvocation = DDP._CurrentMethodInvocation.get() || DDP._CurrentPublicationInvocation.get();\n if (!currentInvocation)\n throw new Error(\"Meteor.userId can only be invoked in method calls or publications.\");\n return currentInvocation.userId;\n }\n\n ///\n /// LOGIN HOOKS\n ///\n\n /**\n * @summary Validate login attempts.\n * @locus Server\n * @param {Function} func Called whenever a login is attempted (either successful or unsuccessful). A login can be aborted by returning a falsy value or throwing an exception.\n */\n validateLoginAttempt(func) {\n // Exceptions inside the hook callback are passed up to us.\n return this._validateLoginHook.register(func);\n }\n\n /**\n * @summary Set restrictions on new user creation.\n * @locus Server\n * @param {Function} func Called whenever a new user is created. Takes the new user object, and returns true to allow the creation or false to abort.\n */\n validateNewUser(func) {\n this._validateNewUserHooks.push(func);\n }\n\n ///\n /// CREATE USER HOOKS\n ///\n\n /**\n * @summary Customize new user creation.\n * @locus Server\n * @param {Function} func Called whenever a new user is created. Return the new user object, or throw an `Error` to abort the creation.\n */\n onCreateUser(func) {\n if (this._onCreateUserHook) {\n throw new Error(\"Can only call onCreateUser once\");\n }\n\n this._onCreateUserHook = func;\n }\n\n /**\n * @summary Customize oauth user profile updates\n * @locus Server\n * @param {Function} func Called whenever a user is logged in via oauth. Return the profile object to be merged, or throw an `Error` to abort the creation.\n */\n onExternalLogin(func) {\n if (this._onExternalLoginHook) {\n throw new Error(\"Can only call onExternalLogin once\");\n }\n\n this._onExternalLoginHook = func;\n }\n\n _validateLogin(connection, attempt) {\n this._validateLoginHook.each(callback => {\n let ret;\n try {\n ret = callback(cloneAttemptWithConnection(connection, attempt));\n }\n catch (e) {\n attempt.allowed = false;\n // XXX this means the last thrown error overrides previous error\n // messages. Maybe this is surprising to users and we should make\n // overriding errors more explicit. (see\n // https://github.com/meteor/meteor/issues/1960)\n attempt.error = e;\n return true;\n }\n if (! ret) {\n attempt.allowed = false;\n // don't override a specific error provided by a previous\n // validator or the initial attempt (eg \"incorrect password\").\n if (!attempt.error)\n attempt.error = new Meteor.Error(403, \"Login forbidden\");\n }\n return true;\n });\n };\n\n _successfulLogin(connection, attempt) {\n this._onLoginHook.each(callback => {\n callback(cloneAttemptWithConnection(connection, attempt));\n return true;\n });\n };\n\n _failedLogin(connection, attempt) {\n this._onLoginFailureHook.each(callback => {\n callback(cloneAttemptWithConnection(connection, attempt));\n return true;\n });\n };\n\n _successfulLogout(connection, userId) {\n const user = userId && this.users.findOne(userId);\n this._onLogoutHook.each(callback => {\n callback({ user, connection });\n return true;\n });\n };\n\n ///\n /// LOGIN METHODS\n ///\n\n // Login methods return to the client an object containing these\n // fields when the user was logged in successfully:\n //\n // id: userId\n // token: *\n // tokenExpires: *\n //\n // tokenExpires is optional and intends to provide a hint to the\n // client as to when the token will expire. If not provided, the\n // client will call Accounts._tokenExpiration, passing it the date\n // that it received the token.\n //\n // The login method will throw an error back to the client if the user\n // failed to log in.\n //\n //\n // Login handlers and service specific login methods such as\n // `createUser` internally return a `result` object containing these\n // fields:\n //\n // type:\n // optional string; the service name, overrides the handler\n // default if present.\n //\n // error:\n // exception; if the user is not allowed to login, the reason why.\n //\n // userId:\n // string; the user id of the user attempting to login (if\n // known), required for an allowed login.\n //\n // options:\n // optional object merged into the result returned by the login\n // method; used by HAMK from SRP.\n //\n // stampedLoginToken:\n // optional object with `token` and `when` indicating the login\n // token is already present in the database, returned by the\n // \"resume\" login handler.\n //\n // For convenience, login methods can also throw an exception, which\n // is converted into an {error} result. However, if the id of the\n // user attempting the login is known, a {userId, error} result should\n // be returned instead since the user id is not captured when an\n // exception is thrown.\n //\n // This internal `result` object is automatically converted into the\n // public {id, token, tokenExpires} object returned to the client.\n\n // Try a login method, converting thrown exceptions into an {error}\n // result. The `type` argument is a default, inserted into the result\n // object if not explicitly returned.\n //\n // Log in a user on a connection.\n //\n // We use the method invocation to set the user id on the connection,\n // not the connection object directly. setUserId is tied to methods to\n // enforce clear ordering of method application (using wait methods on\n // the client, and a no setUserId after unblock restriction on the\n // server)\n //\n // The `stampedLoginToken` parameter is optional. When present, it\n // indicates that the login token has already been inserted into the\n // database and doesn't need to be inserted again. (It's used by the\n // \"resume\" login handler).\n _loginUser(methodInvocation, userId, stampedLoginToken) {\n if (! stampedLoginToken) {\n stampedLoginToken = this._generateStampedLoginToken();\n this._insertLoginToken(userId, stampedLoginToken);\n }\n\n // This order (and the avoidance of yields) is important to make\n // sure that when publish functions are rerun, they see a\n // consistent view of the world: the userId is set and matches\n // the login token on the connection (not that there is\n // currently a public API for reading the login token on a\n // connection).\n Meteor._noYieldsAllowed(() =>\n this._setLoginToken(\n userId,\n methodInvocation.connection,\n this._hashLoginToken(stampedLoginToken.token)\n )\n );\n\n methodInvocation.setUserId(userId);\n\n return {\n id: userId,\n token: stampedLoginToken.token,\n tokenExpires: this._tokenExpiration(stampedLoginToken.when)\n };\n };\n\n // After a login method has completed, call the login hooks. Note\n // that `attemptLogin` is called for *all* login attempts, even ones\n // which aren't successful (such as an invalid password, etc).\n //\n // If the login is allowed and isn't aborted by a validate login hook\n // callback, log in the user.\n //\n _attemptLogin(\n methodInvocation,\n methodName,\n methodArgs,\n result\n ) {\n if (!result)\n throw new Error(\"result is required\");\n\n // XXX A programming error in a login handler can lead to this occuring, and\n // then we don't call onLogin or onLoginFailure callbacks. Should\n // tryLoginMethod catch this case and turn it into an error?\n if (!result.userId && !result.error)\n throw new Error(\"A login method must specify a userId or an error\");\n\n let user;\n if (result.userId)\n user = this.users.findOne(result.userId);\n\n const attempt = {\n type: result.type || \"unknown\",\n allowed: !! (result.userId && !result.error),\n methodName: methodName,\n methodArguments: Array.from(methodArgs)\n };\n if (result.error) {\n attempt.error = result.error;\n }\n if (user) {\n attempt.user = user;\n }\n\n // _validateLogin may mutate `attempt` by adding an error and changing allowed\n // to false, but that's the only change it can make (and the user's callbacks\n // only get a clone of `attempt`).\n this._validateLogin(methodInvocation.connection, attempt);\n\n if (attempt.allowed) {\n const ret = {\n ...this._loginUser(\n methodInvocation,\n result.userId,\n result.stampedLoginToken\n ),\n ...result.options\n };\n ret.type = attempt.type;\n this._successfulLogin(methodInvocation.connection, attempt);\n return ret;\n }\n else {\n this._failedLogin(methodInvocation.connection, attempt);\n throw attempt.error;\n }\n };\n\n // All service specific login methods should go through this function.\n // Ensure that thrown exceptions are caught and that login hook\n // callbacks are still called.\n //\n _loginMethod(\n methodInvocation,\n methodName,\n methodArgs,\n type,\n fn\n ) {\n return this._attemptLogin(\n methodInvocation,\n methodName,\n methodArgs,\n tryLoginMethod(type, fn)\n );\n };\n\n\n // Report a login attempt failed outside the context of a normal login\n // method. This is for use in the case where there is a multi-step login\n // procedure (eg SRP based password login). If a method early in the\n // chain fails, it should call this function to report a failure. There\n // is no corresponding method for a successful login; methods that can\n // succeed at logging a user in should always be actual login methods\n // (using either Accounts._loginMethod or Accounts.registerLoginHandler).\n _reportLoginFailure(\n methodInvocation,\n methodName,\n methodArgs,\n result\n ) {\n const attempt = {\n type: result.type || \"unknown\",\n allowed: false,\n error: result.error,\n methodName: methodName,\n methodArguments: Array.from(methodArgs)\n };\n\n if (result.userId) {\n attempt.user = this.users.findOne(result.userId);\n }\n\n this._validateLogin(methodInvocation.connection, attempt);\n this._failedLogin(methodInvocation.connection, attempt);\n\n // _validateLogin may mutate attempt to set a new error message. Return\n // the modified version.\n return attempt;\n };\n\n ///\n /// LOGIN HANDLERS\n ///\n\n // The main entry point for auth packages to hook in to login.\n //\n // A login handler is a login method which can return `undefined` to\n // indicate that the login request is not handled by this handler.\n //\n // @param name {String} Optional. The service name, used by default\n // if a specific service name isn't returned in the result.\n //\n // @param handler {Function} A function that receives an options object\n // (as passed as an argument to the `login` method) and returns one of:\n // - `undefined`, meaning don't handle;\n // - a login method result object\n\n registerLoginHandler(name, handler) {\n if (! handler) {\n handler = name;\n name = null;\n }\n\n this._loginHandlers.push({\n name: name,\n handler: handler\n });\n };\n\n\n // Checks a user's credentials against all the registered login\n // handlers, and returns a login token if the credentials are valid. It\n // is like the login method, except that it doesn't set the logged-in\n // user on the connection. Throws a Meteor.Error if logging in fails,\n // including the case where none of the login handlers handled the login\n // request. Otherwise, returns {id: userId, token: *, tokenExpires: *}.\n //\n // For example, if you want to login with a plaintext password, `options` could be\n // { user: { username: }, password: }, or\n // { user: { email: }, password: }.\n\n // Try all of the registered login handlers until one of them doesn't\n // return `undefined`, meaning it handled this call to `login`. Return\n // that return value.\n _runLoginHandlers(methodInvocation, options) {\n for (let handler of this._loginHandlers) {\n const result = tryLoginMethod(\n handler.name,\n () => handler.handler.call(methodInvocation, options)\n );\n\n if (result) {\n return result;\n }\n\n if (result !== undefined) {\n throw new Meteor.Error(400, \"A login handler should return a result or undefined\");\n }\n }\n\n return {\n type: null,\n error: new Meteor.Error(400, \"Unrecognized options for login request\")\n };\n };\n\n // Deletes the given loginToken from the database.\n //\n // For new-style hashed token, this will cause all connections\n // associated with the token to be closed.\n //\n // Any connections associated with old-style unhashed tokens will be\n // in the process of becoming associated with hashed tokens and then\n // they'll get closed.\n destroyToken(userId, loginToken) {\n this.users.update(userId, {\n $pull: {\n \"services.resume.loginTokens\": {\n $or: [\n { hashedToken: loginToken },\n { token: loginToken }\n ]\n }\n }\n });\n };\n\n _initServerMethods() {\n // The methods created in this function need to be created here so that\n // this variable is available in their scope.\n const accounts = this;\n\n\n // This object will be populated with methods and then passed to\n // accounts._server.methods further below.\n const methods = {};\n\n // @returns {Object|null}\n // If successful, returns {token: reconnectToken, id: userId}\n // If unsuccessful (for example, if the user closed the oauth login popup),\n // throws an error describing the reason\n methods.login = function (options) {\n // Login handlers should really also check whatever field they look at in\n // options, but we don't enforce it.\n check(options, Object);\n\n const result = accounts._runLoginHandlers(this, options);\n\n return accounts._attemptLogin(this, \"login\", arguments, result);\n };\n\n methods.logout = function () {\n const token = accounts._getLoginToken(this.connection.id);\n accounts._setLoginToken(this.userId, this.connection, null);\n if (token && this.userId) {\n accounts.destroyToken(this.userId, token);\n }\n accounts._successfulLogout(this.connection, this.userId);\n this.setUserId(null);\n };\n\n // Delete all the current user's tokens and close all open connections logged\n // in as this user. Returns a fresh new login token that this client can\n // use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens\n // immediately instead of using a delay.\n //\n // XXX COMPAT WITH 0.7.2\n // This single `logoutOtherClients` method has been replaced with two\n // methods, one that you call to get a new token, and another that you\n // call to remove all tokens except your own. The new design allows\n // clients to know when other clients have actually been logged\n // out. (The `logoutOtherClients` method guarantees the caller that\n // the other clients will be logged out at some point, but makes no\n // guarantees about when.) This method is left in for backwards\n // compatibility, especially since application code might be calling\n // this method directly.\n //\n // @returns {Object} Object with token and tokenExpires keys.\n methods.logoutOtherClients = function () {\n const user = accounts.users.findOne(this.userId, {\n fields: {\n \"services.resume.loginTokens\": true\n }\n });\n if (user) {\n // Save the current tokens in the database to be deleted in\n // CONNECTION_CLOSE_DELAY_MS ms. This gives other connections in the\n // caller's browser time to find the fresh token in localStorage. We save\n // the tokens in the database in case we crash before actually deleting\n // them.\n const tokens = user.services.resume.loginTokens;\n const newToken = accounts._generateStampedLoginToken();\n accounts.users.update(this.userId, {\n $set: {\n \"services.resume.loginTokensToDelete\": tokens,\n \"services.resume.haveLoginTokensToDelete\": true\n },\n $push: { \"services.resume.loginTokens\": accounts._hashStampedToken(newToken) }\n });\n Meteor.setTimeout(() => {\n // The observe on Meteor.users will take care of closing the connections\n // associated with `tokens`.\n accounts._deleteSavedTokensForUser(this.userId, tokens);\n }, accounts._noConnectionCloseDelayForTest ? 0 :\n CONNECTION_CLOSE_DELAY_MS);\n // We do not set the login token on this connection, but instead the\n // observe closes the connection and the client will reconnect with the\n // new token.\n return {\n token: newToken.token,\n tokenExpires: accounts._tokenExpiration(newToken.when)\n };\n } else {\n throw new Meteor.Error(\"You are not logged in.\");\n }\n };\n\n // Generates a new login token with the same expiration as the\n // connection's current token and saves it to the database. Associates\n // the connection with this new token and returns it. Throws an error\n // if called on a connection that isn't logged in.\n //\n // @returns Object\n // If successful, returns { token: , id: ,\n // tokenExpires: }.\n methods.getNewToken = function () {\n const user = accounts.users.findOne(this.userId, {\n fields: { \"services.resume.loginTokens\": 1 }\n });\n if (! this.userId || ! user) {\n throw new Meteor.Error(\"You are not logged in.\");\n }\n // Be careful not to generate a new token that has a later\n // expiration than the curren token. Otherwise, a bad guy with a\n // stolen token could use this method to stop his stolen token from\n // ever expiring.\n const currentHashedToken = accounts._getLoginToken(this.connection.id);\n const currentStampedToken = user.services.resume.loginTokens.find(\n stampedToken => stampedToken.hashedToken === currentHashedToken\n );\n if (! currentStampedToken) { // safety belt: this should never happen\n throw new Meteor.Error(\"Invalid login token\");\n }\n const newStampedToken = accounts._generateStampedLoginToken();\n newStampedToken.when = currentStampedToken.when;\n accounts._insertLoginToken(this.userId, newStampedToken);\n return accounts._loginUser(this, this.userId, newStampedToken);\n };\n\n // Removes all tokens except the token associated with the current\n // connection. Throws an error if the connection is not logged\n // in. Returns nothing on success.\n methods.removeOtherTokens = function () {\n if (! this.userId) {\n throw new Meteor.Error(\"You are not logged in.\");\n }\n const currentToken = accounts._getLoginToken(this.connection.id);\n accounts.users.update(this.userId, {\n $pull: {\n \"services.resume.loginTokens\": { hashedToken: { $ne: currentToken } }\n }\n });\n };\n\n // Allow a one-time configuration for a login service. Modifications\n // to this collection are also allowed in insecure mode.\n methods.configureLoginService = (options) => {\n check(options, Match.ObjectIncluding({service: String}));\n // Don't let random users configure a service we haven't added yet (so\n // that when we do later add it, it's set up with their configuration\n // instead of ours).\n // XXX if service configuration is oauth-specific then this code should\n // be in accounts-oauth; if it's not then the registry should be\n // in this package\n if (!(accounts.oauth\n && accounts.oauth.serviceNames().includes(options.service))) {\n throw new Meteor.Error(403, \"Service unknown\");\n }\n\n const { ServiceConfiguration } = Package['service-configuration'];\n if (ServiceConfiguration.configurations.findOne({service: options.service}))\n throw new Meteor.Error(403, `Service ${options.service} already configured`);\n\n if (hasOwn.call(options, 'secret') && usingOAuthEncryption())\n options.secret = OAuthEncryption.seal(options.secret);\n\n ServiceConfiguration.configurations.insert(options);\n };\n\n accounts._server.methods(methods);\n };\n\n _initAccountDataHooks() {\n this._server.onConnection(connection => {\n this._accountData[connection.id] = {\n connection: connection\n };\n\n connection.onClose(() => {\n this._removeTokenFromConnection(connection.id);\n delete this._accountData[connection.id];\n });\n });\n };\n\n _initServerPublications() {\n // Bring into lexical scope for publish callbacks that need `this`\n const { users, _autopublishFields } = this;\n\n // Publish all login service configuration fields other than secret.\n this._server.publish(\"meteor.loginServiceConfiguration\", () => {\n const { ServiceConfiguration } = Package['service-configuration'];\n return ServiceConfiguration.configurations.find({}, {fields: {secret: 0}});\n }, {is_auto: true}); // not techincally autopublish, but stops the warning.\n\n // Publish the current user's record to the client.\n this._server.publish(null, function () {\n if (this.userId) {\n return users.find({\n _id: this.userId\n }, {\n fields: {\n profile: 1,\n username: 1,\n emails: 1\n }\n });\n } else {\n return null;\n }\n }, /*suppress autopublish warning*/{is_auto: true});\n\n // Use Meteor.startup to give other packages a chance to call\n // addAutopublishFields.\n Package.autopublish && Meteor.startup(() => {\n // ['profile', 'username'] -> {profile: 1, username: 1}\n const toFieldSelector = fields => fields.reduce((prev, field) => (\n { ...prev, [field]: 1 }),\n {}\n );\n this._server.publish(null, function () {\n if (this.userId) {\n return users.find({ _id: this.userId }, {\n fields: toFieldSelector(_autopublishFields.loggedInUser),\n })\n } else {\n return null;\n }\n }, /*suppress autopublish warning*/{is_auto: true});\n\n // XXX this publish is neither dedup-able nor is it optimized by our special\n // treatment of queries on a specific _id. Therefore this will have O(n^2)\n // run-time performance every time a user document is changed (eg someone\n // logging in). If this is a problem, we can instead write a manual publish\n // function which filters out fields based on 'this.userId'.\n this._server.publish(null, function () {\n const selector = this.userId ? { _id: { $ne: this.userId } } : {};\n return users.find(selector, {\n fields: toFieldSelector(_autopublishFields.otherUsers),\n })\n }, /*suppress autopublish warning*/{is_auto: true});\n });\n };\n\n // Add to the list of fields or subfields to be automatically\n // published if autopublish is on. Must be called from top-level\n // code (ie, before Meteor.startup hooks run).\n //\n // @param opts {Object} with:\n // - forLoggedInUser {Array} Array of fields published to the logged-in user\n // - forOtherUsers {Array} Array of fields published to users that aren't logged in\n addAutopublishFields(opts) {\n this._autopublishFields.loggedInUser.push.apply(\n this._autopublishFields.loggedInUser, opts.forLoggedInUser);\n this._autopublishFields.otherUsers.push.apply(\n this._autopublishFields.otherUsers, opts.forOtherUsers);\n };\n\n ///\n /// ACCOUNT DATA\n ///\n\n // HACK: This is used by 'meteor-accounts' to get the loginToken for a\n // connection. Maybe there should be a public way to do that.\n _getAccountData(connectionId, field) {\n const data = this._accountData[connectionId];\n return data && data[field];\n };\n\n _setAccountData(connectionId, field, value) {\n const data = this._accountData[connectionId];\n\n // safety belt. shouldn't happen. accountData is set in onConnection,\n // we don't have a connectionId until it is set.\n if (!data)\n return;\n\n if (value === undefined)\n delete data[field];\n else\n data[field] = value;\n };\n\n ///\n /// RECONNECT TOKENS\n ///\n /// support reconnecting using a meteor login token\n\n _hashLoginToken(loginToken) {\n const hash = crypto.createHash('sha256');\n hash.update(loginToken);\n return hash.digest('base64');\n };\n\n // {token, when} => {hashedToken, when}\n _hashStampedToken(stampedToken) {\n const hashedStampedToken = Object.keys(stampedToken).reduce(\n (prev, key) => key === 'token' ?\n prev :\n { ...prev, [key]: stampedToken[key] },\n {},\n )\n return {\n ...hashedStampedToken,\n hashedToken: this._hashLoginToken(stampedToken.token)\n };\n };\n\n // Using $addToSet avoids getting an index error if another client\n // logging in simultaneously has already inserted the new hashed\n // token.\n _insertHashedLoginToken(userId, hashedToken, query) {\n query = query ? { ...query } : {};\n query._id = userId;\n this.users.update(query, {\n $addToSet: {\n \"services.resume.loginTokens\": hashedToken\n }\n });\n };\n\n // Exported for tests.\n _insertLoginToken(userId, stampedToken, query) {\n this._insertHashedLoginToken(\n userId,\n this._hashStampedToken(stampedToken),\n query\n );\n };\n\n _clearAllLoginTokens(userId) {\n this.users.update(userId, {\n $set: {\n 'services.resume.loginTokens': []\n }\n });\n };\n\n // test hook\n _getUserObserve(connectionId) {\n return this._userObservesForConnections[connectionId];\n };\n\n // Clean up this connection's association with the token: that is, stop\n // the observe that we started when we associated the connection with\n // this token.\n _removeTokenFromConnection(connectionId) {\n if (hasOwn.call(this._userObservesForConnections, connectionId)) {\n const observe = this._userObservesForConnections[connectionId];\n if (typeof observe === 'number') {\n // We're in the process of setting up an observe for this connection. We\n // can't clean up that observe yet, but if we delete the placeholder for\n // this connection, then the observe will get cleaned up as soon as it has\n // been set up.\n delete this._userObservesForConnections[connectionId];\n } else {\n delete this._userObservesForConnections[connectionId];\n observe.stop();\n }\n }\n };\n\n _getLoginToken(connectionId) {\n return this._getAccountData(connectionId, 'loginToken');\n };\n\n // newToken is a hashed token.\n _setLoginToken(userId, connection, newToken) {\n this._removeTokenFromConnection(connection.id);\n this._setAccountData(connection.id, 'loginToken', newToken);\n\n if (newToken) {\n // Set up an observe for this token. If the token goes away, we need\n // to close the connection. We defer the observe because there's\n // no need for it to be on the critical path for login; we just need\n // to ensure that the connection will get closed at some point if\n // the token gets deleted.\n //\n // Initially, we set the observe for this connection to a number; this\n // signifies to other code (which might run while we yield) that we are in\n // the process of setting up an observe for this connection. Once the\n // observe is ready to go, we replace the number with the real observe\n // handle (unless the placeholder has been deleted or replaced by a\n // different placehold number, signifying that the connection was closed\n // already -- in this case we just clean up the observe that we started).\n const myObserveNumber = ++this._nextUserObserveNumber;\n this._userObservesForConnections[connection.id] = myObserveNumber;\n Meteor.defer(() => {\n // If something else happened on this connection in the meantime (it got\n // closed, or another call to _setLoginToken happened), just do\n // nothing. We don't need to start an observe for an old connection or old\n // token.\n if (this._userObservesForConnections[connection.id] !== myObserveNumber) {\n return;\n }\n\n let foundMatchingUser;\n // Because we upgrade unhashed login tokens to hashed tokens at\n // login time, sessions will only be logged in with a hashed\n // token. Thus we only need to observe hashed tokens here.\n const observe = this.users.find({\n _id: userId,\n 'services.resume.loginTokens.hashedToken': newToken\n }, { fields: { _id: 1 } }).observeChanges({\n added: () => {\n foundMatchingUser = true;\n },\n removed: connection.close,\n // The onClose callback for the connection takes care of\n // cleaning up the observe handle and any other state we have\n // lying around.\n });\n\n // If the user ran another login or logout command we were waiting for the\n // defer or added to fire (ie, another call to _setLoginToken occurred),\n // then we let the later one win (start an observe, etc) and just stop our\n // observe now.\n //\n // Similarly, if the connection was already closed, then the onClose\n // callback would have called _removeTokenFromConnection and there won't\n // be an entry in _userObservesForConnections. We can stop the observe.\n if (this._userObservesForConnections[connection.id] !== myObserveNumber) {\n observe.stop();\n return;\n }\n\n this._userObservesForConnections[connection.id] = observe;\n\n if (! foundMatchingUser) {\n // We've set up an observe on the user associated with `newToken`,\n // so if the new token is removed from the database, we'll close\n // the connection. But the token might have already been deleted\n // before we set up the observe, which wouldn't have closed the\n // connection because the observe wasn't running yet.\n connection.close();\n }\n });\n }\n };\n\n // (Also used by Meteor Accounts server and tests).\n //\n _generateStampedLoginToken() {\n return {\n token: Random.secret(),\n when: new Date\n };\n };\n\n ///\n /// TOKEN EXPIRATION\n ///\n\n // Deletes expired password reset tokens from the database.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expirePasswordResetTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getPasswordResetTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n\n const tokenFilter = {\n $or: [\n { \"services.password.reset.reason\": \"reset\"},\n { \"services.password.reset.reason\": {$exists: false}}\n ]\n };\n\n expirePasswordToken(this, oldestValidDate, tokenFilter, userId);\n }\n\n // Deletes expired password enroll tokens from the database.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expirePasswordEnrollTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getPasswordEnrollTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n\n const tokenFilter = {\n \"services.password.reset.reason\": \"enroll\"\n };\n\n expirePasswordToken(this, oldestValidDate, tokenFilter, userId);\n }\n\n // Deletes expired tokens from the database and closes all open connections\n // associated with these tokens.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expireTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n const userFilter = userId ? {_id: userId} : {};\n\n\n // Backwards compatible with older versions of meteor that stored login token\n // timestamps as numbers.\n this.users.update({ ...userFilter,\n $or: [\n { \"services.resume.loginTokens.when\": { $lt: oldestValidDate } },\n { \"services.resume.loginTokens.when\": { $lt: +oldestValidDate } }\n ]\n }, {\n $pull: {\n \"services.resume.loginTokens\": {\n $or: [\n { when: { $lt: oldestValidDate } },\n { when: { $lt: +oldestValidDate } }\n ]\n }\n }\n }, { multi: true });\n // The observe on Meteor.users will take care of closing connections for\n // expired tokens.\n };\n\n // @override from accounts_common.js\n config(options) {\n // Call the overridden implementation of the method.\n const superResult = AccountsCommon.prototype.config.apply(this, arguments);\n\n // If the user set loginExpirationInDays to null, then we need to clear the\n // timer that periodically expires tokens.\n if (hasOwn.call(this._options, 'loginExpirationInDays') &&\n this._options.loginExpirationInDays === null &&\n this.expireTokenInterval) {\n Meteor.clearInterval(this.expireTokenInterval);\n this.expireTokenInterval = null;\n }\n\n return superResult;\n };\n\n // Called by accounts-password\n insertUserDoc(options, user) {\n // - clone user document, to protect from modification\n // - add createdAt timestamp\n // - prepare an _id, so that you can modify other collections (eg\n // create a first task for every new user)\n //\n // XXX If the onCreateUser or validateNewUser hooks fail, we might\n // end up having modified some other collection\n // inappropriately. The solution is probably to have onCreateUser\n // accept two callbacks - one that gets called before inserting\n // the user document (in which you can modify its contents), and\n // one that gets called after (in which you should change other\n // collections)\n user = {\n createdAt: new Date(),\n _id: Random.id(),\n ...user,\n };\n\n if (user.services) {\n Object.keys(user.services).forEach(service =>\n pinEncryptedFieldsToUser(user.services[service], user._id)\n );\n }\n\n let fullUser;\n if (this._onCreateUserHook) {\n fullUser = this._onCreateUserHook(options, user);\n\n // This is *not* part of the API. We need this because we can't isolate\n // the global server environment between tests, meaning we can't test\n // both having a create user hook set and not having one set.\n if (fullUser === 'TEST DEFAULT HOOK')\n fullUser = defaultCreateUserHook(options, user);\n } else {\n fullUser = defaultCreateUserHook(options, user);\n }\n\n this._validateNewUserHooks.forEach(hook => {\n if (! hook(fullUser))\n throw new Meteor.Error(403, \"User validation failed\");\n });\n\n let userId;\n try {\n userId = this.users.insert(fullUser);\n } catch (e) {\n // XXX string parsing sucks, maybe\n // https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day\n if (!e.errmsg) throw e;\n if (e.errmsg.includes('emails.address'))\n throw new Meteor.Error(403, \"Email already exists.\");\n if (e.errmsg.includes('username'))\n throw new Meteor.Error(403, \"Username already exists.\");\n throw e;\n }\n return userId;\n };\n\n // Helper function: returns false if email does not match company domain from\n // the configuration.\n _testEmailDomain(email) {\n const domain = this._options.restrictCreationByEmailDomain;\n\n return !domain ||\n (typeof domain === 'function' && domain(email)) ||\n (typeof domain === 'string' &&\n (new RegExp(`@${Meteor._escapeRegExp(domain)}$`, 'i')).test(email));\n };\n\n ///\n /// CLEAN UP FOR `logoutOtherClients`\n ///\n\n _deleteSavedTokensForUser(userId, tokensToDelete) {\n if (tokensToDelete) {\n this.users.update(userId, {\n $unset: {\n \"services.resume.haveLoginTokensToDelete\": 1,\n \"services.resume.loginTokensToDelete\": 1\n },\n $pullAll: {\n \"services.resume.loginTokens\": tokensToDelete\n }\n });\n }\n };\n\n _deleteSavedTokensForAllUsersOnStartup() {\n // If we find users who have saved tokens to delete on startup, delete\n // them now. It's possible that the server could have crashed and come\n // back up before new tokens are found in localStorage, but this\n // shouldn't happen very often. We shouldn't put a delay here because\n // that would give a lot of power to an attacker with a stolen login\n // token and the ability to crash the server.\n Meteor.startup(() => {\n this.users.find({\n \"services.resume.haveLoginTokensToDelete\": true\n }, {\n \"services.resume.loginTokensToDelete\": 1\n }).forEach(user => {\n this._deleteSavedTokensForUser(\n user._id,\n user.services.resume.loginTokensToDelete\n );\n });\n });\n };\n\n ///\n /// MANAGING USER OBJECTS\n ///\n\n // Updates or creates a user after we authenticate with a 3rd party.\n //\n // @param serviceName {String} Service name (eg, twitter).\n // @param serviceData {Object} Data to store in the user's record\n // under services[serviceName]. Must include an \"id\" field\n // which is a unique identifier for the user in the service.\n // @param options {Object, optional} Other options to pass to insertUserDoc\n // (eg, profile)\n // @returns {Object} Object with token and id keys, like the result\n // of the \"login\" method.\n //\n updateOrCreateUserFromExternalService(\n serviceName,\n serviceData,\n options\n ) {\n options = { ...options };\n\n if (serviceName === \"password\" || serviceName === \"resume\") {\n throw new Error(\n \"Can't use updateOrCreateUserFromExternalService with internal service \"\n + serviceName);\n }\n if (!hasOwn.call(serviceData, 'id')) {\n throw new Error(\n `Service data for service ${serviceName} must include id`);\n }\n\n // Look for a user with the appropriate service user id.\n const selector = {};\n const serviceIdKey = `services.${serviceName}.id`;\n\n // XXX Temporary special case for Twitter. (Issue #629)\n // The serviceData.id will be a string representation of an integer.\n // We want it to match either a stored string or int representation.\n // This is to cater to earlier versions of Meteor storing twitter\n // user IDs in number form, and recent versions storing them as strings.\n // This can be removed once migration technology is in place, and twitter\n // users stored with integer IDs have been migrated to string IDs.\n if (serviceName === \"twitter\" && !isNaN(serviceData.id)) {\n selector[\"$or\"] = [{},{}];\n selector[\"$or\"][0][serviceIdKey] = serviceData.id;\n selector[\"$or\"][1][serviceIdKey] = parseInt(serviceData.id, 10);\n } else {\n selector[serviceIdKey] = serviceData.id;\n }\n\n let user = this.users.findOne(selector);\n\n // When creating a new user we pass through all options. When updating an\n // existing user, by default we only process/pass through the serviceData\n // (eg, so that we keep an unexpired access token and don't cache old email\n // addresses in serviceData.email). The onExternalLogin hook can be used when\n // creating or updating a user, to modify or pass through more options as\n // needed.\n let opts = user ? {} : options;\n if (this._onExternalLoginHook) {\n opts = this._onExternalLoginHook(options, user);\n }\n\n if (user) {\n pinEncryptedFieldsToUser(serviceData, user._id);\n\n let setAttrs = {};\n Object.keys(serviceData).forEach(key =>\n setAttrs[`services.${serviceName}.${key}`] = serviceData[key]\n );\n\n // XXX Maybe we should re-use the selector above and notice if the update\n // touches nothing?\n setAttrs = { ...setAttrs, ...opts };\n this.users.update(user._id, {\n $set: setAttrs\n });\n\n return {\n type: serviceName,\n userId: user._id\n };\n } else {\n // Create a new user with the service data.\n user = {services: {}};\n user.services[serviceName] = serviceData;\n return {\n type: serviceName,\n userId: this.insertUserDoc(opts, user)\n };\n }\n };\n\n // Removes default rate limiting rule\n removeDefaultRateLimit() {\n const resp = DDPRateLimiter.removeRule(this.defaultRateLimiterRuleId);\n this.defaultRateLimiterRuleId = null;\n return resp;\n };\n\n // Add a default rule of limiting logins, creating new users and password reset\n // to 5 times every 10 seconds per connection.\n addDefaultRateLimit() {\n if (!this.defaultRateLimiterRuleId) {\n this.defaultRateLimiterRuleId = DDPRateLimiter.addRule({\n userId: null,\n clientAddress: null,\n type: 'method',\n name: name => ['login', 'createUser', 'resetPassword', 'forgotPassword']\n .includes(name),\n connectionId: (connectionId) => true,\n }, 5, 10000);\n }\n };\n\n}\n\n// Give each login hook callback a fresh cloned copy of the attempt\n// object, but don't clone the connection.\n//\nconst cloneAttemptWithConnection = (connection, attempt) => {\n const clonedAttempt = EJSON.clone(attempt);\n clonedAttempt.connection = connection;\n return clonedAttempt;\n};\n\nconst tryLoginMethod = (type, fn) => {\n let result;\n try {\n result = fn();\n }\n catch (e) {\n result = {error: e};\n }\n\n if (result && !result.type && type)\n result.type = type;\n\n return result;\n};\n\nconst setupDefaultLoginHandlers = accounts => {\n accounts.registerLoginHandler(\"resume\", function (options) {\n return defaultResumeLoginHandler.call(this, accounts, options);\n });\n};\n\n// Login handler for resume tokens.\nconst defaultResumeLoginHandler = (accounts, options) => {\n if (!options.resume)\n return undefined;\n\n check(options.resume, String);\n\n const hashedToken = accounts._hashLoginToken(options.resume);\n\n // First look for just the new-style hashed login token, to avoid\n // sending the unhashed token to the database in a query if we don't\n // need to.\n let user = accounts.users.findOne(\n {\"services.resume.loginTokens.hashedToken\": hashedToken});\n\n if (! user) {\n // If we didn't find the hashed login token, try also looking for\n // the old-style unhashed token. But we need to look for either\n // the old-style token OR the new-style token, because another\n // client connection logging in simultaneously might have already\n // converted the token.\n user = accounts.users.findOne({\n $or: [\n {\"services.resume.loginTokens.hashedToken\": hashedToken},\n {\"services.resume.loginTokens.token\": options.resume}\n ]\n });\n }\n\n if (! user)\n return {\n error: new Meteor.Error(403, \"You've been logged out by the server. Please log in again.\")\n };\n\n // Find the token, which will either be an object with fields\n // {hashedToken, when} for a hashed token or {token, when} for an\n // unhashed token.\n let oldUnhashedStyleToken;\n let token = user.services.resume.loginTokens.find(token =>\n token.hashedToken === hashedToken\n );\n if (token) {\n oldUnhashedStyleToken = false;\n } else {\n token = user.services.resume.loginTokens.find(token =>\n token.token === options.resume\n );\n oldUnhashedStyleToken = true;\n }\n\n const tokenExpires = accounts._tokenExpiration(token.when);\n if (new Date() >= tokenExpires)\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Your session has expired. Please log in again.\")\n };\n\n // Update to a hashed token when an unhashed token is encountered.\n if (oldUnhashedStyleToken) {\n // Only add the new hashed token if the old unhashed token still\n // exists (this avoids resurrecting the token if it was deleted\n // after we read it). Using $addToSet avoids getting an index\n // error if another client logging in simultaneously has already\n // inserted the new hashed token.\n accounts.users.update(\n {\n _id: user._id,\n \"services.resume.loginTokens.token\": options.resume\n },\n {$addToSet: {\n \"services.resume.loginTokens\": {\n \"hashedToken\": hashedToken,\n \"when\": token.when\n }\n }}\n );\n\n // Remove the old token *after* adding the new, since otherwise\n // another client trying to login between our removing the old and\n // adding the new wouldn't find a token to login with.\n accounts.users.update(user._id, {\n $pull: {\n \"services.resume.loginTokens\": { \"token\": options.resume }\n }\n });\n }\n\n return {\n userId: user._id,\n stampedLoginToken: {\n token: options.resume,\n when: token.when\n }\n };\n};\n\nconst expirePasswordToken = (\n accounts,\n oldestValidDate,\n tokenFilter,\n userId\n) => {\n const userFilter = userId ? {_id: userId} : {};\n const resetRangeOr = {\n $or: [\n { \"services.password.reset.when\": { $lt: oldestValidDate } },\n { \"services.password.reset.when\": { $lt: +oldestValidDate } }\n ]\n };\n const expireFilter = { $and: [tokenFilter, resetRangeOr] };\n\n accounts.users.update({...userFilter, ...expireFilter}, {\n $unset: {\n \"services.password.reset\": \"\"\n }\n }, { multi: true });\n};\n\nconst setExpireTokensInterval = accounts => {\n accounts.expireTokenInterval = Meteor.setInterval(() => {\n accounts._expireTokens();\n accounts._expirePasswordResetTokens();\n accounts._expirePasswordEnrollTokens();\n }, EXPIRE_TOKENS_INTERVAL_MS);\n};\n\n///\n/// OAuth Encryption Support\n///\n\nconst OAuthEncryption =\n Package[\"oauth-encryption\"] &&\n Package[\"oauth-encryption\"].OAuthEncryption;\n\nconst usingOAuthEncryption = () => {\n return OAuthEncryption && OAuthEncryption.keyIsLoaded();\n};\n\n// OAuth service data is temporarily stored in the pending credentials\n// collection during the oauth authentication process. Sensitive data\n// such as access tokens are encrypted without the user id because\n// we don't know the user id yet. We re-encrypt these fields with the\n// user id included when storing the service data permanently in\n// the users collection.\n//\nconst pinEncryptedFieldsToUser = (serviceData, userId) => {\n Object.keys(serviceData).forEach(key => {\n let value = serviceData[key];\n if (OAuthEncryption && OAuthEncryption.isSealed(value))\n value = OAuthEncryption.seal(OAuthEncryption.open(value), userId);\n serviceData[key] = value;\n });\n};\n\n\n// Encrypt unencrypted login service secrets when oauth-encryption is\n// added.\n//\n// XXX For the oauthSecretKey to be available here at startup, the\n// developer must call Accounts.config({oauthSecretKey: ...}) at load\n// time, instead of in a Meteor.startup block, because the startup\n// block in the app code will run after this accounts-base startup\n// block. Perhaps we need a post-startup callback?\n\nMeteor.startup(() => {\n if (! usingOAuthEncryption()) {\n return;\n }\n\n const { ServiceConfiguration } = Package['service-configuration'];\n\n ServiceConfiguration.configurations.find({\n $and: [{\n secret: { $exists: true }\n }, {\n \"secret.algorithm\": { $exists: false }\n }]\n }).forEach(config => {\n ServiceConfiguration.configurations.update(config._id, {\n $set: {\n secret: OAuthEncryption.seal(config.secret)\n }\n });\n });\n});\n\n// XXX see comment on Accounts.createUser in passwords_server about adding a\n// second \"server options\" argument.\nconst defaultCreateUserHook = (options, user) => {\n if (options.profile)\n user.profile = options.profile;\n return user;\n};\n\n// Validate new user's email or Google/Facebook/GitHub account's email\nfunction defaultValidateNewUserHook(user) {\n const domain = this._options.restrictCreationByEmailDomain;\n if (!domain) {\n return true;\n }\n\n let emailIsGood = false;\n if (user.emails && user.emails.length > 0) {\n emailIsGood = user.emails.reduce(\n (prev, email) => prev || this._testEmailDomain(email.address), false\n );\n } else if (user.services && Object.values(user.services).length > 0) {\n // Find any email of any service and check it\n emailIsGood = Object.values(user.services).reduce(\n (prev, service) => service.email && this._testEmailDomain(service.email),\n false,\n );\n }\n\n if (emailIsGood) {\n return true;\n }\n\n if (typeof domain === 'string') {\n throw new Meteor.Error(403, `@${domain} email required`);\n } else {\n throw new Meteor.Error(403, \"Email doesn't match the criteria.\");\n }\n}\n\nconst setupUsersCollection = users => {\n ///\n /// RESTRICTING WRITES TO USER OBJECTS\n ///\n users.allow({\n // clients can modify the profile field of their own document, and\n // nothing else.\n update: (userId, user, fields, modifier) => {\n // make sure it is our record\n if (user._id !== userId) {\n return false;\n }\n\n // user can only modify the 'profile' field. sets to multiple\n // sub-keys (eg profile.foo and profile.bar) are merged into entry\n // in the fields list.\n if (fields.length !== 1 || fields[0] !== 'profile') {\n return false;\n }\n\n return true;\n },\n fetch: ['_id'] // we only look at _id.\n });\n\n /// DEFAULT INDEXES ON USERS\n users._ensureIndex('username', {unique: 1, sparse: 1});\n users._ensureIndex('emails.address', {unique: 1, sparse: 1});\n users._ensureIndex('services.resume.loginTokens.hashedToken',\n {unique: 1, sparse: 1});\n users._ensureIndex('services.resume.loginTokens.token',\n {unique: 1, sparse: 1});\n // For taking care of logoutOtherClients calls that crashed before the\n // tokens were deleted.\n users._ensureIndex('services.resume.haveLoginTokensToDelete',\n { sparse: 1 });\n // For expiring login tokens\n users._ensureIndex(\"services.resume.loginTokens.when\", { sparse: 1 });\n // For expiring password tokens\n users._ensureIndex('services.password.reset.when', { sparse: 1 });\n};\n"]}