{"id":252713,"date":"2015-03-10T12:53:02","date_gmt":"2015-03-10T08:53:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=252713"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=252713","title":{"rendered":"\u0414\u0432\u0443\u0445-\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0432 Meteor.js"},"content":{"rendered":"<p> \t\t\t\u0412 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u043d\u0435 \u0434\u043e\u0432\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0440\u0442\u0430\u043f\u0435. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u044d\u043a-\u044d\u043d\u0434\u0430 (\u0438 \u0444\u0440\u043e\u043d\u0442-\u044d\u043d\u0434\u0430) \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 Meteor.js. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0432\u0443\u0445-\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0442 \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0438\u0447\u0443 \u0432 Meteor.js.<\/p>\n<p>  \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0432\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\/\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u0437\u0430\u0442\u043e \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0442\u043e\u0440\u044b\u043c \u0444\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u0431\u044b\u043b \u043a\u043e\u0434 \u0432 \u0441\u043c\u0441-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u043c \u0447\u0435\u0440\u0435\u0437 Twilio. \u041c\u043d\u043e\u0433\u0438\u0435 \u0438\u0437 \u0432\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0441\u043a\u043b\u0438\u0446\u0430\u0442\u044c, \u0447\u0442\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043c\u0441-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u2014 \u044d\u0442\u043e \u0440\u0430\u0441\u0442\u043e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u0433\u043b\u0443\u043f\u043e. \u042d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f TFA \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440. \u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0431\u044b\u043b\u043e \u0431\u044b \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0438\u0445 (\u0432\u0442\u043e\u0440\u044b\u0435 \u0444\u0430\u043a\u0442\u043e\u0440\u044b) \u043a\u0430\u043a \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043d\u043e \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u044f \u0442\u0430\u043a \u0438 \u043d\u0435 \u0434\u043e\u0431\u0440\u0430\u043b\u0441\u044f. \u0421\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0443\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 Meteor.js.<\/p>\n<p>  \u042f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u0432\u0432\u043e\u0434\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0435\u0441\u0441\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0432\u0432\u043e\u0434\u043e\u043c \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<p>  \u041f\u0430\u043a\u0435\u0442 Meteor Accounts \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u044d\u0442\u0430 \u043f\u0430\u0443\u0437\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0438 \u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0432\u0432\u043e\u0434. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <strong>Meteor.loginWithPassword<\/strong> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>Meteor.loginWithToken<\/strong>, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0443\u0436\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0432 MongoDB \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<h2>\u0425\u043e\u0434 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439<\/h2>\n<p>  \u041f\u043e \u0448\u0430\u0433\u0430\u043c:<\/p>\n<ol>\n<li>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0438\u043c Meteor \u043c\u0435\u0442\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u043e\u0432\u0435\u043c <strong>LoginProcedure<\/strong>;<\/li>\n<li>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u0432\u0441\u044f\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438;<\/li>\n<li>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u2014 \u043a\u043e\u0434, \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Twilio \u2014 \u044d\u0442\u043e\u0442 \u0448\u0430\u0433 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438;<\/li>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e MongoDB, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438;<\/li>\n<li>\u0412\u0435\u0440\u043d\u0435\u043c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432\u0432\u043e\u0434 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430;<\/li>\n<li>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430;<\/li>\n<li>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443;<\/li>\n<li>\u041a\u043b\u0438\u0435\u043d\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 <strong>loginWithToken<\/strong> \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u043c;<\/li>\n<\/ol>\n<h2>\u0428\u0430\u0433\u0438 1-2<\/h2>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 Meteor \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u043a\u0430\u043a \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <strong>loginWithPassword<\/strong>?<br \/>  \u0415\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>Accounts.validateLoginAttempt<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u00ab\u043e\u0434\u043e\u0431\u0440\u0438\u0442\u044c\u00bb \u043a\u0430\u0436\u0434\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0442\u0443\u0434\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 <strong>attempt<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <strong>methodName<\/strong> \u0438 <strong>type<\/strong>. \u0414\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u0430 <strong>loginWithToken<\/strong> \u044d\u0442\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <strong>login<\/strong> \u0438 <strong>resume<\/strong> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0418 \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043f\u043e e-mail \u0438 \u043f\u043e\u0441\u043b\u0435 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u044f, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u00ab\u043e\u0434\u043e\u0431\u0440\u0438\u0442\u044c\u00bb \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <strong>methodName<\/strong>. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">Accounts.validateLoginAttempt(function(attempt){     var allowed = [         'login',         'verifyEmail',         'resetPassword'     ];     if (_.contains(allowed, attempt.methodName) && attempt.type == 'resume'){         return true;     }     return false; }); <\/code><\/pre>\n<p>  \u0421\u0440\u0430\u0437\u0443 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430. \u042d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043d\u0435 \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0445 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e. \u0410 \u0432\u043e\u0442 \u0438 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">var generateLoginToken = function(){     var stampedToken = Accounts._generateStampedLoginToken();     return [         stampedToken,         Accounts._hashStampedToken(stampedToken)     ]; };  var saveLoginToken = function(userId){     return Meteor.wrapAsync(function(userId, tokens, cb){         \/\/ In tokens array first is stamped, second is hashed         \/\/ Save hashed to Mongo         Meteor.users.update(userId, {             $push: {                 'services.resume.loginTokens': tokens[1]             }         }, function(error){             if (error){                 cb(new Meteor.Error(500, 'Couldnt save login token into user profile'));             }else{                 \/\/ Return stamped to user                 cb && cb(null, [200,tokens[0].token]);             }         });     })(userId, generateLoginToken()); }; <\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 <strong>Accounts._generateStampedLoginToken<\/strong> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>loginWithToken<\/strong>. \u041c\u0435\u0442\u043e\u0434 <strong>Accounts._hashStampedToken<\/strong> \u0445\u044d\u0448\u0438\u0440\u0443\u0435\u0442 \u0442\u043e\u043a\u0435\u043d, \u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0445\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0432\u0438\u0434\u0435 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0432 MongoDB.<\/p>\n<p>  \u0421\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 Meteor \u043c\u0435\u0442\u043e\u0434\u0443. \u0410 \u0432\u043e\u0442 \u0438 \u043a\u043e\u0434, \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435:<\/p>\n<pre><code class=\"javascript\">Meteor.methods({     'LoginProcedure': function(username, pswdDigest, code, hash){         \/\/Here perform some checks         \/\/I'll leave it up to you         \/\/Something to prevent NoSQL-Injections etc.         ...         \/\/Now check if user already exists         var user = Meteor.users.findOne({             '$or': [             {                 'username': username             },             {                 'emails.address': username             }             ]         });         if (!user)             throw new Meteor.Error(404, 'fail');         \/\/Now password checks         \/\/Explanations about this are right after the code         var password = {digest: pswdDigest, algorithm: 'sha-256'};         var pswdCheck = Accounts._checkPassword(user, password);         if (pswdCheck.error)             throw new Meteor.Error(403,'fail');         \/\/Next check if two-factor is enabled         \/\/If it's not, just generate token and return it         \/\/Else start the procedure...         if (!user.twoFactorEnabled){             \/\/Use function defined above             return saveLoginToken(user._id);         }else{             \/\/Step 3-7             ...         }     } }); <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u0432\u0441\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0442\u043e \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u043e\u0436\u0435 \u043d\u0430\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0410 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c Meteor \u0438\u0445 \u0445\u044d\u0448\u0438\u0440\u0443\u0435\u0442. \u041a\u0430\u043a \u0440\u0430\u0437 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <strong>Accouts._checkPassword<\/strong>. \u041a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u043d\u0435\u0435 \u0438\u0437 MongoDB, \u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0445\u044d\u0448 \u043f\u0430\u0440\u043e\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434 \u0445\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042d\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 sha-256.<br \/>  \u0421\u0430\u043c\u043e \u0445\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c Meteor \u043c\u0435\u0442\u043e\u0434\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u2014 <strong>Package.sha.SHA256(&#8216;\u041f\u043f\u0410\u0430\u0440\u0420\u043e\u043b\u044c&#8217;)<\/strong>.<\/p>\n<p>  \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043d \u0445\u043e\u0434 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u0439 TFA \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442, \u0430 \u043e\u0442\u0442\u0443\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432 <strong>Meteor.loginWithToken<\/strong>.<\/p>\n<p>  \u0425\u043e\u0447\u0443 \u043f\u043e\u044f\u0441\u043d\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 Meteor \u043c\u0435\u0442\u043e\u0434\u0430 \u2014 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <strong>hash<\/strong> \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0443\u0436\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\/\u0432\u043a\u043b\u0430\u0434\u043a\u0443, \u043d\u043e \u0441\u043c\u0441 \u0441 \u043a\u043e\u0434\u043e\u043c \u0443\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e. \u0410 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043c\u0438\u043d\u0443\u0442\u044b (\u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0436\u0438\u0437\u043d\u0438 \u0441\u0435\u0441\u0441\u0438\u0438) \u043e\u043d \u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0441\u043d\u043e\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043c\u0441. \u042d\u0442\u043e \u0431\u044b\u043b\u0430 \u0431\u044b \u0447\u0438\u0441\u0442\u0430\u044f \u043f\u043e\u0442\u0435\u0440\u044f \u0434\u0435\u043d\u0435\u0433. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (\u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430) \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0445\u044d\u0448, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a \u043d\u0435\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d c \u043d\u0435\u0439 \u0432 MongoDB, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442, \u0430 \u0442\u0430\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u0432 localstorage\/cookie. \u0418, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437, \u043e\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 \u043f\u043e \u0441\u0432\u043e\u0438\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430\u043c, \u0436\u0438\u0432\u0430 \u043b\u0438 \u043f\u0440\u043e\u0448\u043b\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0415\u0441\u043b\u0438 \u0436\u0438\u0432\u0430, \u0442\u043e \u043e\u043d \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442 \u044d\u0442\u043e\u0442 \u0445\u044d\u0448 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0435\u0440\u0432\u044b\u043c \u0444\u0430\u043a\u0442\u043e\u0440\u043e\u043c (username, password). \u042d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u0438 TFA \u0441 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u041e\u0431 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0435\u0435 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0433\u0430\u0445.<\/p>\n<h2>\u0428\u0430\u0433\u0438 3-5<\/h2>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0441\u0430\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440.<br \/>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0432 MongoDB, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f <strong>TwoFactorSessions<\/strong>. \u041e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Meteor.<\/p>\n<p>  \u0410 \u0432\u043e\u0442 \u0438 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">Meteor.methods({     'LoginProcedure': function(username, pswdDigest, code, hash){         \/\/Steps 1-2         ...         if (!user.twoFactorEnabled){             \/\/Steps 1-2             ...         }else{             if (code && hash){                 \/\/Step 6-7                 ...             }else(hash){                 \/\/That part is for continuing previous session                 \/\/New code will not be sent, but client-side app                 \/\/will receive special response code and open the pop-up                 var session = TwoFactorSessions.findOne({                     hash: hash,                     username: username                 });                 if (session){                     \/\/Lets use some imaginary validation function                     \/\/that you will define by your own in your project                     validateSession(session, user);                     return [401, hash];                 }else{                     \/\/ Couldnt find, return error                     throw new Meteor.Error(404, 'No session');                 }             }else{                 \/\/Generated code, i'll leave it up to you                 var newCode = &lt;code here&gt;;                 \/\/The now date can be used as hash, just timestamp                 var now = new Date();                 var hash = +now;                 \/\/Save it to special collection for suspended sign-in processes                 TwoFactorSessions.insert({                     hash: hash,                     code: newCode,                     username: username,                     sent: now                 });                 \/\/ Wrap async task                 return Meteor.wrapAsync(function(user, hash, code, startTime, cb){                     \/\/ Send code using Twilio to the phone number of user                     Twilio.messages.create({                         to: user.phone,                         from: '+000000000000',                         body: 'Hi! Code - '+code                     }, function(error, message){                         if (error){                             \/\/ Return error with Twilio                             cb && cb(new Meteor.Error(500, 'Twilio error'));                         }else{                             \/\/ Return 403, saying that SMS has been sent                             \/\/ hash, which user will send to us with code to identify his TF session                             cb && cb(null, [403, hash]);                         }                     });                 })(user, hash, newCode, now);             }         }     } }); <\/code><\/pre>\n<p>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c hash, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043e\u0442\u043a\u0440\u044b\u0442\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u0430\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0435\u0451 \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 (\u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0435\u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0439\u0434\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0441 \u0441\u0430\u043c\u044b\u043c\u0438 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438). \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432\u0441\u0435 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0434\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0435\u0449\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0439\u0442\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 <strong>hash<\/strong> \u043d\u0435\u0442, \u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u043f\u0440\u043e\u0439\u0434\u0435\u043d, \u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440), \u0445\u044d\u0448, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0438 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440). \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u043e\u0439 \u0445\u044d\u0448 \u0432\u043e\u0432\u0441\u0435 \u043d\u0435 \u0445\u044d\u0448, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e timestamp. \u041c\u043d\u0435 \u044d\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439, \u043d\u043e \u0432\u0430\u043c \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0445\u044d\u0448, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0441\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u043a \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440.<\/p>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Twilio \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c <a href=\"https:\/\/twilio.github.io\/twilio-node\/\">twilio-node<\/a>. \u0414\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043e\u0442 Node.js \u043a Meteor \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/atmospherejs.com\/meteorhacks\/npm\">meteorhacks:npm<\/a>.<\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <strong>Meteor.wrapAsync<\/strong>. \u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 Meteor, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0432\u0441\u0435 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043d\u0430\u0434\u043e \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<p>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0445\u044d\u0448 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u043a\u043e\u0434, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043e\u043d \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442 \u0444\u043e\u0440\u043c\u0443 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<p>  \u0412\u0441\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e, \u0441\u043e\u0433\u043b\u0430\u0441\u0435\u043d, \u0441\u0443\u043c\u0431\u0443\u0440\u043d\u043e.<\/p>\n<h2>\u0428\u0430\u0433\u0438 6-7<\/h2>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430 \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f \u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435.<\/p>\n<p>  \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u2014 <strong>signIn<\/strong>. \u0412 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u0444\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043f-\u0430\u043f \u0434\u043b\u044f \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e <strong>#modal<\/strong>, \u0430 \u0432\u0441\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u0430\u043a <strong>#modal-&lt;\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0440\u043e\u043b\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430&gt;<\/strong>. \u041a\u0430\u043a \u0432\u044b \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0445\u044d\u0448 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 localstorage\/cookie, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043a\u043e\u0434\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <strong>Storage<\/strong>. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0430\u043c \u0440\u0435\u0448\u0438\u0442 \u043a\u0443\u0434\u0430 \u043a\u043b\u0430\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 (localstorage \u0438\u043b\u0438 cookie, \u043f\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438). \u0410 \u0432\u043e\u0442 \u0438 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">Template.signIn.events({     ...     'submit #signInForm': function(e) {         e.preventDefault();         \/\/Here go your methods for retreiving         \/\/username\/email and password         var username = ...;         var password = ...;         var pswdDigest = Package.sha.SHA256(password);         \/\/ Check if there is previous Two-Factor session         var sessionHash = Storage.get('two-factor-auth-hash');         if (sessionHash){             \/\/Validate it maybe?             \/\/We have additional value here, code expiration time             var valid = validateItHereAsYouWant();             if (!valid)                 sessionHash = null;         }         \/\/Now actual login procedure start         Meteor.call('LoginProcedure', username, pswdDigest, null, sessionHash, function(error, response){             if (error){                 if (error.error === 400){                     \/\/ That code would mean that session is invalid                     Storage.remove('two-factor-auth-hash');                     \/\/ Show some alerts here                 }             }else if (response[0]===200){                 \/\/ That response code would mean that                 \/\/ two-factor authentication is turned off                 \/\/ and client received new login token immediately                 \/\/ right after passing simple username\/password check                 Meteor.loginWithToken(response[1], function(err){                     if(err){                         alert('Problem!');                     }else{                         Router.go('Account');                     }                 });             }else if (response[0]===403){                 \/\/ That response code would mean that second factor code is sent                 \/\/ Open modal window with code input field                 $('#modal').modal();                 \/\/ Save hash into storage for continuation                 Storage.set('two-factor-auth-hash', response[1]);                 \/\/ Show alert saying the code was sent             }else if (response[0]===401){                 \/\/ Open modal window with code input field                 $('#modal').modal();                 \/\/ Show alert that there is previous code that awaits input             }         }     ...     'click #modal-code-submit': function(e){         e.preventDefault();         \/\/ Read the code, get the id hash         var code = $('#modal-code-input').val();         var hash = Storage.get('two-factor-auth-hash');         \/\/ Again get the values inside fields         \/\/ i mean username and password         ...         \/\/ Throught the net, only the digest should go         var pswdDigest = Package.sha.SHA256(pswd);         \/\/ Perform login again, but with code and id hash         Meteor.call('LoginProcedure', username, pswdDigest, code, hash, function(error, response){             if (error){                 if (error.error === 400){                     \/\/ That error code would mean that session is invalid                     Storage.remove('two-factor-auth-hash');                     Storage.remove('two-factor-auth-ttl');                     $('#modal').modal('toggle');                     \/\/ Show some error alerts                 }             }else if (response[0]===200){                 \/\/ Seems like ok, login token received                 Storage.remove('two-factor-auth-hash');                 \/\/ Login                 Meteor.loginWithToken(response[1]);             }         });     } }); <\/code><\/pre>\n<p>  \u0412 \u043a\u043e\u0434\u0435 \u043f\u043e\u043b\u043d\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432, \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435, \u043d\u043e \u0432\u0441\u0435 \u0436\u0435 \u043f\u043e\u044f\u0441\u043d\u044e.<\/p>\n<p>  \u041f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e <strong>submit #signInForm<\/strong> \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0444\u043e\u0440\u043c\u044b, \u0445\u044d\u0448\u0438\u0440\u0443\u0435\u043c \u043f\u0430\u0440\u043e\u043b\u044c \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c Meteor method, \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044f <strong>hash<\/strong>, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0430\u0439\u0434\u0435\u043d. \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 4\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0442\u0432\u0435\u0442\u0430:<\/p>\n<ol>\n<li><strong>400<\/strong> \u2014 \u0441\u0435\u0441\u0441\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e (ttl \u0438\u0441\u0442\u0435\u043a), \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0442\u0435\u0440\u0435\u0442\u044c \u0441\u0432\u043e\u0439 hash;<\/li>\n<li><strong>200<\/strong> \u2014 \u043f\u0435\u0440\u0432\u044b\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u043f\u0440\u043e\u0439\u0434\u0435\u043d, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d, \u0437\u043d\u0430\u0447\u0438\u0442 \u043f\u0440\u0438\u0448\u0435\u043b \u0442\u043e\u043a\u0435\u043d, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f;<\/li>\n<li><strong>403<\/strong> \u2014 \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440) \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043f-\u0430\u043f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430;<\/li>\n<li><strong>401<\/strong> \u2014 \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440) \u0435\u0449\u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043f-\u0430\u043f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0432\u0435\u0441\u0442\u0438 \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u0434.<\/li>\n<\/ol>\n<p>  \u0418\u0437 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e <strong>click #modal-code-submit<\/strong> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u043e\u0442 \u0436\u0435 Meteor method, \u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0435\u0449\u0435 \u0438 \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440). \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0434\u0432\u0443\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432:  <\/p>\n<ol>\n<li><strong>400<\/strong> \u2014 \u0441\u0435\u0441\u0441\u0438\u044f \u0443\u0436\u0435 \u0438\u0441\u0442\u0435\u043a\u043b\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438, \u0447\u0438\u0441\u0442\u0438\u043c <strong>hash<\/strong> \u0432 localstorage\/cookie;<\/li>\n<li><strong>200<\/strong> \u2014 \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0439\u0434\u0435\u043d, \u0447\u0438\u0441\u0442\u0438\u043c <strong>hash<\/strong> \u0432 localstorage\/cookie \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u043a, \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u043c.<\/li>\n<\/ol>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435. \u042d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435\u043c \u0432\u0441\u0435\u0445 4\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 Meteor \u043c\u0435\u0442\u043e\u0434\u0430. \u0410 \u0432\u043e\u0442 \u0438 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">Meteor.methods({     'LoginProcedure': function(username, pswdDigest, code, hash){         \/\/Steps 1-2         ...         if (!user.twoFactorEnabled){             \/\/Steps 1-2             ...         }else{             if (code && hash){                 \/\/All 4 arguments present here                 \/\/First factor has already been passed since we're here                 \/\/Process second factor                 var session = TwoFactorSessions.findOne({                     hash: hash,                     username: username                 });                 if (session){                     \/\/Lets use some imaginary validation function                     \/\/that you will define by your own in your project                     validateSession(session, user, code);                     \/\/ Passed all checks                     \/\/ Update two-factor session with submitted date                     TwoFactorSessions.update({                         hash: hash                     }, {                         $set: {                             submitted: new Date()                         }                     });                     \/\/ Generate and save login token using                      \/\/ previously defined function (look for it in steps 1-2)                     return saveLoginToken(user._id);                 }else{                     \/\/ Couldnt find, return error                     throw new Meteor.Error(404, 'twoFactor.invalidHash');                 }             }else(hash){                 \/\/Step 3-5                 ...             }else{                 \/\/Step 3-5                   ...             }         }     } }); <\/code><\/pre>\n<p>  4 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 Meteor \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e TFA. \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0442\u0430\u043a\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f. \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 MongoDB.<\/p>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e. \u041a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\u041d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0430 \u043b\u0438 \u0443\u0436\u0435 \u044d\u0442\u0430 \u0441\u0435\u0441\u0441\u0438\u044f;<\/li>\n<li>\u041d\u0435 \u0438\u0441\u0442\u0435\u043a \u043b\u0438 ttl;<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u044e;<\/li>\n<li>\u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u043a\u043e\u0434 (\u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u043a\u0442\u043e\u0440);<\/li>\n<li>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/li>\n<\/ul>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0441\u0435\u0441\u0441\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 MongoDB, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0441\u0435\u0441\u0441\u0438\u0438.<br \/>  \u0417\u0430\u0442\u0435\u043c, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443.<\/p>\n<h2>\u0428\u0430\u0433 8<\/h2>\n<p>  \u041a\u043e\u0434 \u044d\u0442\u043e\u0433\u043e \u0448\u0430\u0433\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0448\u0430\u0433\u0435. \u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430, \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <strong>Meteor.loginWithToken<\/strong> \u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c\u0441\u044f.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  \u0414\u043b\u044f \u043c\u043d\u043e\u0433\u0438\u0445 API Meteor.js \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043c\u043a\u043d\u0443\u0442\u044b\u043c, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c, \u0431\u0435\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0438 \u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u043e\u0435. \u041d\u043e, \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0433\u043b\u0443\u0431\u0436\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0440\u043e\u0434\u0435 \u0438 \u043d\u0435 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b.<\/p>\n<p>  \u0421\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u044b\u0442\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041c\u043d\u043e\u0433\u0438\u0445 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u043e\u0440\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f. \u041d\u043e \u0431\u0435\u0437 \u043d\u0438\u0445 \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u043b\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c TFA \u0432 \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043d\u0435\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0438\u0434\u0435. \u041f\u043e-\u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438, \u044f \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \t\t\t<\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/252593\/\"> http:\/\/habrahabr.ru\/post\/252593\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p> \t\t\t\u0412 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u043d\u0435 \u0434\u043e\u0432\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0440\u0442\u0430\u043f\u0435. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u044d\u043a-\u044d\u043d\u0434\u0430 (\u0438 \u0444\u0440\u043e\u043d\u0442-\u044d\u043d\u0434\u0430) \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 Meteor.js. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0432\u0443\u0445-\u0444\u0430\u043a\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0442 \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0438\u0447\u0443 \u0432 Meteor.js.<\/p>\n<p>  \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0432\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\/\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u0437\u0430\u0442\u043e \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0435\u0441\u044c \u043a\u043e\u0434, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-252713","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/252713","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=252713"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/252713\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=252713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=252713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=252713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}