HttpURLConnection authentication mode - java

I'm using HttpURLConnection class to manage HTTP connections in my Android app. Problem is, on some servers, I have a code 401 using an URL which working on a Internet navigator. I initialize connection with basic authentication, but I think these servers need an other mode. I know it works with libCURL and the following instruction:
curl_easy_setopt(pCurlHandle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
But is there an way to doing something like that on Android? Currently, I do that:
...
connection.setRequestProperty("Authorization", "Basic " + Base64.encode("username:password"));
...
I tried with Authenticator too:
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("username", "password".toCharArray());
}
});
But I still have a 401 in my app. Any idea?

Well, this post really helped me (but I don't use Authenticator class at all) and now my code do the job like that (if authentication is needed):
Initialize my HttpURLConnection object with Basic authentication (see the first Java sample in my question's code)
Test if I receive a code 401 and if it is, check if server was excepted for a Digest authentication analyzing response headers.
Retry with a manually-built Digest request property (see the post I mentioned)
And it works!
I hope this answer'll help someone!

Related

Proxy Authentication Failed error. [Java, FTP Proxy] [duplicate]

I'm trying to access an FTP server through an FTP SITE Proxy to bypass a firewall using it.sauronsoftware.ftp4j.FTPClient I know my username/password is correct because I can connect using FileZilla. I tried using Authenticator, but it has no use. Code:
import java.net.Authenticator;
import it.sauronsoftware.ftp4j.FTPClient;
import it.sauronsoftware.ftp4j.connectors.FTPProxyConnector;
...
FTPClient client = new FTPClient();
FTPProxyConnector connector = new FTPProxyConnector(String "proxyHost", int proxyPort);
client.setConnector(connector);
Authenticator.setDefault(new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("proxyUser", "proxyPass".toCharArray());
}});
System.setProperty("ftp.proxyHost", "proxyHost");
System.setProperty("ftp.proxyPort", "proxyPort");
System.setProperty("ftp.proxyUser", "proxyUser");
System.setProperty("ftp.proxyPass", "proxyPass");
System.out.println("Proxy Accessed");
client.connect("ftpHost");
client.login("ftpUser", "ftpPass");
Gives me this error: java.io.IOException: Proxy authentication failed
Things I have tried:
Using the alternate constructor (String, int, String, String).
Removing Authenticator
Using just Authenticator, without the FTPProxyConnector
Authenticating before setting the connector, and vice versa.
However, when I am JUST using the Authenticator, I get a different error saying Connection timed out.
Both errors occur on line client.connect("ftpHost");
ANY help would be appreciated.
Note: The FTP Proxy Connector
EDIT: I found out that the proxy is used to bypass a Firewall-1 Checkpoint -- if this helps.
Check password property name. It's name is ftp.proxyPassword, and not ftp.proxyPass.
System.setProperty("ftp.proxyUser", "proxyUser");
System.setProperty("ftp.proxyPassword", "proxyPass");
Try it and let us know your results!
Check password property name. It's name is ftp.proxyPassword, and not ftp.proxyPass.
System.setProperty("ftp.proxyUser", "proxyUser");
System.setProperty("ftp.proxyPassword", "proxyPass");
Try it and let us know your results!
I found the solution...
I discovered that the FTP client was responding with a different response code:
200-User <username> authenticated by FireWall-1 authentication
In the source code of FTPProxyConnector, a response code of anything other than the regular
230-Connected to server. Logging in...
will throw an error.
I had to decompile the class file for FTPProxyConnector and then modify the source code, then recompile and save it back to the jar. Worked like a charm.

NTLM authentication with httpclient 4.2.1

I need to do a HTTP GET to a URL that needs NTLM authentication. I can access the URL using Firefox or Chrome on a MacBook Pro. The browser asks for the username/password combo and it works. I am now trying to do the same from Groovy using HttpClient. I followed the NTLM support guide, but I always get a 401 Unauthorized back. There is also this sentence in the response:
You do not have permission to view this directory or page using the
credentials that you supplied because your Web browser is sending a
WWW-Authenticate header field that the Web server is not configured to
accept.
I tried all kinds of combinations for the servername and domain (the remote windows pc is not on a domain) in this piece of code, but I always get the same response.
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("myserver", -1),
new NTCredentials("username", "password", "MYSERVER", "MYDOMAIN"));
Anybody had the same problem and managed to solve it? Note that this is an external program that uses IIS under the hood, so I don't think I can change any settings there.
EDIT:
Unlike what I have said, I managed to change the security settings in IIS to accept BASIC authentation, so I don't have the problem anymore.
EDIT:
In my experience with setting up Kerberos or NTLM (both are single sign on), you don't have to enter username/password at all when you are already logged in to your system.
I am pretty sure that when the browser asked for username/password combo, that's not an NTLM authentication at all. Most likely the server side application has a fallback scheme to HTTP Basic Digest (that why it displayed the username/password combo). With NTLM you'll never have to enter your username/password (principal/credentials) at all, as the server will recognize who you are through the negotiation mechanism between your browser, your operating system, server and Active Directory server.
If your MacBook Pro is running on OS/X, you also need to add your OS/X to the domain.
Your server also needs to be in the same domain where the client OS/X being added.
This may not be a trivial case. Some external tools/driver may be needed. This one may be a good candidate (but I haven't tried that).
NTLM needs both the client to be a member of the same domain as the server, hence both needs to be registered in the Active Directory domain. If your server is not in the domain, than that will be another set of problem.
In order to get your browser works with NTLM, you need to install plugin (ntlmauth-plugin?). But I have never try that on MacOS/X yet. Even in Windows you still need a plugin in order to run Firefox successfully with NTLM.
HttpClient did not work for me but finally the code below worked.
Reference - http://docs.oracle.com/javase/7/docs/technotes/guides/net/http-auth.html
For quick reference -
public static String getResponse(String url, String userName, String password) throws IOException {
Authenticator.setDefault(new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
System.out.println(getRequestingScheme() + " authentication");
return new PasswordAuthentication(userName, password.toCharArray());
}
});
URL urlRequest = new URL(url);
HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("GET");
StringBuilder response = new StringBuilder();
InputStream stream = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
response.append(str);
}
in.close();
return response.toString();
}

