0

I'm testing some Ruby code that uses Mechanize under the covers. I found that when I pass a bad OAuth token in a request, Mechanize throws an unexpected exception.

I make my call with the bad token, and the call raises the following exception:

#<NoMethodError: undefined method `any?' for nil:NilClass>

I've got some additional analysis that I'll post as an answer, but if anyone has additional insight it would be appreciated.

I tried putting this question on the mechanize-users mailing list, but the moderator didn't post it.

Bruce
  • 8,202
  • 6
  • 37
  • 49
  • Is your question why does `nil.any?` raise that error? – pguardiario Oct 04 '12 at 06:27
  • My question is - why does Mechanize behave unexpectedly (raising an unrelated exception) when I send a request with a bad oauth token? Mechanize has all the information it needs to tell me the token is bad, but it raises this undefined method exception instead. I did some analysis, and my best guess is shown as the first answer below; but I'd really like to see someone actually familiar with the code to verify or correct. – Bruce Oct 04 '12 at 07:33
  • Who cares? It would probably be better if it raised a NoChallengesException, but you deal with it the same way, catch the error and handle it. – pguardiario Oct 04 '12 at 08:05
  • Because I'm testing a library on top of Mechanize, and when I get this exception I don't know if the library is buggy or if Mechanize is. I have to debug into Mechanize to figure out what is going on. Also, this exception doesn't give my test code access to the actual response with the detailed error info in the WWW-Authenticate header. – Bruce Oct 04 '12 at 12:22
  • I admit this is more of a bug report than a question - that's why I answered it myself - but since the moderator of the mechanize-users mailing list didn't accept my posting of this issue, this is the next-best way I know of to let the community know about this issue. – Bruce Oct 04 '12 at 12:24
  • Also note that the Mechanize home page (http://mechanize.rubyforge.org/) lists a bug reporting link (https://github.com/tenderlove/mechanize/issues) that just returns a 404. – Bruce Oct 04 '12 at 12:26

2 Answers2

1

If you look here you can see than Mechanize::HTTP::WWWAuthenticateParser#parse can return nil under certain conditions (line 83 as of this post) I'm not sure why this might be useful but there's your answer.

pguardiario
  • 53,827
  • 19
  • 119
  • 159
0

The initial response contains a WWW-AUTHENTICATE header with the error information:

response-header: www-authenticate => Bearer realm=api.att.com,error=invalid_token, error_description=the token is not valid

From my reading of the OAuth spec this is correct usage. However, tracing through the Mechanize code, I see that Mechanize assumes the WWW-AUTHENTICATE header will contain one or more challenges, describing how to retry the request with authentication. I specifically find myself at agent.rb:702 in #response_authenticate, where it checks for credentials with:

@auth_store.credentials?

And that method in turn calls #any? on a nil object, since it didn't manage to parse any challenges out of the header:

def credentials? uri, challenges
    challenges.any? do |challenge|
        credentials_for uri, challenge.realm_name
    end
end
Bruce
  • 8,202
  • 6
  • 37
  • 49