[
  {
    "comment": "create new account and login",
    "include": "new_account",
    "params": {
      "email": "user-multifactor_auth_registered@example.com"
    }
  },

  {
    "comment": "resend verification message for registration email",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts/verify",
      "entity": {
        "type": "email",
        "info": "user-multifactor_auth_registered@example.com"
      }
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox for email verification message for registration email",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/user-multifactor_auth_registered@example.com?action=verify"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'verify'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve email verification request for registration email",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    }
  },

  {
    "comment": "add second email to account policy",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "user-multifactor_auth@example.com"
      }
    }
  },

  {
    "comment": "look up account policy, check that email is not an authFactor and not verified",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 2"},
        {"condition": "!json.getAccountContacts()[1].authFactor()"},
        {"condition": "!json.getAccountContacts()[1].verified()"}
      ]
    }
  },

  {
    "comment": "set email to be required auth factor, fails because it is not verified",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "user-multifactor_auth@example.com",
        "authFactor": "required"
      }
    },
    "response": {
      "status": 422,
      "check": [
        {"condition": "json.has('err.contact.unverified')"}
      ]
    }
  },

  {
    "comment": "resend verification message for email",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts/verify",
      "entity": {
        "type": "email",
        "info": "user-multifactor_auth@example.com"
      }
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (1st) for email verification message",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/user-multifactor_auth@example.com?action=verify"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'verify'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve email verification request",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "look up account policy, check that email is not an authFactor and but IS now verified",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 2"},
        {"condition": "!json.getAccountContacts()[1].authFactor()"},
        {"condition": "json.getAccountContacts()[1].verified()"}
      ]
    }
  },

  {
    "comment": "set email to be required auth factor",
    "request": {
      "session": "userSession",
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "user-multifactor_auth@example.com",
        "authFactor": "required"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getType().name() == 'email'"},
        {"condition": "json.getAuthFactor().name() == 'required'"}
      ]
    }
  },

  {
    "comment": "re-read policy, verify email is now a required auth factor",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 2"},
        {"condition": "json.getAccountContacts()[1].requiredAuthFactor()"}
      ]
    }
  },

  {
    "comment": "log out (1st)",
    "request": { "uri": "auth/logout" }
  },

  {
    "comment": "new session, login (2nd) as user, receive MFA info",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "{{userAccount.name}}",
        "password": "foobar1!"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getMultifactorAuth() != null"},
        {"condition": "json.getMultifactorAuth().length == 1"},
        {"condition": "json.getMultifactorAuth()[0].getType().name() == 'email'"},
        {"condition": "json.getMultifactorAuth()[0].getInfo().indexOf('***') != -1"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (2nd), verify login request message sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/user-multifactor_auth@example.com?action=login"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'login'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve login request",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    },
    "response": {
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "add authenticator as required auth factor",
    "include": "add_authenticator",
    "params": {
      "userId": "{{userAccount.name}}",
      "authFactor": "required"
    }
  },

  {
    "comment": "re-read policy, both contacts are now required auth factors",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 3"},
        {"condition": "json.getAccountContacts()[1].requiredAuthFactor()"},
        {"condition": "json.getAccountContacts()[2].requiredAuthFactor()"}
      ]
    }
  },

  {
    "comment": "log out (2nd)",
    "request": { "uri": "auth/logout" }
  },

  {
    "comment": "new session, login (3rd) as user, receive MFA info",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "{{userAccount.name}}",
        "password": "foobar1!"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getMultifactorAuth() != null"},
        {"condition": "json.getMultifactorAuth().length == 2"},
        {"condition": "json.getMultifactorAuth()[0].getInfo().indexOf('***') != -1"},
        {"condition": "json.getMultifactorAuth()[1].getInfo() == '{\"masked\": true}'"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (3rd), verify login request message sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/user-multifactor_auth@example.com?action=login"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'login'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve email request, fails without TOTP token",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    },
    "response": {
      "status": 422,
      "check": [ {"condition": "json.has('err.totpToken.required')"} ]
    }
  },

  {
    "comment": "as user, approve email request with TOTP token, now logged in",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [
        {"name": "account", "value": "user-multifactor_auth_registered@example.com"},
        {"name": "totpToken", "value": "{{authenticator_token authenticator.totpKey}}"}
      ]
    },
    "response": {
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "remove email from contacts, fails because TOTP token is required",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts/email/user-multifactor_auth@example.com",
      "method": "delete"
    },
    "response": {
      "status": 422,
      "check": [
        {"condition": "json.has('err.totpToken.invalid')"}
      ]
    }
  },

  {
    "comment": "send TOTP token",
    "request": {
      "uri": "auth/authenticator",
      "entity": {
        "account": "{{userAccount.name}}",
        "token": "{{authenticator_token authenticator.totpKey}}",
        "authenticate": true
      }
    }
  },

  {
    "comment": "remove email from contacts after sending TOTP token, succeeds",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts/email/user-multifactor_auth@example.com",
      "method": "delete"
    },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 2"},
        {"condition": "json.getAccountContacts()[1].requiredAuthFactor()"}
      ]
    }
  },

  {
    "comment": "add SMS authentication as sufficient, fails because it is not verified",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "sms",
        "info": "US:800-555-1212",
        "authFactor": "sufficient"
      }
    },
    "response": {
      "status": 422,
      "check": [
        {"condition": "json.has('err.contact.unverified')"}
      ]
    }
  },

  {
    "comment": "add SMS authenticator as not_required, OK",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "sms",
        "info": "US:800-555-1212"
      }
    },
    "response": {
      "store": "smsContact",
      "check": [
        {"condition": "json.getType().name() == 'sms'"},
        {"condition": "json.getAuthFactor().name() == 'not_required'"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (4th) for sms verification message",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/sms/+18005551212?action=verify"
    },
    "response": {
      "store": "smsInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'verify'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve SMS verification request",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{smsInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "look up account policy, check that SMS is not an authFactor and but IS now verified",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 3"},
        {"condition": "json.getAccountContacts()[2].getType().name() == 'sms'"},
        {"condition": "!json.getAccountContacts()[2].authFactor()"},
        {"condition": "json.getAccountContacts()[2].verified()"}
      ]
    }
  },

  {
    "comment": "set sms to be sufficient auth factor",
    "request": {
      "session": "userSession",
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "sms",
        "info": "{{smsContact.info}}",
        "authFactor": "sufficient"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getType().name() == 'sms'"},
        {"condition": "json.getAuthFactor().name() == 'sufficient'"}
      ]
    }
  },


  {
    "comment": "log out (3nd)",
    "request": { "uri": "auth/logout" }
  },

  {
    "comment": "new session, login (4th) as user, receive MFA info",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "{{userAccount.name}}",
        "password": "foobar1!"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getMultifactorAuth() != null"},
        {"condition": "json.getMultifactorAuth().length == 2"},
        {"condition": "json.getMultifactorAuth()[0].getInfo() == '{\"masked\": true}'"},
        {"condition": "json.getMultifactorAuth()[1].getInfo().indexOf('***') != -1"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check SMS inbox (5th), verify login request message sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/sms/+18005551212?action=login"
    },
    "response": {
      "store": "smsInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'login'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "approve SMS request, not yet logged in because we have a required authenticator",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{smsInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    },
    "response": {
      "status": 422,
      "check": [ {"condition": "json.has('err.totpToken.required')"} ]
    }
  },

  {
    "comment": "approve SMS request with TOTP token, logged in",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{smsInbox.[0].ctx.confirmationToken}}",
      "entity": [
        {"name": "account", "value": "user-multifactor_auth_registered@example.com"},
        {"name": "totpToken", "value": "{{authenticator_token authenticator.totpKey}}"}
      ]
    },
    "response": {
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "send TOTP token prior to removing authenticator",
    "request": {
      "uri": "auth/authenticator",
      "entity": {
        "account": "{{userAccount.name}}",
        "token": "{{authenticator_token authenticator.totpKey}}",
        "authenticate": true
      }
    }
  },

  {
    "comment": "remove authenticator, only SMS remains as contact method",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts/authenticator",
      "method": "delete"
    },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 2"},
        {"condition": "json.getAccountContacts()[1].getType().name() == 'sms'"}
      ]
    }
  },

  {
    "comment": "add another email contact, sends another verify request",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "foo@example.com"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getType().name() == 'email'"},
        {"condition": "json.getInfo() == 'foo@example.com'"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (6th) for email verification message",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/foo@example.com?action=verify"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'verify'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, approve email verification request",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "update email contact, set authFactor to sufficient",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "foo@example.com",
        "authFactor": "sufficient"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getAuthFactor().name() == 'sufficient'"}
      ]
    }
  },

  {
    "comment": "log out (4nd)",
    "request": { "uri": "auth/logout" }
  },

  {
    "comment": "new session, login (5th) as user, receive MFA info",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "{{userAccount.name}}",
        "password": "foobar1!"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getMultifactorAuth() != null"},
        {"condition": "json.getMultifactorAuth().length == 2"},
        {"condition": "json.getMultifactorAuth()[0].getInfo().indexOf('***') != -1"},
        {"condition": "json.getMultifactorAuth()[1].getInfo().indexOf('***') != -1"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (7th), verify login request message sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/foo@example.com?type=request&action=login&target=account"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'login'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "approve via email, logged in",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{userInbox.[0].ctx.confirmationToken}}",
      "entity": [{"name": "account", "value": "user-multifactor_auth_registered@example.com"}]
    },
    "response": {
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "disable email MFA",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "foo@example.com",
        "authFactor": "not_required"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getType().name() == 'email'"},
        {"condition": "json.getAuthFactor().name() == 'not_required'"}
      ]
    }
  },

  {
    "comment": "disable sms MFA",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "sms",
        "info": "{{smsContact.info}}",
        "authFactor": "not_required"
      }
    },
    "response": {
      "check": [
        {"condition": "json.getType().name() == 'sms'"},
        {"condition": "json.getAuthFactor().name() == 'not_required'"}
      ]
    }
  },

  {
    "comment": "log out (5nd)",
    "request": { "uri": "auth/logout" }
  },

  {
    "comment": "new session, login (6th) as user, works fine with no MFA enabled",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "{{userAccount.name}}",
        "password": "foobar1!"
      }
    },
    "response": {
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "add a THIRD email contact, sends another verify request",
    "request": {
      "uri": "users/{{userAccount.name}}/policy/contacts",
      "entity": {
        "type": "email",
        "info": "bar@example.com"
      }
    },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getInfo() == 'bar@example.com'"},
        {"condition": "json.getType().name() == 'email'"}
      ]
    }
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check inbox (8th) for email verification message",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/bar@example.com?action=verify"
    },
    "response": {
      "store": "userInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'verify'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "as user, DENY email verification request",
    "request": {
      "session": "userSession",
      "uri": "auth/deny/{{userInbox.[0].ctx.confirmationToken}}",
      "method": "post"
    }
  },

  {
    "before": "sleep 1s",
    "comment": "look up account policy again, email that was denied has been removed",
    "request": { "uri": "users/{{userAccount.name}}/policy" },
    "response": {
      "store": "policy",
      "check": [
        {"condition": "json.getAccountContacts() != null"},
        {"condition": "json.getAccountContacts().length == 3"},
        {"condition": "!json.getAccountContacts()[1].getInfo().startsWith('bar')"},
        {"condition": "!json.getAccountContacts()[2].getInfo().startsWith('bar')"}
      ]
    }
  }
]