Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge #5265

Closed
asfimport opened this issue Mar 26, 2020 · 15 comments

Comments

@asfimport
Copy link
Collaborator

Peter Lynch (Bug 64267):
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.

Created attachment basic-auth-challenge-test.jmx: reproduce test case

basic-auth-challenge-test.jmx
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.2.1">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP Authorization Manager" enabled="true">
        <collectionProp name="AuthManager.auth_list">
          <elementProp name="" elementType="Authorization">
            <stringProp name="Authorization.url">http</stringProp>
            <stringProp name="Authorization.username">user</stringProp>
            <stringProp name="Authorization.password">passwd</stringProp>
            <stringProp name="Authorization.domain"></stringProp>
            <stringProp name="Authorization.realm">Fake Realm</stringProp>
          </elementProp>
        </collectionProp>
        <boolProp name="AuthManager.controlledByThreadGroup">false</boolProp>
      </AuthManager>
      <hashTree/>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">1</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">1</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
      </ThreadGroup>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">httpbin.org</stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.protocol">https</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/basic-auth/user/passwd</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree>
          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
            <collectionProp name="Asserion.test_strings">
              <stringProp name="49586">200</stringProp>
            </collectionProp>
            <stringProp name="Assertion.custom_message"></stringProp>
            <stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
            <boolProp name="Assertion.assume_success">true</boolProp>
            <intProp name="Assertion.test_type">8</intProp>
          </ResponseAssertion>
          <hashTree/>
        </hashTree>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

OS: All

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
Created attachment jmeter.log: log from running reproduce case with log level DEBUG

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
Looks like a regression to me - or a deliberate change that was not documented.

