Bug 64267 - when preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge
Summary: when preemptive auth is disabled HTTP Sampler does not automatically respond ...
Status: NEEDINFO
Alias: None
Product: JMeter
Classification: Unclassified
Component: HTTP (show other bugs)
Version: 5.2.1
Hardware: All All
: P2 regression (vote)
Target Milestone: JMETER_5.3.0
Assignee: JMeter issues mailing list
URL:
Keywords: FixedInTrunk
Depends on:
Blocks:
 
Reported: 2020-03-26 01:21 UTC by Peter Lynch
Modified: 2020-05-10 12:34 UTC (History)
1 user (show)



Attachments
reproduce test case (4.58 KB, application/xml)
2020-03-26 01:21 UTC, Peter Lynch
Details
log from running reproduce case with log level DEBUG (59.72 KB, text/plain)
2020-03-26 01:22 UTC, Peter Lynch
Details
log file proof that jmeter version 3.3 did what I expected (35.60 KB, text/plain)
2020-03-26 01:52 UTC, Peter Lynch
Details
Fix non-preemptive authentication for http sampler (6.92 KB, patch)
2020-05-09 09:19 UTC, Felix Schumacher
Details | Diff
Try harder to match even partial URLs from AuthManager (2.17 KB, patch)
2020-05-10 12:34 UTC, Felix Schumacher
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Lynch 2020-03-26 01:21:36 UTC
Created attachment 37121 [details]
reproduce test case

This page: https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Authorization_Manager

States:

"The HttpComponents (HC 4.5.X) implementation defaults to pre-emptive since 3.2 and the header will be shown. To disable this, set the values as below, in which case authentication will only be performed in response to a challenge.

In the file jmeter.properties set httpclient4.auth.preemptive=false
"

This statement suggests to me that when the property is set to false, that the HTTP sampler using HC will automatically respond to an auth challenge if it has access to an HTTP Authorization Manager with appropriate credentials.

The attached test case and jmeter.log suggests this is not the case. I added a Response Assertion with Ignore Status enabled checking for a 200 response code. The assertion fails because 401 is received and the logs show no challenge response is automatically sent.

Expected:

When httpclient4.auth.preemptive=false and HC HTTP Sampler is used, then HTTP sampler should automatically respond to an Auth challenge if credentials are present via an HTTP Authorization Manager. Subsequently a response assertion testing for status code, should be able to test against the response code of the second request sent by the sampler with its credentials - instead of the first response challenge (401).

I realize there might be use cases the verify a challenge response code/headers/etc. and I don't wish to remove that ability. But I do believe the automatic challenge request by the HTTP Sampler also worked at one point in jmeter history, thus I filed this as bug, not enhancement.
Comment 1 Peter Lynch 2020-03-26 01:22:34 UTC
Created attachment 37122 [details]
log from running reproduce case with log level DEBUG
Comment 2 Peter Lynch 2020-03-26 01:52:29 UTC
Created attachment 37123 [details]
log file proof that jmeter version 3.3 did what I expected

