3

I am currently working on a Java project and I can't get the http digest authentication working. I tried using the Apache website, but it didn't help. I have a site that requires HTTP digest authentication.

        DefaultHttpClient httpclient = new DefaultHttpClient();
        String hostUrl = "http://somewebsite.com";
        String postUrl = "http://somewebsite.com/request";
        HttpPost httpPost = new HttpPost(postUrl);
        String username = "hello";
        String password = "world";
        HttpHost targetHost = new HttpHost(hostUrl);

        httpclient.getCredentialsProvider().setCredentials(
                new AuthScope(hostUrl, AuthScope.ANY_PORT),
                new UsernamePasswordCredentials(username, password));

        AuthCache authCache = new BasicAuthCache();

        DigestScheme digestAuth = new DigestScheme();

        digestAuth.overrideParamter("realm", "some realm");

        digestAuth.overrideParamter("nonce", "whatever");
        authCache.put(targetHost, digestAuth);

        BasicHttpContext localcontext = new BasicHttpContext();
        localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

        // List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        // nvps.add(new BasicNameValuePair("username", "[email protected]"));
        // nvps.add(new BasicNameValuePair("password", "example"));
        // httpPost.setEntity(new UrlEncodedFormEntity(nvps));
        HttpResponse response2 = httpclient.execute(httpPost);
1
  • any solution for that? Commented Feb 21, 2014 at 13:18

5 Answers 5

2

This code works for me pretty well:

protected static void downloadDigest(URL url, FileOutputStream fos)
  throws IOException {
  HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
  CloseableHttpClient httpClient = HttpClients.createDefault();
  HttpClientContext context = HttpClientContext.create();

  String credential = url.getUserInfo();
  if (credential != null) {
    String user = credential.split(":")[0];
    String password = credential.split(":")[1];

    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(AuthScope.ANY,
      new UsernamePasswordCredentials(user, password));
    AuthCache authCache = new BasicAuthCache();
    DigestScheme digestScheme = new DigestScheme();
    authCache.put(targetHost, digestScheme);

    context.setCredentialsProvider(credsProvider);
    context.setAuthCache(authCache);
  }

  HttpGet httpget = new HttpGet(url.getPath());

  CloseableHttpResponse response = httpClient.execute(targetHost, httpget, context);

  try {
    ReadableByteChannel rbc = Channels.newChannel(response.getEntity().getContent());
    fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
  } finally {
    response.close();
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

try this code from apache httpClient 4.3.3

final HttpHost targetHost = new HttpHost("localhost", 8080, "http");
    final CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(AuthScope.ANY,
            new UsernamePasswordCredentials(user, password));

    final AuthCache authCache = new BasicAuthCache();
    DigestScheme digestAuth = new DigestScheme();
    digestAuth.overrideParamter("realm", "some-realm");
    digestAuth.overrideParamter("nonce", "whatever");
    authCache.put(targetHost, digestAuth);

    // Add AuthCache to the execution context
    HttpClientContext context = HttpClientContext.create();
    context.setAuthCache(authCache);
HttpGet httpget = new HttpGet("/");
CloseableHttpResponse response = httpclient.execute(targetHost , httpget, context );

Please can you give me the site which requires HTTP digest authentication?

2 Comments

did you find any online webservice to test your stuff?
I use httpbin.org. There is a digest auth endpoint to test. But I still get a 401 back using the code above. Is this snippet working for anyone using Digest Auth?
0

Try this code from Apache :

   public static void main(String[] args) throws Exception {
            HttpClient client = new HttpClient();
            client.getState().setCredentials(
                new AuthScope("myhost", 80, "myrealm"),
                new UsernamePasswordCredentials("username", "password"));
            // Suppose the site supports several authetication schemes: NTLM and Basic
            // Basic authetication is considered inherently insecure. Hence, NTLM authentication
            // is used per default

            // This is to make HttpClient pick the Basic authentication scheme over NTLM & Digest
            List authPrefs = new ArrayList(3);
            authPrefs.add(AuthPolicy.BASIC);
            authPrefs.add(AuthPolicy.NTLM);
            authPrefs.add(AuthPolicy.DIGEST);
            client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authrefs);

            GetMethod httpget = new GetMethod("http://myhost/protected/auth-required.html");

            try {
                int status = client.executeMethod(httpget);
                // print the status and response
                System.out.println(httpget.getStatusLine());
                System.out.println(httpget.getResponseBodyAsString());
            } finally {
                // release any connection resources used by the method
                httpget.releaseConnection();
            }            
        }

Comments

0

Tipp: do not use HTTP Digest :) It is not secure at all. Over HTTPS it has not point.