Created attachment jmeter-3.3-working-automatic-challenge-response.log: log file proof that jmeter version 3.3 did what I expected

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
It would be an enhancement not a regression.
JMeter has never in the past handled Basic Auth the way you suggest it.

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
(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?

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
(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 ?

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
(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

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
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.

Created attachment 01.diff: Fix non-preemptive authentication for http sampler

01.diff
diff --git a/bin/jmeter.properties b/bin/jmeter.properties
diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
index b24cb66bf2..3808bb9e74 100644
--- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
+++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
@@ -24,12 +24,14 @@ import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLDecoder;
 import java.nio.charset.Charset;
 import java.security.GeneralSecurityException;
+import java.security.Principal;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
@@ -62,6 +64,7 @@ import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.AuthState;
 import org.apache.http.auth.Credentials;
 import org.apache.http.auth.NTCredentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.AuthCache;
 import org.apache.http.client.AuthenticationStrategy;
 import org.apache.http.client.CredentialsProvider;
@@ -119,6 +122,7 @@ import org.apache.http.impl.client.HttpClients;
 import org.apache.http.impl.client.LaxRedirectStrategy;
 import org.apache.http.impl.client.ProxyAuthenticationStrategy;
 import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
+import org.apache.http.impl.client.TargetAuthenticationStrategy;
 import org.apache.http.impl.conn.DefaultHttpClientConnectionOperator;
 import org.apache.http.impl.conn.DefaultSchemePortResolver;
 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
@@ -205,6 +209,80 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
 
     private static final InputStreamFactory BROTLI = BrotliInputStream::new;
 
+    private static final class ManagedCredentialsProvider implements CredentialsProvider {
+        private AuthManager authManager;
+        private Credentials proxyCredentials;
+        private AuthScope proxyAuthScope;
+
+        public ManagedCredentialsProvider(AuthManager authManager, AuthScope proxyAuthScope, Credentials proxyCredentials) {
+            this.authManager = authManager;
+            this.proxyAuthScope = proxyAuthScope;
+            this.proxyCredentials = proxyCredentials;
+        }
+
+        @Override
+        public void setCredentials(AuthScope authscope, Credentials credentials) {
+            log.debug("Store creds {} for {}", credentials, authscope);
+        }
+
+        @Override
+        public Credentials getCredentials(AuthScope authScope) {
+            log.info("Get creds for {}", authScope);
+            if (this.proxyAuthScope != null && authScope.equals(proxyAuthScope)) {
+                return proxyCredentials;
+            }
+            final Authorization authorization = getAuthorizationForAuthScope(authScope);
+            if (authorization == null) {
+                return null;
+            }
+            return new UsernamePasswordCredentials(authorization.getUser(), authorization.getPass());
+        }
+
+        /**
+         * Find the Authorization for the given AuthScope. We can't ask the AuthManager
+         * by the URL, as we didn't get the scheme or path of the URL. Therefore we do a
+         * best guess on the information we have
+         *
+         * @param authScope information which destination we want to get credentials for
+         * @return matching authorization information entry from the AuthManager
+         */
+        private Authorization getAuthorizationForAuthScope(AuthScope authScope) {
+            if (authScope == null) {
+                return null;
+            }
+            for (JMeterProperty authProp : authManager.getAuthObjects()) {
+                Object authObject = authProp.getObjectValue();
+                if (authObject instanceof Authorization) {
+                    Authorization auth = (Authorization) authObject;
+                    if (!authScope.getRealm().equals(auth.getRealm())) {
+                        continue;
+                    }
+                    try {
+                        URL authUrl = new URL(auth.getURL());
+                        if (authUrl.getHost().equals(authScope.getHost()) && getPort(authUrl) == authScope.getPort()) {
+                            return auth;
+                        }
+                    } catch (MalformedURLException e) {
+                        log.debug("Invalid URL {} in authManager", auth.getURL());
+                    }
+                }
+            }
+            return null;
+        }
+
+        private int getPort(URL url) {
+            if (url.getPort() == -1) {
+                return url.getProtocol().equals("https") ? 443 : 80;
+            }
+            return url.getPort();
+        }
+
+        @Override
+        public void clear() {
+            log.debug("clear creds");
+        }
+    }
+
     private static final class PreemptiveAuthRequestInterceptor implements HttpRequestInterceptor {
         @Override
         public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
@@ -1050,21 +1131,27 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
             }
 
             // Set up proxy details
+            AuthScope proxyAuthScope = null;
+            NTCredentials proxyCredentials = null;
             if (key.hasProxy) {
                 HttpHost proxy = new HttpHost(key.proxyHost, key.proxyPort, key.proxyScheme);
                 builder.setProxy(proxy);
 
                 CredentialsProvider credsProvider = new BasicCredentialsProvider();
                 if (!key.proxyUser.isEmpty()) {
+                    proxyAuthScope = new AuthScope(key.proxyHost, key.proxyPort);
+                    proxyCredentials = new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN);
                     credsProvider.setCredentials(
-                            new AuthScope(key.proxyHost, key.proxyPort),
-                            new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN));
+                            proxyAuthScope,
+                            proxyCredentials);
                 }
                 builder.setDefaultCredentialsProvider(credsProvider);
             }
             builder.disableContentCompression().addInterceptorLast(RESPONSE_CONTENT_ENCODING);
             if(BASIC_AUTH_PREEMPTIVE) {
                 builder.addInterceptorFirst(PREEMPTIVE_AUTH_INTERCEPTOR);
+            } else {
+                builder.setDefaultCredentialsProvider(new ManagedCredentialsProvider(getAuthManager(), proxyAuthScope, proxyCredentials));
             }
             httpClient = builder.build();
             if (log.isDebugEnabled()) {

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
(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

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
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.

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
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 740a206
AuthorDate: Sat May 9 11:55:31 2020 +0200

When preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge

https://github.com/apache/jmeter/issues/5265

.../jmeter/protocol/http/sampler/HTTPHC4Impl.java | 86 +++++++++++++++++++++-
xdocs/changes.xml | 1 +
2 files changed, 85 insertions(+), 2 deletions(-)

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
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:

740a206#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

if (s1.startsWith(uRL) || s2 != null && s2.startsWith(uRL)) {

I did not perform any other auth related tests given he above noted issue.

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
(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/
740a206#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/
b6d11d7/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?

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
Try to match on partial URLs when asking for BASIC authentication.

Created attachment 01.diff: Try harder to match even partial URLs from AuthManager

01.diff
diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
index 4824ed6a70..fab565a59b 100644
--- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
+++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
@@ -255,19 +255,32 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
                     if (!authScope.getRealm().equals(auth.getRealm())) {
                         continue;
                     }
-                    try {
-                        URL authUrl = new URL(auth.getURL());
-                        if (authUrl.getHost().equals(authScope.getHost()) && getPort(authUrl) == authScope.getPort()) {
-                            return auth;
-                        }
-                    } catch (MalformedURLException e) {
-                        log.debug("Invalid URL {} in authManager", auth.getURL());
+                    if (matchesOnUrl(authScope, auth)) {
+                        return auth;
                     }
                 }
             }
             return null;
         }
 
+        private boolean matchesOnUrl(AuthScope authScope, Authorization auth) {
+            String authUrlString = auth.getURL().toLowerCase();
+            try {
+                URL authUrl = new URL(authUrlString);
+                if (authUrl.getHost().equals(authScope.getHost()) && getPort(authUrl) == authScope.getPort()) {
+                    return true;
+                }
+            } catch (MalformedURLException e) {
+                for (String prefix: Arrays.asList("http://", "https://")) {
+                    if ((prefix + authScope.getHost() + ":" + authScope.getPort()).startsWith(authUrlString)) {
+                        return true;
+                    }
+                }
+                log.debug("Invalid URL {} in authManager", authUrlString);
+            }
+            return false;
+        }
+
         private int getPort(URL url) {
             if (url.getPort() == -1) {
                 return url.getProtocol().equals("https") ? 443 : 80;

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
(In reply to Felix Schumacher from comment 13)

Created attachment 37222 [details]
Try harder to match even partial URLs from AuthManager

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

Hello Peter,
Did you have a chance to try Felix's fix ?

Thank you

@asfimport
Copy link
Collaborator Author

Peter Lynch (migrated from Bugzilla):
I believe this issue to be solved. When I tested the snapshot with latest changes before it was released official, it did work as I expect now. I will be updating to try the official released version soon, but I wanted to relay my findings so far in case you just want to close this issue now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant