ãã°ããã®éãç§ã¯ã¹ã¿ãŒãã¢ããã§åãæ©äŒããããŸããã ããã¯ãšã³ãïŒããã³ããã³ããšã³ãïŒãšããŠãMeteor.jsã䜿çšããŸããã ããæç¹ã§ã2èŠçŽ èªèšŒãå®è£
ããå¿
èŠã«çŽé¢ããŸããã ãã®èšäºã§ã¯ãMeteor.jsã§ãã®æ©èœãå®è£
ããæ¹æ³ã«ã€ããŠã話ããããšæããŸãã
ã«ããã®äžã«ã¯ãåäžã®ã¹ã¯ãªãŒã³ã·ã§ãã/ç»åã¯ãããŸããããå®è£
ã«å¿
èŠãªãã¹ãŠã®ã³ãŒãã衚瀺ãããŸãã
ãšã³ããªãŒ
ç§ãã¡ã®å Žåã2çªç®ã®èŠå ã¯ãTwilioãä»ããŠéä¿¡ãããSMSã¡ãã»ãŒãžã®ã³ãŒãã§ããã ããªãã®å€ãã¯ãSMSã¡ãã»ãŒãžã®åœ¢åŒã®2çªç®ã®èŠçŽ ã¯ç¡é§ã§ãããæãã§ããããšãå«ã¶ã§ãããã ãã®TFAå®è£
ã§ã¯ã2çªç®ã®èŠçŽ ã䜿çšã§ããŸãã ç§ã®æèŠã§ã¯ãããããæŠç¥ãšããŠå
¬åŒåãïŒå¿
èŠã«å¿ããŠïŒãå¿
èŠã«å¿ããŠæ¥ç¶ããããšãçæ³çã§ãããç§ã¯ãããéæã§ããŸããã§ããã Meteor.jsãã©ãããã©ãŒã ã§ã®æ©èœã®å®è£
ã«ç¹ã«çŠç¹ãåœãŠãŸãã
æåã®èŠçŽ ã®å
¥åã«æåãããšãæéå¶éã®ããã»ãã·ã§ã³ãéãã2çªç®ã®èŠçŽ ãå
¥åããããšã§å®äºããå€å
žçãªã¢ãããŒããå®è£
ããŸããã
Meteor Accountsããã±ãŒãžã«ã¯èªèšŒãäžæåæ¢ããæ¹æ³ã¯ãããŸããããã³ãŒããçæããŠéä¿¡ãããŠãŒã¶ãŒã«å
¥åããæéãäžããããã«ããã®äžæåæ¢ãå¿
èŠã§ãã ãããã£ãŠãæšæºã®
Meteor.loginWithPasswordã¡ãœãããæŸæ£ããããã¥ã¡ã³ãã«ã¯ãªã
Meteor.loginWithTokenã¡ãœããã䜿çšãã
å¿
èŠããããŸãã ãã®ã¡ãœããã䜿çšãããšããŠãŒã¶ãŒã¯ãMongoDBã«æ¢ã«çæããã³ä¿åãããŠããããŒã¯ã³ã䜿çšããŠã·ã¹ãã ã§èªèšŒã§ããŸãã
è¡åæ¹é
æé ïŒ
- LoginProcedureãåŒã³åºãMeteorã¡ãœããã§èªèšŒããã»ã¹å
šäœã眮ãæããŸãã
- æåã®èŠçŽ ãšãã¹ãŠã®çš®é¡ã®ãã§ãã¯ã®æ€èšŒã
- 2çªç®ã®èŠçŽ ïŒã³ãŒãïŒãçæããTwilioã䜿çšããŠéä¿¡ããŸãããã®ã¹ãããã¯ã2çªç®ã®èŠçŽ ãšãã®é
ä¿¡ãçæããä»»æã®æ¹æ³ã«çœ®ãæããããšãã§ããŸãã
- ã³ãŒããšãã®ä»ã®ããŒã¿ãå¥åã®MongoDBã³ã¬ã¯ã·ã§ã³ã«ä¿åãããªãŒãã³èªèšŒã»ãã·ã§ã³ãä¿åããŸãã
- ã¯ã©ã€ã¢ã³ãããŠãŒã¶ãŒã«2çªç®ã®èŠçŽ ãå
¥åããããã«èŠæ±ããäžéçµæãè¿ããŸãã
- 2çªç®ã®èŠçŽ ã®åä¿¡ãšç¢ºèªã
- æ°ããããŒã¯ã³ãçæããã¯ã©ã€ã¢ã³ãã«è¿ããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ãåä¿¡ããããŒã¯ã³ã䜿çšããŠloginWithTokenãèªåçã«å®è¡ããŸãã
æé 1ã2
Meteorã¡ãœãããèªèšŒã«äœ¿çšããã®ã¯ç°¡åã§ããããŠãŒã¶ãŒãæšæºã®
loginWithPasswordã䜿çšã§ããªãããã«ããæ¹æ³ã¯ãããŸããïŒ
Accounts.validateLoginAttemptã¡ãœããããããåèªèšŒæäœããæ¿èªãããå¿
èŠããã
ãŸã ã åŒæ°ã¯ã
methodName屿§ãš
type屿§ã«é¢å¿ããã
詊è¡ãªããžã§ã¯ããååŸããŸãã
loginWithTokenã¡ãœããã®å Žå
ããããã®å±æ§ã«ã¯ãããã
ãã°ã€ã³å€ãš
åéå€ããããŸãã ãŸããé»åã¡ãŒã«ã§ã¢ã«ãŠã³ãã確èªãããã¹ã¯ãŒããå埩ããåŸãèªèšŒãèš±å¯ããå Žåã¯ã
methodNameã®è¿œå ã®å€ããæ¿èªãããå¿
èŠããããŸãã çµæã¯æ¬¡ã®ã¡ãœããã§ãã
Accounts.validateLoginAttempt(function(attempt){ var allowed = [ 'login', 'verifyEmail', 'resetPassword' ]; if (_.contains(allowed, attempt.methodName) && attempt.type == 'resume'){ return true; } return false; });
æ°ããããŒã¯ã³ãçæããããã®é¢æ°ãããã«èšè¿°ããŸãã ãããã®é¢æ°ã¯ãããã¥ã¡ã³ãã«å«ãŸããŠããªãããã€ãã®ã¡ãœããã䜿çšããŸãã ãããŠãããã«ã³ãŒãããããŸãïŒ
var generateLoginToken = function(){ var stampedToken = Accounts._generateStampedLoginToken(); return [ stampedToken, Accounts._hashStampedToken(stampedToken) ]; }; var saveLoginToken = function(userId){ return Meteor.wrapAsync(function(userId, tokens, cb){
Accounts._generateStampedLoginTokenã¡ãœããã¯ãå°æ¥
loginWithTokenã¡ãœãããå®è¡ããããã«ã¯ã©ã€ã¢ã³ãã«è¿ãããå¿
èŠãããæ°ããããŒã¯ã³ãè¿ããŸãã
Accounts._hashStampedTokenã¡ãœããã¯ããŒã¯ã³ãããã·ã¥ããMongoDBã«ä¿åããå¿
èŠãããã®ã¯ããã·ã¥åœ¢åŒã§ãã
Meteorã¡ãœããã«æ»ããŸãããã ãããŠãããã«ã³ãŒããšèª¬æããããŸãïŒ
Meteor.methods({ 'LoginProcedure': function(username, pswdDigest, code, hash){
ã芧ã®ãšãããããã¥ã¡ã³ãã«èšèŒãããŠããªãå¥ã®æ¹æ³ã
ãã¹ãŠã®èªèšŒãæåã§å®è¡ããããããã¹ã¯ãŒããæåã§ç¢ºèªããå¿
èŠããããŸãã åé¡ã¯ãMeteorãã©ã®ããã«ããããããã·ã¥ãããããããªãããšã§ãã ããã¯ãŸãã«
Accouts._checkPasswordã¡ãœããã®äœ¿çšç®çã§ãã åŒæ°ãšããŠãå
ã«MongoDBããååŸãããŠãŒã¶ãŒã¬ã³ãŒããããã³ãŠãŒã¶ãŒã®ãã¹ã¯ãŒãããã·ã¥ãšããã·ã¥ã¡ãœãããå«ãå¥ã®ãªããžã§ã¯ããåœŒã«æž¡ãããŸãã åžžã«sha-256ã§ãã
ããã·ã¥èªäœã¯ãMeteorã¡ãœãããåŒã³åºãåã«ã¯ã©ã€ã¢ã³ãåŽã§å®è¡ãããŸãã 䜿çšãããæšæºã®æ¹æ³ã¯
Package.sha.SHA256ïŒ ''ïŒã§ãã
ãŸããTFAãç¡å¹ãªå Žåã®ã¢ã¯ã·ã§ã³ã³ãŒã¹ã«ã€ããŠã説æããŸããæ°ããããŒã¯ã³ãçæããã¯ã©ã€ã¢ã³ãã«è¿ãã ãã§ããããã
Meteor.loginWithTokenãåŒã³åºãããŸãã
Meteorã¡ãœããã®åŒæ°ã®æ°ãæç¢ºã«ããã-åãã¡ãœããã䜿çšããŠãèªèšŒã»ãã·ã§ã³ãéããŠçµäºããŸãã
ããã·ã¥åŒæ°ã¯ããã§ã«éããŠããã»ãã·ã§ã³ã远跡ããããã®ãã®ã§ãã ãŠãŒã¶ãŒãèªèšŒã»ãã·ã§ã³ãéããŠãããã©ãŠã¶ãŒ/ã¿ããéããããã³ãŒããå«ãSMSãæ¢ã«éä¿¡ãããŠãããšããŸãã ãããŠã1åïŒã»ãã·ã§ã³ã®æå¹æéïŒä»¥å
ã«ã圌ã¯åã³èªèšŒã»ãã·ã§ã³ãéããSMSãå床éä¿¡ãããŸãã ããã¯ãéã®ç޿倱ã«ãªããŸãã ãããã£ãŠãïŒæåã®èŠçŽ ãæž¡ããåŸïŒãªãŒãã³ã»ãã·ã§ã³ã®å Žåãããã·ã¥ãäœæãããããã«æ¥ç¶ãããŠMongoDBã«ä¿åãããã¯ã©ã€ã¢ã³ãã«è¿ãããããã§localstorage / cookieã«ä¿åãããŸãã ãããŠãã¯ã©ã€ã¢ã³ãã¯åã³èµ·åãããšãããã®æéæšå®ã«åŸã£ãŠãæåŸã®èªèšŒã»ãã·ã§ã³ãçããŠãããã©ããããã§ãã¯ããŸãã çããŠããå Žåã圌ã¯ãã®ããã·ã¥ãæåã®èŠçŽ ïŒãŠãŒã¶ãŒåããã¹ã¯ãŒãïŒãšå
±ã«æ·»ä»ããŸãã ãŸããããŸããŸãªããã€ã¹ããTFAã»ãã·ã§ã³ãéãããšãã§ããŸãã ãã®ããã»ã¹ã«ã€ããŠã¯ã次ã®ã¹ãããã§è©³ãã説æããŸãã
ã¹ããã3-5
ãããã®æé ã«ã¯ã2çªç®ã®èŠçŽ èªäœãå«ãŸããŸãã
MongoDBã«ããªãŒãã³èªèšŒã»ãã·ã§ã³ãå«ãç¹å¥ãªã³ã¬ã¯ã·ã§ã³ãäœæããŸãããã
TwoFactorSessionsãšåŒã°ãããšã
ãŸã ã Meteorã®ãµãŒããŒåŽã§ã®ã¿å®çŸ©ããå¿
èŠããããŸãã
ãããŠãããã«ã³ãŒãããããŸãïŒ
Meteor.methods({ 'LoginProcedure': function(username, pswdDigest, code, hash){
ããã·ã¥åŒæ°ã䜿çšããã¡ãœããåŒã³åºããã¯ã©ã€ã¢ã³ãããå°çããå Žåãæ¢åã®ãªãŒãã³èªèšŒã»ãã·ã§ã³ãèŠã€ããããšããå¿
èŠããããŸãã ãããååšããå Žåã§ãããã®æå¹æéã確èªããå¿
èŠããããŸãïŒã¯ã©ã€ã¢ã³ãã¯äºæž¬äžèœã§ããããŸããŸãªåŒæ°ã䜿çšããŠã³ã³ãœãŒã«ããããŸããŸãªã¡ãœãããåŒã³åºããã£ã©ã¯ã¿ãŒãå¿
ãååšããŸãïŒã ãã¹ãŠãæ£åžžãªå Žåãã¯ã©ã€ã¢ã³ãã«2çªç®ã®èŠçŽ ãééããå¿
èŠãããããšãçè§£ãããŸãã
ããã·ã¥åŒæ°ããªããæåã®èŠçŽ ãæž¡ãããå Žåãã³ãŒãïŒ2çªç®ã®èŠçŽ ïŒãããã·ã¥ãçæããå¿
èŠãªãã®ããã¹ãŠä¿åããŠãã³ãŒãïŒ2çªç®ã®èŠçŽ ïŒãæäŸããŸãã ã芧ã®ãšãããç§ã®ããã·ã¥ã¯ãŸã£ããããã·ã¥ã§ã¯ãªããåãªãã¿ã€ã ã¹ã¿ã³ãã§ãã ãã¢ã³ã¹ãã¬ãŒã·ã§ã³ã«ã¯ååãªããã«æããŸããããããšãã°ãéããŠããã»ãã·ã§ã³ãããã€ã¹ã«ãã€ã³ãããããã«ããŒã¿ãé衚瀺ã«ã§ããå®å
šãªããã·ã¥ã䜿çšããããšãçŠæ¢ãã人ã¯ããŸããã
Twilioã䜿çšããã«ã¯ãå
¬åŒã®
twilio-nodeã¢ãžã¥ãŒã«ã䜿çšããŸããã Node.jsããMeteorã«ã¢ãžã¥ãŒã«ãæ¥ç¶ããã«ã¯ã䟿å©ãª
meteorhacksããã±ãŒãž
npmã䜿çšã§ããŸãã
Meteor.wrapAsyncã«ã泚æãæã䟡å€ã
ãããŸãã Meteorã«ç²ŸéããŠããå Žåã¯ããµãŒããŒåŽã®ãã¹ãŠã®éåæã¿ã¹ã¯ããã®æ¹æ³ã§ã©ããããå¿
èŠãããããšãããããŸãã
ãã®çµæãã¯ã©ã€ã¢ã³ãã«ããã·ã¥ãéä¿¡ãããéããŠããã»ãã·ã§ã³ãšã2çªç®ã®èŠçŽ ãå
¥åããããã®ãã©ãŒã ã衚瀺ããã³ãŒããããã«èå¥ãããŸãã
ãã¹ãŠãéåžžã«åçŽã§ãããç§ã¯åæããŸããåä»ã§ãã
ã¹ããã6ã7
次ã«ãã¯ã©ã€ã¢ã³ãåŽã«ã€ããŠèããŸãã
èªèšŒ
-signInã®ãã³ãã¬ãŒãããããšããŸãã ããã«ã¯ãæåã®èŠçŽ ã®ãã©ãŒã ãš2çªç®ã®èŠçŽ ã®ã¢ãŒãã«ãããã¢ãããããã
ïŒmodalã§èå¥ããããã¹ãŠã®ãã¹ããããèŠçŽ ã¯
ïŒmodal- <element name and role>ãšããŠèªèãããŸãã èŠããŠããããã«ãéããŠããã»ãã·ã§ã³ãèå¥ããããã®ããã·ã¥ã¯localstorage / cookieã«ä¿åããå¿
èŠããããããæ¬¡ã®ã³ãŒãã§ã¯
Storageãªããžã§ã¯ãã䜿çšããŸãã ããã¯äœããã®æœè±¡ãªããžã§ã¯ãã«ãªããããèªäœãå€ãé
眮ããå Žæã決å®ããŸãïŒäœ¿çšå¯èœãªå ŽåãlocalstorageãŸãã¯cookieïŒã ãããŠãããã«ã³ãŒãããããŸãïŒ
Template.signIn.events({ ... 'submit #signInForm': function(e) { e.preventDefault();
ã³ãŒãã«ã¯ã³ã¡ã³ãããããããããäœãèµ·ãã£ãŠããããæ³šææ·±ã説æããŠããŸãããããã§ã説æããŸãã
submit #signInFormã€ãã³ãã§ããã©ãŒã ã®å
容
ãèªã¿åãããã¹ã¯ãŒããããã·ã¥ããMeteorã¡ãœãããåŒã³åºããŸãããŸãã
ããã·ã¥ãèŠã€ãã£ãå Žåã¯éä¿¡ããŸãã 4ã€ã®åçãªãã·ã§ã³ã®ãããããåãåãäºå®ã§ãã
- 400-ã»ãã·ã§ã³ã¯æ€èšŒã«åæ ŒããŸããã§ããïŒttlãæéåãã§ãïŒãã¯ã©ã€ã¢ã³ãã¯ããã·ã¥ãæ¶å»ããå¿
èŠããããŸãã
- 200-æåã®èŠçŽ ãæž¡ããã2çªç®ã®èŠçŽ ããªã³ã«ãªã£ãŠããªããããèªèšŒå¯èœãªããŒã¯ã³ãå°çããŸããã
- 403-æ°ããã³ãŒãïŒ2çªç®ã®èŠçŽ ïŒãçæããã³éä¿¡ãããå
¥åçšã®ã¢ãŒãã«ãããã¢ããã衚瀺ãããŸãã
- 401-å€ãã³ãŒãïŒ2çªç®ã®èŠå ïŒã¯ãŸã ã¢ã¯ãã£ãã§ããæ®ãã®ã»ãã·ã§ã³ã®æå¹æéãšåãã³ãŒããå
¥åããå¿
èŠæ§ã衚瀺ãããããã¢ããã衚瀺ããŸãã
ã¢ãŒãã«ãŠã£ã³ããŠããã
clickïŒmodal-code-submitã€ãã³ãã«ãããåãMeteorã¡ãœãããåŒã³åºããŸãããã³ãŒãïŒ2çªç®ã®èŠçŽ ïŒãæž¡ããŸãã ãã®çµæã次ã®2ã€ã®åçã®ãããããåãåãããšãæåŸ
ããŠããŸãã
- 400-ã»ãã·ã§ã³ã¯ãã§ã«æå¹æéãåããŠããŸãããšã©ãŒã衚瀺ããlocalstorage / cookieã®ããã·ã¥ãã¯ãªã¢ããŸãã
- 200-2çªç®ã®èŠçŽ ãæ£åžžã«æž¡ãããŸããããšã©ãŒãåé¿ããããã«localstorage / cookieã®ããã·ã¥ãæ¶å»ããåä¿¡ããããŒã¯ã³ã§èªèšŒããŸãã
次ã«ããµãŒããŒåŽã§2çªç®ã®èŠçŽ ãã§ãã¯ãå®è£
ããå¿
èŠããããŸãã ãã®ã€ãã³ãã¯ãMeteorã¡ãœãããåŒã³åºããããšãã«4ã€ã®åŒæ°ãã¹ãŠãååšããããšãç¹åŸŽãšããŠããŸãã ãããŠãããã«ã³ãŒãããããŸãïŒ
Meteor.methods({ 'LoginProcedure': function(username, pswdDigest, code, hash){
Meteorã¡ãœãããåŒã³åºããšãã®4ã€ã®åŒæ°ã¯ãéããŠããTFAã»ãã·ã§ã³ãçµäºããããšããããšãæå³ããŸãã æåã«ç¢ºèªããããšã¯ããã®ãããªã»ãã·ã§ã³ãååšãããã©ããã§ãã MongoDBã®åçŽãªã¯ãšãªã
次ã«ãã»ãã·ã§ã³ãæ€èšŒããŸãã å°ãªããšãã以äžã確èªããå¿
èŠããããŸãã
- ãã®ã»ãã·ã§ã³ããã§ã«éããããŠãããã©ããã
- ttlã®æå¹æéãåããŠããŸããïŒ
- ã»ãã·ã§ã³ãéããããã®è©Šè¡åæ°ã確èªããŠãã ããã
- ã³ãŒãã¯äžèŽããŸããïŒ2çªç®ã®èŠå ïŒã
- ãŠãŒã¶ãŒãšã®ã»ãã·ã§ã³ã³ã³ãã©ã€ã¢ã³ã¹ã®è¿œå ãã§ãã¯ã
æ€èšŒãæåãããšãã»ãã·ã§ã³ã¯éãããããšèŠãªãããŸãã ãããã£ãŠãã»ãã·ã§ã³çµäºæéã远å ããããšã«ãããMongoDBã®ãšã³ããªãæŽæ°ããŸãã
次ã«ã以åã«å®çŸ©ããã颿°ã䜿çšããŠãŠãŒã¶ãŒã®æ°ããããŒã¯ã³ãçæããã¯ã©ã€ã¢ã³ãåŽã«éãè¿ããŸãã
ã¹ããã8
ãã®ã¹ãããã®ã³ãŒãã¯æåŸã®ã¹ãããã«å«ãŸããŠããŸãã ã¯ã©ã€ã¢ã³ãåŽã§ã¯ãããŒã¯ã³ãåä¿¡ãããšãããã«
Meteor.loginWithTokenã¡ãœãããåŒã³åºããŠèªèšŒã«æåããŸãã
ãããã«
å€ãã®APIã«ãšã£ãŠãMeteor.jsã¯ãè€éã§è€éãªæäœãè¡ãããšãã§ããªããããéããããå¶éãããŠããããã«èŠããå ŽåããããŸãã ãã ãããã®èšäºã§èª¬æããããã«ãæšæºããã±ãŒãžã«ã¯åãŸããªãããã«èŠããæ©èœãããæ·±ãèŠãŠå®è£
ã§ããŸãã
ãã¡ãããæãéèŠãªããšã¯ãå
¬åŒããã¥ã¡ã³ãã«èšèŒãããŠããªãé ã颿°ã䜿çšããªããã°ãªããªãã£ãããšã§ãã ãããã®æ©èœã¯èŠåãªãã«å€æŽãããå¯èœæ§ããããããå€ãã®äººãèŠåãåããŸãã ãããããããããªããã°ãTFAãå€ããå°ãªããéåžžã®åœ¢åŒã§å®è£
ããããšã¯å°é£ã§ãã å°ãªããšãå·çæç¹ã§ã¯ãåäžã®å®è£
ãèŠã€ããããšãã§ããŸããã§ããã