Looks like a regression to me - or a deliberate change that was not documented.
Comment 3 Philippe Mouawad 2020-04-27 11:52:01 UTC
It would be an enhancement not a regression.
JMeter has never in the past handled Basic Auth the way you suggest it.
Comment 4 Peter Lynch 2020-05-01 13:21:42 UTC
(In reply to Philippe Mouawad from comment #3)
> It would be an enhancement not a regression.
> JMeter has never in the past handled Basic Auth the way you suggest it.

I don't understand your claim.

How do you explain what jmeter 3.3 did? https://bz.apache.org/bugzilla/attachment.cgi?id=37123

And how do you explain the documentation contradicting the behaviour?
Comment 5 Philippe Mouawad 2020-05-01 13:40:18 UTC
(In reply to Peter Lynch from comment #4)
> (In reply to Philippe Mouawad from comment #3)
> > It would be an enhancement not a regression.
> > JMeter has never in the past handled Basic Auth the way you suggest it.
> 
> I don't understand your claim.
> 
> How do you explain what jmeter 3.3 did?
> https://bz.apache.org/bugzilla/attachment.cgi?id=37123

Can you clarify ?
> 
> And how do you explain the documentation contradicting the behaviour?

Which documentation ? Can you point me to it please ?
Comment 6 Peter Lynch 2020-05-01 16:12:02 UTC
(In reply to Philippe Mouawad from comment #5)
> (In reply to Peter Lynch from comment #4)
> > (In reply to Philippe Mouawad from comment #3)
> > > It would be an enhancement not a regression.
> > > JMeter has never in the past handled Basic Auth the way you suggest it.
> > 
> > I don't understand your claim.
> > 
> > How do you explain what jmeter 3.3 did?
> > https://bz.apache.org/bugzilla/attachment.cgi?id=37123
> 
> Can you clarify ?

The following logging extracted from the attachments on this bug.

======= JMeter 3.3

jmeter 3.3 request made:
2020-03-25 22:47:33,036 DEBUG o.a.j.p.h.s.JMeterClientConnectionOperator$JMeterDefaultClientConnection: Sending request: GET /basic-auth/user/passwd HTTP/1.1

jmeter 3.3 response challenged:
2020-03-25 22:47:33,072 DEBUG o.a.h.headers: << HTTP/1.1 401 UNAUTHORIZED
2020-03-25 22:47:33,072 DEBUG o.a.h.headers: << WWW-Authenticate: Basic realm="Fake Realm"

jmeter 3.3 httpclient replies to challenge:
2020-03-25 22:47:33,073 DEBUG o.a.j.p.h.s.HTTPHC4Impl$6: Selected authentication options: [BASIC [complete=true]]
2020-03-25 22:47:33,074 DEBUG o.a.h.c.p.RequestTargetAuthentication: Generating response to an authentication challenge using basic scheme
2020-03-25 22:47:33,075 DEBUG o.a.h.headers: >> User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_231)
2020-03-25 22:47:33,075 DEBUG o.a.h.headers: >> Authorization: Basic dXNlcjpwYXNzd2Q=

jmeter 3.3 remote confirms with success
2020-03-25 22:47:33,112 DEBUG o.a.h.headers: << HTTP/1.1 200 OK

jmeter asserts a successful response:
2020-03-25 22:47:33,114 DEBUG o.a.j.a.ResponseAssertion: Passed: 200

============= JMeter 5


jmeter 5 request made:
2020-03-25 21:51:10,934 DEBUG o.a.h.i.e.MainClientExec: Executing request GET /basic-auth/user/passwd HTTP/1.1

jmeter 5 response challenge:
2020-03-25 21:51:10,975 DEBUG o.a.h.headers: http-outgoing-0 << HTTP/1.1 401 UNAUTHORIZED
2020-03-25 21:51:10,975 DEBUG o.a.h.headers: http-outgoing-0 << WWW-Authenticate: Basic realm="Fake Realm"

jmeter 5 HttpClient, knows it was challenged
2020-03-25 21:51:10,978 DEBUG o.a.h.i.a.HttpAuthenticator: httpbin.org:443 requested authentication
2020-03-25 21:51:10,979 DEBUG o.a.h.i.c.TargetAuthenticationStrategy: Authentication schemes in the order of preference: [Negotiate, Kerberos, NTLM, CredSSP, Digest, Basic]

jmeter 5 rather than responding to challenge, httpclient releases the connection back to pool:
2020-03-25 21:51:10,985 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager: Connection [id: 0][route: {s}->https://httpbin.org:443][state: Thread Group 1-1] can be kept alive indefinitely
2020-03-25 21:51:10,985 DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection: http-outgoing-0: set socket timeout to 0
2020-03-25 21:51:10,985 DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager: Connection released: [id: 0][route: {s}->https://httpbin.org:443][state: Thread Group 1-1][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]

jmeter response assertion fails immediately on 401 status code, instead of sending the expected challenge answer:
2020-03-25 21:51:10,989 DEBUG o.a.j.a.ResponseAssertion: Failed: 200


> > 
> > And how do you explain the documentation contradicting the behaviour?
> 
> Which documentation ? Can you point me to it please ?

Are you not seeing the opening comments of this report? Are you not looking at the attachments?

This page: https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Authorization_Manager
Comment 7 Felix Schumacher 2020-05-09 09:19:20 UTC
Created attachment 37220 [details]
Fix non-preemptive authentication for http sampler

Somehow the "normal" way for authentication for Basic Auth seems to got lost and no one (well apart from you) has noticed it.

The attached patch fixes the issue (at least on my machine :) ), but I am a bit unsure, whether this is the right way to fix it. I had to put my hand deep into some foreign classes, to get the authorization right.

But it would be nice, if you could try the patch on your side and report back, if it fixes your problem.
Comment 8 Philippe Mouawad 2020-05-09 17:00:15 UTC
(In reply to Felix Schumacher from comment #7)
> Created attachment 37220 [details]
> Fix non-preemptive authentication for http sampler
> 
> Somehow the "normal" way for authentication for Basic Auth seems to got lost
> and no one (well apart from you) has noticed it.
> 
> The attached patch fixes the issue (at least on my machine :) ), but I am a
> bit unsure, whether this is the right way to fix it. I had to put my hand
> deep into some foreign classes, to get the authorization right.
> 
> But it would be nice, if you could try the patch on your side and report
> back, if it fixes your problem.

Hello Felix,
Patch looks good to me.
What do you dislike about it ?
Thanks
Comment 9 Felix Schumacher 2020-05-09 17:24:44 UTC
I dislike about the patch
 * that I proxy authentication and website authentication is torn apart and a bit duplicated
 * that it replicates functionality of AuthManager
 * that I didn't write tests first ;)

But I will commit it, as release time is near and a fix is a fix.
Comment 10 Felix Schumacher 2020-05-09 17:57:37 UTC
Peter, thanks for your bug report and the detailed information. It would be nice, if you could test the next nightly and report back, whether your issue is fixed.

commit 740a2066b01f5a0ad6633bb9b617022918d37d65
AuthorDate: Sat May 9 11:55:31 2020 +0200

    When preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge
    
    Bugzilla Id: 64267
---
 .../jmeter/protocol/http/sampler/HTTPHC4Impl.java  | 86 +++++++++++++++++++++-
 xdocs/changes.xml                                  |  1 +
 2 files changed, 85 insertions(+), 2 deletions(-)
Comment 11 Peter Lynch 2020-05-10 12:04:51 UTC
Thanks for trying to fix this.

I tried latest snapshot with the test case attached to this bug report.

Initially it didn't work - looks like this was the logged cause:

2020-05-10 08:13:49,560 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Invalid URL http in authManager

I have "http" as the Base URL in HTTP Authorization Manager - which I believe is a valid value according to the HTTP Authorization manager docs, but the patched code rejects it:

https://github.com/apache/jmeter/commit/740a2066b01f5a0ad6633bb9b617022918d37d65#diff-98b4f752302231261a91b5c0ee96ea9dR264

Once I changed the Base URL value in the HTTP Authorization Manager to a parseable URL object (https://httpbin.org) , then the test case passes.

So while the specific problem seems to have been improved - I am concerned the new patch makes the incorrect assumption that the Authorization.getURL() method returns a proper URL in all cases. This would change the semantics used to match Base URL for Auth documented for the the HTTP Authorization Manager. 

https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Authorization_Manager

states "Base URL" contains "A partial or complete URL".

So it seems the patch would need to use similar startsWith matching logic as in https://github.com/apache/jmeter/blob/b6d11d79d905d0c099732bb928d2372fd1388981/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/AuthManager.java#L265 

I did not perform any other auth related tests given he above noted issue.
Comment 12 Felix Schumacher 2020-05-10 12:25:40 UTC
(In reply to Peter Lynch from comment #11)
> Thanks for trying to fix this.
> 
> I tried latest snapshot with the test case attached to this bug report.
> 
> Initially it didn't work - looks like this was the logged cause:
> 
> 2020-05-10 08:13:49,560 DEBUG o.a.j.p.h.s.HTTPHC4Impl: Invalid URL http in
> authManager
> 
> I have "http" as the Base URL in HTTP Authorization Manager - which I
> believe is a valid value according to the HTTP Authorization manager docs,
> but the patched code rejects it:
> 
> https://github.com/apache/jmeter/commit/
> 740a2066b01f5a0ad6633bb9b617022918d37d65#diff-
> 98b4f752302231261a91b5c0ee96ea9dR264 
> 
> Once I changed the Base URL value in the HTTP Authorization Manager to a
> parseable URL object (https://httpbin.org) , then the test case passes.
> 
> So while the specific problem seems to have been improved - I am concerned
> the new patch makes the incorrect assumption that the Authorization.getURL()
> method returns a proper URL in all cases. This would change the semantics
> used to match Base URL for Auth documented for the the HTTP Authorization
> Manager. 
> 
> https://jmeter.apache.org/usermanual/component_reference.
> html#HTTP_Authorization_Manager
> 
> states "Base URL" contains "A partial or complete URL".

I always understood the documentation to mean a valid URL, that is shortened on the path and not necessarily on the host name, but I get your point.

> 
> So it seems the patch would need to use similar startsWith matching logic as
> in
> https://github.com/apache/jmeter/blob/
> b6d11d79d905d0c099732bb928d2372fd1388981/src/protocol/http/src/main/java/org/
> apache/jmeter/protocol/http/control/AuthManager.java#L265 
> 
> I did not perform any other auth related tests given he above noted issue.

startsWith is not easily usable, as httpclient is not giving us information about the used protocol. We could guess it and try all combinations (http and https), or try to get the hostname and the port from the URL by means of guessing.

Both approaches have their weaknesses. Which one would you prefer?
Comment 13 Felix Schumacher 2020-05-10 12:34:05 UTC
Created attachment 37222 [details]
Try harder to match even partial URLs from AuthManager

Try to match on partial URLs when asking for BASIC authentication.