cloocher/aggcat

Errors when using account_confirmation method when presented with challenges

Closed this issue · 2 comments

I was working with your gem and running some tests against my Intuit dev account. I was receiving this error:

failed to make API call - undefined method split' for :challengesessionid:Symbol, retrying /Users/clark/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/net/http.rb:1590:incapitalize': undefined method `split' for :challengesessionid:Symbol (NoMethodError)

It turned out that changing the challenge headers to this fixed the problem:
headers = {'challengeSessionId' => challenge_session_id, 'challengeNodeId' => challenge_node_id}

The second problem I noticed was that Intuit's own documentation on the namespace naming had typos in it, and thus coding to their exact specs didn't work. I modified the challenge_answer method to the following, and I was able to run the test using "tfa_text" as username to get MFA login working:

def challenge_answer(answer)
xml = Builder::XmlMarkup.new
xml.InstitutionLogin('xmlns' => LOGIN_NAMESPACE) do |login|
login.challengeResponses do |challenge|
challenge.response(answer, 'xmlns' => CHALLENGE_NAMESPACE)
end
end
end

Lastly, I need to figure out how to get the other MFA types working (tfa_text2, tfa_choice). My thoughts are to make challenge_answer take in an answer array depending on the number of challenge questions presented.

Just wondering if you ran into these problems yet. I can send a pull request with my changes to client.rb.

I didn't get around to test challenge questions yet. I've added your changes to (1) and (2). Need to look more into (3). Please send me your pull request.

I created pull request #3. Here are the changes to client.rb:

def challenge_answer(answers)
      xml = Builder::XmlMarkup.new
      xml.InstitutionLogin('xmlns' => LOGIN_NAMESPACE) do |login|
        login.challengeResponses do |challenge|
          if answers.respond_to?('each')
            answers.each { |answer| challenge.response(answer, 'xmlns' => CHALLENGE_NAMESPACE) }
          else
            challenge.response(answers, 'xmlns' => CHALLENGE_NAMESPACE)
          end
        end
      end
    end

def account_confirmation(institution_id, challenge_session_id, challenge_node_id, answers)
      validate(institution_id: institution_id, challenge_node_id: challenge_session_id, challenge_node_id: challenge_node_id, answers: answers)
      headers = {'challengeSessionId' => challenge_session_id, 'challengeNodeId' => challenge_node_id}
      post("/institutions/#{institution_id}/logins", challenge_answer(answers), headers)
    end

def update_login_confirmation(login_id, challenge_session_id, challenge_node_id, answers)
      validate(login_id: login_id, challenge_node_id: challenge_session_id, challenge_node_id: challenge_node_id, answers: answers)
      headers = {'challengeSessionId' => challenge_session_id, 'challengeNodeId' => challenge_node_id}
      put("/logins/#{login_id}?refresh=true", challenge_answer(answers), headers)
    end

I was able to live test the following login cases on Intuit:

#tfa_direct - no challenge necessary
#tfa_text - {:challenges=>{:challenge=>{:text=>"Enter your first pet's name:"}}}
#tfa_text2 - {:challenges=>{:challenge=>[{:text=>"Enter your first pet's name:"}, {:text=>"Enter your high school's name:"}]}}
#tfa_choice - :challenges=>{:challenge=>{:text=>"Which high school did you attend?", :choice=>[{:text=>"Washington", :val=>"Washington"}, {:text=>"Jefferson", :val=>"Jefferson"}, {:text=>"Wilson", :val=>"Wilson"}, {:text=>"loop", :val=>"loop"}, {:text=>"Fail", :val=>"fail"}]}}}
#tfa_image - {:challenges=>{:challenge=>{:text=>"Enter the word in the dynamic image below", :image=>"/9j/4AAQSkZJRgABAQEAYABgA..."}}}
#tfa_dynamic_image - {:challenges=>{:challenge=>{:text=>"Enter the word in the dynamic image below", :image=>"/9j/4AAQS..."}}}