Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache HTTP Client 5.3 ~ NTCredentials no longer working

I have a project that uses org.apache.httpcomponents.client5:httpclient5. I recently tried upgrading from version 5.2.3 to version 5.3, only to realize that the authentication was no longer working in the new version.

Here is how the relevant code looks:

        BasicCredentialsProvider credentialsProvider =
            new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
            new AuthScope(host, port),
            new NTCredentials(username, password.toCharArray(), "", "")
        );
        httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credentialsProvider)
            .build();
[...]
            final HttpGet httpget = new HttpGet(targetUrl);

            CloseableHttpResponse response = httpclient.execute(httpget);

Before the update from 5.2.3 to 5.3 this worked fine. However, when I use 5.3, I now get a 401 UNAUTHORIZED response.

I also tried the following variations to above code to pass the credentials along, but they all also return only 401 UNAUTHORIZED:

        httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(CredentialsProviderBuilder.create()
                .add(new HttpHost(host, port), username, password.toCharArray())
                .build())
            .build();
        credentialsProvider.setCredentials(
            new AuthScope(host, port),
            new UsernamePasswordCredentials(username, password.toCharArray())
        );
        SystemDefaultCredentialsProvider credentialsProvider =
            new SystemDefaultCredentialsProvider();
        credentialsProvider.setCredentials(
            new AuthScope(host, port),
            new NTCredentials(username, password.toCharArray(), "", "")
        );

Now I am stumped. Could this be a bug in 5.3? Or did something change to the way that the NTCredentialsProvider works? I could not find any release notes indicating so, and since this is only a minor version update that would surprise me.

Nonetheless, the fact it that it works with the old version but not with the new one. Does anyone has any suggestions as to what I can do about that?

like image 609
Kira Resari Avatar asked Oct 27 '25 14:10

Kira Resari


2 Answers

I spent some time trying to get Apache Http Client to authenticate using Single Sign on and Windows Integrated Authentication against a Servlet running on Tomcat with the Waffle filter configured to use Negotiate. My code used to work fine with Apache HttpClient 4.5 but with 5.x it stopped working. This is the code that worked for me.

System.out.println("Win auth available: " + WinHttpClients.isWinAuthAvailable());
    if (WinHttpClients.isWinAuthAvailable()) {
        ClassicHttpRequest request = new HttpGet("http://localhost:8080/ssotestwebapp/webapp");
        CloseableHttpClient client = WinHttpClients.createDefault();
        HttpClientContext context = HttpClientContext.create();
        
        Collection<String> targetPreferedAuthSchemes = Collections.unmodifiableList(
                Arrays.asList(StandardAuthScheme.KERBEROS, StandardAuthScheme.SPNEGO, StandardAuthScheme.NTLM,
                        StandardAuthScheme.BEARER, StandardAuthScheme.DIGEST, StandardAuthScheme.BASIC));
        RequestConfig config = RequestConfig.custom().setTargetPreferredAuthSchemes(targetPreferedAuthSchemes)
                .build();
        context.setRequestConfig(config);
        
        client.execute(request, context, response -> {
            System.out.println("----------------------------------------");
            System.out.println(new StatusLine(response));
            HttpEntity entity = response.getEntity();
            String s = EntityUtils.toString(entity);
            System.out.println(s);
            EntityUtils.consume(response.getEntity());
            return null;
        });
    }

Createing a custom RequestConfig and list of targetPreferedAuthSchemes is the important part beacause the default RequestConfigs doesn't contain the deprecated schemes and will not use them even if you add them to the AuthSchemes reqistry.

Here are the maven dependencies i used:

<!--
    https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
    <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.3.1</version>
    </dependency>

    <!--
    https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5-win -->
    <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5-win</artifactId>
        <version>5.2.3</version>
        <scope>test</scope>
    </dependency>
like image 138
scaryxited Avatar answered Oct 29 '25 03:10

scaryxited


We now managed to solve it by providing the httpclient with a default auth scheme registry like this:

        Lookup<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
                .register(StandardAuthScheme.NTLM, new NTLMSchemeFactory()).build();

        httpclient = HttpClients.custom()
                .setDefaultCredentialsProvider(credentialsProvider)
                .setDefaultRequestConfig(config)
                .setDefaultAuthSchemeRegistry(authSchemeRegistry)
                .build();
like image 40
Kira Resari Avatar answered Oct 29 '25 03:10

Kira Resari