Apache http client sample failing for Digest authentication - java

I am running the sample Apache hc (http client) for digest authentication. I didn't change anything, just using the provided sample:
public static void main(String[] args) throws Exception {
HttpHost target = new HttpHost("httpbin.org", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
new UsernamePasswordCredentials("user", "passwd"));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider)
.build();
try {
// 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();
// Suppose we already know the realm name
digestAuth.overrideParamter("realm", "me#kennethreitz.com");
// Suppose we already know the expected nonce value
digestAuth.overrideParamter("nonce", "b2c603bb7c93cfa197945553a1044283");
authCache.put(target, digestAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd");
System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target);
for (int i = 0; i < 3; i++) {
CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
}
} finally {
httpclient.close();
}
}
And I am getting: HTTP/1.1 401 UNAUTHORIZED
If I go direct to http://httpbin.org/digest-auth/auth/user/passwd in prompts me for user/passwd and then provides the page. So the website is working right.
Any idea what is wrong? I have the latest version of the library.
Fiddler Auth for browser (successful):
No Proxy-Authorization Header is present.
Authorization Header is present: Digest username="user",
realm="me#kennethreitz.com", nonce="8ada87344eb5a10bf810bcc211205c24",
uri="/digest-auth/auth/user/passwd",
response="ad22423e5591d14c90c6fe3cd762e64c",
opaque="361645844d957289c4c8f3479f76269f", qop=auth, nc=00000001,
cnonce="260d8ddfe64bf32e"
Fiddler Auth for my code (failed):
No Proxy-Authorization Header is present.
Authorization Header is present: Digest username="user",
realm="me#kennethreitz.com", nonce="76af6c9c0a1f57ee5f0fcade2a5f758c",
uri="http://httpbin.org/digest-auth/auth/user/passwd",
response="745686e3f38ab40ce5907d41f91823e6", qop=auth, nc=00000001,
cnonce="634b618d5c8ac9af", algorithm=MD5,
opaque="fe84ce11c48a7b258490600800e5e6df"

This code digestAuth.overrideParamter("realm", "some realm") should have some change.To replace "some realm" by your server realm.Please look this question