Java Proxy Authentication

I have a Java webapp, running in Tomcat 6, that loads RSS feeds from remote URLs.
I use Rome to handle the RSS feeds and different formats for me. The connection part looks like like that :
try{
feedSource = new URL(rssObject.getAsset());
}catch(MalformedURLException mue){
logger.error(...);
throw mue;
}
try{
URLConnection connection = feedSource.openConnection();
feed = new SyndFeedInput().build(new XmlReader(connection));
}catch(Exception){handle...}
The code works fine, except at this new client, where they use a proxy.
In order to use the proxy, I set the http.proxyHost and proxyPort system properties :
System.setProperty("http.proxyHost", proxyHost);
System.setProperty("http.proxyPort", proxyPort);
System.setProperty("https.proxyHost", proxyHost);
System.setProperty("https.proxyPort", proxyPort);
HTTP GET is made to the proxy alright, but now I get a HTTP 502 error (bad gateway or something similar).
Analysing the HTTP exchange with Wireshark, I noticed that the proxy is requiring authentication. It sends a HTTP 507. Java is somehow trying to authenticate but it uses the wrong username and passwords. It seems to use the host name as the username, as for the password I don't know.
So I tried to implement the Authenticator method of specifying a username+password :
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
logger.info(MessageFormat.format("Generating PasswordAuthentitcation for proxy authentication, using username={0} and password={1}.", username, password));
return new PasswordAuthentication(username, password.toCharArray());
}
});
Now my problem is that it is ignored. The getPasswordAuthentication method is never called. I don't see the logging statement in the log file and using Wireshark I can see that it still uses the host name as the user name.
Why ? It seems that java somehow tries to authenticate by itself without consulting the Authenticator.
The proxy seems to be a MS device that uses NTLM for authentication. Is there some built-in mechanism in java to handle this ? The machine on which the app runs is Win Server 2008 R2.
We did the same here for authenticating on a NTLM based proxy.
The authentication on the proxy is actually a normal HTTP Basic Authentication.
We used the following method:
protected URLConnection newURLConnection(URL pURL) throws IOException {
URLConnection urlConnection = super.newURLConnection(pURL);
String auth = new String(Base64.base64Encode(new String("username:password").getBytes()));
auth = "Basic " + auth;
urlConnection.setRequestProperty("Proxy-Connection","Keep-Alive");
urlConnection.setRequestProperty("Proxy-Authorization",auth);
return urlConnection;
}
That, together with the proxy jvm settings, did the trick.
See http://en.wikipedia.org/wiki/Basic_access_authentication.

How to avoid JVM opening auth window when HttpURLConnection hits 401

I am using java.net.HttpURLConnection, and it annoyingly presents a window asking for username and password whenever a 401 response code is returned by the HTTP server.
How can I get rid of this automatic auth dialog? I want to handle 401s myself.
I tried setAllowUserInteraction(false), but it seems to have no effect.
The popup comes from the default authenticator. To remove the popup, you can plug in your own authenticator. See How to handle HTTP authentication using HttpURLConnection?
#mdma's answer is correct, you can plug in your own Authenticator to handle authentication, so that there's no popup.
If you're already handling authentication in another way (such as by connection.setRequestProperty("Authorization", ...), as this answer to another question describes), you can use Authenticator.setDefault() to choose to not to use any Authenticator for authentication:
Authenticator.setDefault(null);
This removes the old default Authenticator, so that if your authentication is wrong, you get the error response code via your URLConnection, without opening any popup.
An equivalent way is to set the default to an Authenticator which returns null for getPasswordAuthentication() (which is the default implementation), as in the following code:
Authenticator.setDefault(new Authenticator() { });
But unless you're going to add code to your Authenticator, I don't see a reason to choose this over null.

NTLMv2 HTTP Authentication Java

I'm very confused on how this is supposed to work. I've tried using something like this:
con = (HttpURLConnection) url2.openConnection();
con.setReadTimeout(10000);
con.setInstanceFollowRedirects(true);
con.setAllowUserInteraction(true);
con.setDoOutput(true);
con.setDoInput(true);
Authenticator.setDefault(new MyAuthenticator());
con.connect();
class MyAuthenticator extends Authenticator {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("myUser", "MyPassword".toCharArray());
}
}
I'm getting a 401 error returned by this method so obviously I'm missing the point. According to this chart NTLMv2 should be supported in JRE 6. My confusion lies in the fact that this is running on Android. In the stack trace from the exception thrown by getOutputStream I see an Apache implementation of HttpURLConnection being referenced.
From what I have found in my research Apache is unable to include NTLMv2 protocols due to licensing issues. Is this why it does not work on android?
Either way I'd like to know how this would be done in Java, not just Android.
It is not implemented. Check out this issue: http://code.google.com/p/android/issues/detail?id=4962. Also consider the fact that Android is not JRE 6, it is a modified version of standard Java.

Categories