{"_id":"59f79e3c584eb200345cecc6","initVersion":null,"project":"59f79e3c584eb200345ceafc","user":{"_id":"54e4044e8ef7552300409dcb","username":"","name":"Sankaet Pathak"},"__v":0,"createdAt":"2015-05-20T00:23:15.772Z","changelog":[],"body":"Some of you have been asking questions about the best way to handle MFAs for bank logins so we thought we would write this blog post to aid the process.\n\nThe first step is pretty straightforward: post the online banking credentials and wait for the response.\n\nThe response can be one of three kinds:\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"1) No MFA\"\n}\n[/block]\nThis is the response when no MFA (multi-factor authentication) question is asked from the user. The response sends back the array of linked banks.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"banks\\\": [\\n        {\\n            \\\"account_class\\\": 1,\\n            \\\"account_number_string\\\": \\\"********6239\\\",\\n            \\\"account_type\\\": 1,\\n            \\\"address\\\": \\\"[]\\\",\\n            \\\"balance\\\": \\\"10.51\\\",\\n            \\\"bank_name\\\": \\\"Bank of America\\\",\\n            \\\"date\\\": \\\"2015-04-27T16:25:33.020610\\\",\\n            \\\"email\\\": \\\"[email protected]\\\",\\n            \\\"id\\\": 1737,\\n            \\\"is_buyer_default\\\": false,\\n            \\\"is_seller_default\\\": false,\\n            \\\"mfa_verifed\\\": false,\\n            \\\"name_on_account\\\": \\\"Test User\\\",\\n            \\\"nickname\\\": \\\"eBanking\\\",\\n            \\\"phone_number\\\": \\\"901-111-2222\\\",\\n            \\\"resource_uri\\\": \\\"/api/v2/bank/1737\\\",\\n            \\\"routing_number_string\\\": \\\"*******20\\\"\\n        }\\n    ],\\n    \\\"is_mfa\\\": false,\\n    \\\"success\\\": true\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNotice it says **\"is_mfa\": false**\n\nThis effectively means that the bank was linked with the user.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"2) Question based MFA\"\n}\n[/block]\nThis is the response when a bank returns an MFA (multi-factor authentication) in the form of a static question. This is the question the bank has asked the user beforehand. The response in this case looks as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\n   \\\"is_mfa\\\":true,\\n   \\\"response\\\":{\\n      \\\"access_token\\\":\\\"sometoken\\\",\\n      \\\"mfa\\\":[\\n         {\\n            \\\"question\\\":\\\"Some question from bank?\\\"\\n         }\\n      ],\\n      \\\"type\\\":\\\"questions\\\"\\n   },\\n   \\\"success\\\":true\\n   \\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNote that it says **\"is_mfa\":true** . Also note that it sends you the MFA type as well, which in this case is question based **\"type\":\"questions\"**\n\nThe response also has an access token [**\"access_token\":\"sometoken\"**] associated with this specific online bank account. This access_token is for one time use only and expires after the bank is linked.\n\nSupply access_token and user's response to this question in **bank/mfa** .\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"3) Code based MFA\"\n}\n[/block]\nThis is the response when a bank returns an MFA (multi-factor authentication) in the form of a dynamic code sent to either the user's email or cellphone. The bank expects the user to respond back to the code as the answer. The response in this case looks as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\n   \\\"is_mfa\\\":true,\\n   \\\"response\\\":{\\n      \\\"access_token\\\":\\\"test\\\",\\n      \\\"cookies\\\":\\\"\\\",\\n      \\\"form_extra\\\":\\\"\\\",\\n      \\\"mfa\\\":{\\n         \\\"message\\\":\\\"Code sent to [email protected]\\\"\\n      },\\n      \\\"type\\\":\\\"device\\\"\\n   },\\n   \\\"success\\\":true\\n   \\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nNote that it says **\"is_mfa\":true**. Also note that it sends you the MFA type as well, which in this case is question based **\"type\":\"device\"**.\n\nThe response also has an access token [**\"access_token\":\"sometoken\"**] associated with this specific online bank account. This access_token is for one time use only and expires after the bank is linked.\n\nSupply access_token and user's response to this question in **bank/mfa**.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Mapping Responses\"\n}\n[/block]\nThe question that arises is what is the best way to map these diverse responses?\n\nSo here is a snippet to map the responses:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"if (payload.success){\\n      if (payload.is_mfa){\\n            if (payload.type == \\\"questions\\\"){\\n                  #bank not linked yet, requires user to answer a question\\n                  print mfa[0].question\\n            }else{\\n                  #bank not linked yet, requires user to put in the code sent to their phone or email\\n                  print mfa.message\\n            }\\n      }else{\\n            print \\\"bank linked! You are good to go\\\"\\n      }\\n}\",\n      \"language\": \"python\"\n    }\n  ]\n}\n[/block]\nNext step is to either display to the user that the bank was linked, or if it wasn't, to collect the correct response from the user and respond back with the answer and the access_token in **bank/mfa**.\n\nIf another question is returned, follow the same steps.\n\nHope this helps!","slug":"banklogin-best-practices","title":"Best Practices: bank/login"}

Best Practices: bank/login


Some of you have been asking questions about the best way to handle MFAs for bank logins so we thought we would write this blog post to aid the process. The first step is pretty straightforward: post the online banking credentials and wait for the response. The response can be one of three kinds: [block:api-header] { "type": "basic", "title": "1) No MFA" } [/block] This is the response when no MFA (multi-factor authentication) question is asked from the user. The response sends back the array of linked banks. [block:code] { "codes": [ { "code": "{\n \"banks\": [\n {\n \"account_class\": 1,\n \"account_number_string\": \"********6239\",\n \"account_type\": 1,\n \"address\": \"[]\",\n \"balance\": \"10.51\",\n \"bank_name\": \"Bank of America\",\n \"date\": \"2015-04-27T16:25:33.020610\",\n \"email\": \"[email protected]\",\n \"id\": 1737,\n \"is_buyer_default\": false,\n \"is_seller_default\": false,\n \"mfa_verifed\": false,\n \"name_on_account\": \"Test User\",\n \"nickname\": \"eBanking\",\n \"phone_number\": \"901-111-2222\",\n \"resource_uri\": \"/api/v2/bank/1737\",\n \"routing_number_string\": \"*******20\"\n }\n ],\n \"is_mfa\": false,\n \"success\": true\n}", "language": "json" } ] } [/block] Notice it says **"is_mfa": false** This effectively means that the bank was linked with the user. [block:api-header] { "type": "basic", "title": "2) Question based MFA" } [/block] This is the response when a bank returns an MFA (multi-factor authentication) in the form of a static question. This is the question the bank has asked the user beforehand. The response in this case looks as follows: [block:code] { "codes": [ { "code": "{\n\n \"is_mfa\":true,\n \"response\":{\n \"access_token\":\"sometoken\",\n \"mfa\":[\n {\n \"question\":\"Some question from bank?\"\n }\n ],\n \"type\":\"questions\"\n },\n \"success\":true\n \n}", "language": "json" } ] } [/block] Note that it says **"is_mfa":true** . Also note that it sends you the MFA type as well, which in this case is question based **"type":"questions"** The response also has an access token [**"access_token":"sometoken"**] associated with this specific online bank account. This access_token is for one time use only and expires after the bank is linked. Supply access_token and user's response to this question in **bank/mfa** . [block:api-header] { "type": "basic", "title": "3) Code based MFA" } [/block] This is the response when a bank returns an MFA (multi-factor authentication) in the form of a dynamic code sent to either the user's email or cellphone. The bank expects the user to respond back to the code as the answer. The response in this case looks as follows: [block:code] { "codes": [ { "code": "{\n\n \"is_mfa\":true,\n \"response\":{\n \"access_token\":\"test\",\n \"cookies\":\"\",\n \"form_extra\":\"\",\n \"mfa\":{\n \"message\":\"Code sent to [email protected]\"\n },\n \"type\":\"device\"\n },\n \"success\":true\n \n}", "language": "json" } ] } [/block] Note that it says **"is_mfa":true**. Also note that it sends you the MFA type as well, which in this case is question based **"type":"device"**. The response also has an access token [**"access_token":"sometoken"**] associated with this specific online bank account. This access_token is for one time use only and expires after the bank is linked. Supply access_token and user's response to this question in **bank/mfa**. [block:api-header] { "type": "basic", "title": "Mapping Responses" } [/block] The question that arises is what is the best way to map these diverse responses? So here is a snippet to map the responses: [block:code] { "codes": [ { "code": "if (payload.success){\n if (payload.is_mfa){\n if (payload.type == \"questions\"){\n #bank not linked yet, requires user to answer a question\n print mfa[0].question\n }else{\n #bank not linked yet, requires user to put in the code sent to their phone or email\n print mfa.message\n }\n }else{\n print \"bank linked! You are good to go\"\n }\n}", "language": "python" } ] } [/block] Next step is to either display to the user that the bank was linked, or if it wasn't, to collect the correct response from the user and respond back with the answer and the access_token in **bank/mfa**. If another question is returned, follow the same steps. Hope this helps!