Ok I got it working. You have to set a cookie too. Thanks to this post for the help. The below code works - but only if you are not using Fiddler.
public static void main(String[] args) throws Exception {
CookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("fake", "fake_value");
cookie.setDomain("httpbin.org");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// https://stackoverflow.com/questions/27291842/digest-auth-with-java-apache-client-always-401-unauthorized
HttpHost target = new HttpHost("httpbin.org", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
new UsernamePasswordCredentials("user", "passwd"));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider)
// .setProxy(new HttpHost("127.0.0.1", 8888))
.build();
try {
// 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();
// Suppose we already know the realm name
digestAuth.overrideParamter("realm", "me#kennethreitz.com");
// Suppose we already know the expected nonce value
digestAuth.overrideParamter("nonce", calculateNonce());
authCache.put(target, digestAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd");
System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target);
CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
public static synchronized String calculateNonce() {
Date d = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy:MM:dd:hh:mm:ss");
String fmtDate = f.format(d);
Random rand = new Random(100000);
Integer randomInt = rand.nextInt();
return org.apache.commons.codec.digest.DigestUtils.md5Hex(fmtDate + randomInt.toString());
}

Related

how can i get jsessionId from client: DefaultHttpClient httpclient = new DefaultHttpClient();

HttpHost targetHost = new HttpHost("myhost",8080, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new
AuthScope(targetHost.getHostName(), targetHost.getPort()), new
UsernamePasswordCredentials("username", "password"));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);
HttpGet httpget = new HttpGet("/");
try {
HttpResponse response = httpclient.execute(targetHost, httpget, context);
System.out.println(httpclient.getCookieStore().getCookies());
} catch (Exception e) {
} finally {
try {
httpget.abort();}catch(Exception e){}
}
}
but output i am getting is : [] nothing else . what mistake i am doing and how i can get jsessionId so that i can store it and use it later when i have to post json data to my server
Have you checked this link
How to manage sessions with Android Application
private void parseSessionID(HttpResponse response) {
try {
Header header = response.getFirstHeader("Set-Cookie");
String value = header.getValue();
if (value.contains("JSESSIONID")) {
int index = value.indexOf("JSESSIONID=");
int endIndex = value.indexOf(";", index);
String sessionID = value.substring(
index + "JSESSIONID=".length(), endIndex);
Logger.d(this, "id " + sessionID);
if (sessionID != null) {
classStaticVariable= sessionID;
}
}
} catch (Exception e) {
}

i'm trying to send a https request through a proxy with apache httpclient,but i can't find the headers on the proxy side

i'm trying to send a https request through a proxy with apache httpclient,but i can't find the headers on the proxy side
HttpClient httpClient =new DefaultHttpClient();
HttpHost proxy = new HttpHost("10.1.1.100", 8080);
httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY,proxy);
HttpGet get = new HttpGet(uri);
get.addHeader("Proxy-Authorization", "222222");
HttpResponse hr = defaultHttpClient.execute(get);
the proxy side only find proxy-connection and user-agent:
Proxy-Connection:[Keep-Alive] User-Agent:[Apache-HttpClient/4.3.6 (java 1.5)]
First, that's not how you authenticate to a proxy. Second, those headers are added to the get request (not to the proxy). Finally, this is based on an example the HttpClient examples - specifically ClientProxyAuthentication and updated to use try-with-resources (and modified to use an URL)
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope("10.1.1.100", 8080),
new UsernamePasswordCredentials("username", "password"));
try (CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build()) {
URL url = new URL(uri);
HttpHost target = new HttpHost(url.getHost(), url.getPort(),
url.getProtocol());
HttpHost proxy = new HttpHost("10.1.1.100", 8080);
RequestConfig config = RequestConfig.custom().setProxy(proxy)
.build();
HttpGet httpget = new HttpGet(url.getPath());
httpget.setConfig(config);
System.out.println("Executing request " + httpget.getRequestLine()
+ " to " + target + " via " + proxy);
try (CloseableHttpResponse response = httpclient.execute(target,
httpget)) {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(response.getEntity());
}
} catch (IOException e1) {
e1.printStackTrace();
}

Digest auth with Java & Apache client : Always 401 Unauthorized