If you must, below is a code that works with parsing the WWW-Authenticate header.

This is tested with the following dependency (i use gradle):

compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'

The code:

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class DigestExample {

  private final static String uri = "http://my.digest.based.auth.url.com";
  private static HttpHost target;

  public static void main(String[] args) throws IOException {    

    setup();
    if (target == null) {
      System.out.println("Setup was unsuccesfull");
      return;
    }
    Header challengeHeader = getAuthChallengeHeader();
    if (challengeHeader == null) {
      System.out.println("Setup was unsuccesfull");
      return;
    }

    // NOTE: challenge is reused for subsequent HTTP GET calls (typo corrected)
    getWithDigestAuth(challengeHeader, "/", "/schema");

  }

  private static void setup() throws MalformedURLException {
    URL url = new URL(uri);
    target = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
  }

  private static Header getAuthChallengeHeader() {
    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
      CloseableHttpResponse response = httpClient.execute(new HttpGet(uri));
      return response.getFirstHeader("WWW-Authenticate");
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }

  private static void getWithDigestAuth(Header challengeHeader, String... requests)
      throws IOException {

    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
        new AuthScope(target.getHostName(), target.getPort()),
        new UsernamePasswordCredentials("user", "pass"));

    try (CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultCredentialsProvider(credsProvider)
        .build()) {

      // Create AuthCache instance
      AuthCache authCache = new BasicAuthCache();
      // Generate DIGEST scheme object, initialize it and add it to the local
      // auth cache
      DigestScheme digestAuth = new DigestScheme();
      digestAuth.processChallenge(challengeHeader);
      authCache.put(target, digestAuth);

      // Add AuthCache to the execution context
      HttpClientContext localContext = HttpClientContext.create();
      localContext.setAuthCache(authCache);

      for (String request : requests) {
        System.out.println("Executing request to target " + target + request);
        try (CloseableHttpResponse response = httpclient
            .execute(target, new HttpGet(request), localContext)) {
          System.out.println("----------------------------------------");
          System.out.println(response.getStatusLine());
          System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
          System.out.println("Error while executing HTTP GET request");
          e.printStackTrace();
        }
      }
    } catch (MalformedChallengeException e) {
      e.printStackTrace();
    }
  }
}

Comments

0

If you are using spring boot, use following dependency:

<dependency>
    <groupId>io.github.springboot-addons</groupId>
    <artifactId>spring-boot-starter-httpclient5</artifactId>
    <version>1.0.5</version>
</dependency>

Create a method to get RestClient for Digest authentication:

import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

public RestClient newDigestAuthRestClient(String host, int port, String username, String secret, String baseUri) {
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                new AuthScope(host, port),
                new UsernamePasswordCredentials(username, secret.toCharArray())
        );
        return RestClient.builder()
                .requestFactory(
                        new HttpComponentsClientHttpRequestFactory(
                                HttpClients.custom()
                                        .setDefaultCredentialsProvider(credentialsProvider)
                                        .build()
                        )
                )
                .baseUrl(baseUri)
                .build();
    }

And this is how you use it:

RestClient restClient = restClientFactory.newDigestAuthRestClient(host, port, user,
                password,
                baseUri); // baseUri: http://example.com
String resultText = restClient.get()
                .uri("/endpoint?param={value}", value)
                .accept(MediaType.APPLICATION_JSON) // acceptable response type
                .retrieve()
                .body(String.class); // Response type, for the sake of this example it is String so it returns the same

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.