I'm trying to implement digest auth with an HTTP client, but this does not work at the moment.
Can someone check if this code is correct? For testing purpose I use http://httpbin.org/, but all I get is HTTP/1.1 401 Unauthorized.
Here is the example code:
private static void doDigestAuth() throws ClientProtocolException,
IOException,
AuthenticationException,
MalformedChallengeException
{
HttpHost target = new HttpHost("httpbin.org", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(target.getHostName(), target.getPort()), new UsernamePasswordCredentials(
"user", "passwd"));
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
try {
HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd");
// 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();
// Suppose we already know the realm name
digestAuth.overrideParamter("realm", "me#kennethreitz.com");
// // Suppose we already know the expected nonce value
// digestAuth.overrideParamter("nonce", Long.toString(new SecureRandom().nextLong(), 36));
// qop-value = "auth" | "auth-int" | token
digestAuth.overrideParamter("qop", "auth");
authCache.put(target, digestAuth);
// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
// context.setAuthSchemeRegistry(authRegistry);
context.setAuthCache(authCache);
System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target);
for (int i = 0; i < 3; i++) {
CloseableHttpResponse response = httpclient.execute(httpget, context);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
InputStream instream = entity.getContent();
// Header contentCncoding = entity .getContentEncoding();
String contentString = IOUtils.toString(instream, null);
System.out.println("ContentString:" + contentString);
AuthState proxyAuthState = context.getProxyAuthState();
System.out.println("Proxy auth state: " + proxyAuthState.getState());
System.out.println("Proxy auth scheme: " + proxyAuthState.getAuthScheme());
System.out.println("Proxy auth credentials: " + proxyAuthState.getCredentials());
AuthState targetAuthState = context.getTargetAuthState();
System.out.println("Target auth state: " + targetAuthState.getState());
System.out.println("Target auth scheme: " + targetAuthState.getAuthScheme());
System.out.println("Target auth credentials: " + targetAuthState.getCredentials());
EntityUtils.consume(response.getEntity());
}
finally {
response.close();
}
}
}
finally {
httpclient.close();
}
}
It was a cookie problem as #heaphach suggested. The wire-log (shown with log category org.apache.http.wire set to debug) shows:
<< "Set-Cookie: fake=fake_value[\r][\n]"
but the HttpClient never picks this up
and does not use it in the second GET request containing the full "Authorization" header with the digest-response.
As a consequence, the server just ignores the digest response.
After I updated the example code (also known as the Preemptive DIGEST authentication example)
with the code shown below (copied from the HTTP state management tutorial), the server responded "200 OK".
CookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("fake", "fake_value");
cookie.setDomain("httpbin.org");
cookie.setPath("/");
cookieStore.addCookie(cookie);
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider)
.build();
I also came across a gist containing some code to calculate a "nonce"
so you can use
digestAuth.overrideParamter("nonce", calculateNonce());
and org.apache.http.impl.auth.HttpAuthenticator no longer shows the error message "missing nonce in challenge".
public static synchronized String calculateNonce() {
Date d = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy:MM:dd:hh:mm:ss");
String fmtDate = f.format(d);
Random rand = new Random(100000);
Integer randomInt = rand.nextInt();
return org.apache.commons.codec.digest.DigestUtils.md5Hex(fmtDate + randomInt.toString());
}

http client 4.3 not sending credentials

I am trying to send a get request using apache http client 4.3 (to a client using self sign cert), however I get back the error "Requires Authentication" everytime. In a web browser it works just fine so the username / password / url is correct. Is this not the way to pass username/password using http client 4.3?
public static String sendJsonHttpGetRequest(
String host,
String path,
String username,
String password,
int socketTimeout,
int connectionTimeout,
int connectionRequestTimeout
) throws Exception
{
String responseBody = null;
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustStrategy(){
#Override
public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException
{
return true;
}
});
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultCredentialsProvider(credsProvider).build();
URIBuilder uriB = new URIBuilder().setScheme("https").setHost(host).setPath(path);
HttpGet _http = new HttpGet( uriB.build() );
RequestConfig _requestConfig = RequestConfig.custom().
setSocketTimeout(socketTimeout).
setConnectTimeout(connectionTimeout).
setConnectionRequestTimeout(connectionRequestTimeout).build();
_http.addHeader("Content-Type", "application/json");
_http.addHeader("Accept","application/json, text/xml;q=9, /;q=8");
_http.setConfig(_requestConfig);
// ###########################
ResponseHandler<String> response = new BasicResponseHandler();
responseBody = httpclient.execute(_http, response);
return responseBody;
}
turns out now with http 4+ you have to provide it in two locations for it to work,
second is
authCache.put(host, basicAuth);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
HttpClientContext _context = HttpClientContext.create();
_context.setAuthCache(authCache);
_context.setCredentialsProvider(credentialsProvider);
responseBody = httpclient.execute(_http, response, _context);
I don't use this library myself, but have you tried the HttpClient class?
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
GetMethod method = new GetMethod(uri);
client.executeMethod(method);
You still have to build the uri and set timeouts, but it could be an option.

Apache Http Digest Authentication using Java

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", "shirwa99#gmail.com"));
// nvps.add(new BasicNameValuePair("password", "example"));
// httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response2 = httpclient.execute(httpPost);
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();
}
}
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?
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();
}
}
}
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();
}
}

Categories

Resources