Basic Auth over HTTPS Java - java

I have HTTPS page calls working fine and I have HTTP Basic Auth working fine what I can not do is get Basic Auth running on a HTTPS connection.
I attach a code example but it doesn't work. I keep getting a 403. I have checked the username and password and it has been successful when testing it with the RESTClinet addon from Firefox.
Any help would be great. Thanks.
private static void getAPITest() throws MalformedURLException, IOException
{
try {
System.setProperty("javax.net.ssl.trustStore","/home/USER/CERTS/myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "PASSWORD");
Authenticator myAuth = new Authenticator()
{
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("USERNAME", "PASSWORD".toCharArray());
}
};
Authenticator.setDefault(myAuth);
String httpsURL = "https://someurlandapi.com";
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
//con.setRequestProperty("Authorization", "Basic " + authString);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setRequestProperty("Accept", "application/json");
con.setRequestMethod("POST");
InputStream ins = con.getInputStream();
InputStreamReader isr = new InputStreamReader(ins);
BufferedReader in = new BufferedReader(isr);
String inputLine;
while ((inputLine = in.readLine()) != null)
{
System.out.println(inputLine);
}
ins.close();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

it turns out don't have a space before the basic:
con.setRequestProperty("Authorization", "Basic " + authStringEnc);
and it needed:
conn.setRequestProperty("User-Agent", "Mozilla/5");
A quick note for anyone doing this if you are creating your own truststore you will need to add the sites/urls SSL certificate chain. In firefox you can click on the padlock > More information > security > view certificates. From there you can highlight the certificate export with chain it then add it to your truststore with the keytool:
keytool -import -file websitecertificate.pem -alias websitecert -keystore myTrustStore

I don't think PasswordAuthentication is doing what you want. But basic auth is really easy to handle yourself. If you're in Java8 it is simply Base64.getEncoder().encodeToString( ("USERNAME" + ":" + "PASSWORD").getBytes()).

Related

Getting Method threw 'javax.net.ssl.SSLException' exception

I'm trying to hit api1 which gives me a token for authentication for api2. However i'm getting this error from Connection.getOutputStream() Method threw 'javax.net.ssl.SSLException' exception.
Any idea how to fix this?
public HttpsURLConnection getHttpsURLConnection(HttpParameterSetter parameters, URL url, String method) throws IOException {
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod(method);
parameters.getHeaders().forEach(connection::setRequestProperty);
return connection;
}
public String requests(URL url) throws Exception {
url = new URL(url.toString() + "?" + parameters.toString());
HttpsURLConnection connection = getHttpsURLConnection(this.parameters, url, this.method);
connection.setDoOutput(true);
BufferedReader in = null;
DataOutputStream wr = null;
try {
if (!payload.equals("")) {
wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(this.getPayload());
wr.flush();
wr.close();
}
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder inputLine = new StringBuilder();
String line;
while ((line = in.readLine()) != null)
inputLine.append(line);
return inputLine.toString();
} catch (Exception e) {
log.error("Exception occurred during token call "+e.getMessage());
throw e;
} finally {
try{
if (wr != null)
wr.close();
}catch (Exception e){
log.error("Error occurred while closing DataOutputStream in the token call: "+e.getMessage());
}
try{
if (in != null)
in.close();
}catch (Exception e){
log.error("Error occurred while closing BufferedReader in the token call: "+e.getMessage());
}
}
}**strong text**
Does the server you are trying to connect to use a self-signed certificate?
If so, please make sure you have imported the self-signed certificate into your jre KeyStore.
Here is an example:
keytool -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -importcert -alias <alias> -file <certificate> -trustcacerts -keypass changeit -storepass changeit
<certificate> is the filename of the certificate, such as xxx.cer or xxx.crt.

PKIX path building failed: SunCertPathBuilderException: unable to find valid certification path to requested target (Java 6) using Jdeveloper

try to call rest postman service with the code below
it works fine in Java 8 but java 6 returns this error.
error returns in java 6
public class Test {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String userName = "postman";
String password = "password";
try {
String encodedCredintals =
"Basic " + Base64.encode((userName + ":" + password).getBytes());
URL url = new URL("https://postman-echo.com/basic-auth");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("GET");
// conn.setRequestProperty("Authorization", "Basic cG9zdG1hbjpwYXNzd29yZA==");
conn.setRequestProperty("Authorization", encodedCredintals);
conn.setRequestProperty("Content-Type", "application/json");
System.out.println(conn.getResponseCode() + " " + conn.getResponseMessage());
InputStream inputStream = null;
try {
inputStream = conn.getInputStream();
System.out.println(inputStream);
} catch (IOException e) {
System.out.println(e.getMessage());
}
InputStreamReader isReader = new InputStreamReader(inputStream);
//Creating a BufferedReader object
BufferedReader reader = new BufferedReader(isReader);
StringBuffer sb = new StringBuffer();
String str;
while ((str = reader.readLine()) != null) {
sb.append(str);
}
System.out.println(sb.toString());
conn.disconnect();
JSONParser parser = new JSONParser();
JSONObject jsonOject = (JSONObject) parser.parse(sb.toString());
String value = jsonOject.get("authenticated").toString();
System.out.println(value + "");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I added certificates to java 6 home through these command
keytool -import -noprompt -trustcacerts -alias postman -file C:\ME\PostmanCer.cer -keystore "C:/Program Files/Java/jdk1.6.0_45/jre/lib/security/cacerts" -storepass changeit
and check the whole list to ensure that is added successfully
keytool -list -v -keystore "C:/Program Files/Java/jdk1.6.0_45/jre/lib/security/cacerts"
and it's added.
how can I solve this issue?

SSL authentication not works in Mule ESB project (illegal_parameter)

I wrote some code which authenticates in HTTPS server over SSL. It working fine.
Now I have to move this part to my Mule ESB project.
Here is my working method:
public boolean authenticate() {
try {
System.setProperty("jsse.enableSNIExtension", "false");
System.setProperty("com.sun.net.ssl.enableECC", "false");
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(manager);
URL url = new URL("https://...");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setUseCaches(false);
con.setInstanceFollowRedirects(true);
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
// KeyStore
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("PATH/TO/.P12/file"), "P12password".toCharArray());
keyManagerFactory.init(keyStore, "P12password".toCharArray());
// ---
// TrustStore
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("PATH/TO/.JKS/file"), "JKSpassword".toCharArray());
trustManagerFactory.init(trustStore);
// ---
SSLContext context = SSLContext.getInstance("SSLv3");
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
con.setSSLSocketFactory(context.getSocketFactory());
con.getContent();
CookieStore cookieJar = manager.getCookieStore();
List<HttpCookie> cookies = cookieJar.getCookies();
for (HttpCookie cookie: cookies) {
if (COOKIE_NAME.equals(cookie.getName())) {
COOKIE_VALUE = cookie.getValue();
return true;
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
In Mule ESB project I call authenticate in processor:
#Override
public MuleEvent process(MuleEvent event) throws MuleException {
MuleMessage message = event.getMessage();
try {
String payloadString = new String(message.getPayloadAsBytes());
LOGGER.info("\nMessage payload:\n" + payloadString + "\n\n");
String xml = extractXMLFromSOAPMessage(payloadString);
LOGGER.info("\nXML: " + xml + "\n\n");
if (authenticate()) {
//send request to server
}
} catch (Exception e) {
LOGGER.error("EXCEPTION: " + e.getMessage());
e.printStackTrace();
}
return event;
}
On this line con.getContent(); exception is raised: SSLException: Received fatal alert: illegal_parameter
This error also appeared in my JAVA project. But adding these parameters helped:
System.setProperty("jsse.enableSNIExtension", "false");
System.setProperty("com.sun.net.ssl.enableECC", "false");
Both JAVA and Mule are on the same machine.
Thanks in advance!
P.S. Sorry for my english (:
Solution is turned out to be very simple.
System.setProperty not working in Mule project.
So all JVM parameters can be configured in MULE_HOME/conf/wrapper.conf.
Here is my solution:
wrapper.java.additional.16=-Djsse.enableSNIExtension=FALSE
wrapper.java.additional.17=-Dcom.sun.net.ssl.enableECC=FALSE
Thank to Vijay Pande.
Have you tried setting JVM parameters as described in mule documentation.

Exception while include .p12 file in java

I have .p12 certificate file which needs to be included in every sent to server from my java code.
When i run sample code from linux its gives me exception
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
My java code is below :
HttpsURLConnection con = null;
try
{
System.out.println("Calling webservice ..... ");
char[] passw = "mypassword".toCharArray();
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream keyInput = new FileInputStream( "/usr/local/KEYSTORE.p12");
ks.load(keyInput, passw );
keyInput.close();
System.out.println("Reading certificate file Completed");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, passw);
System.out.println("Set SSL certificate");
SSLContext sclx = SSLContext.getInstance("SSL");
sclx.init( kmf.getKeyManagers(), null, new SecureRandom());
SSLContext.setDefault(sclx);
HttpsURLConnection.setDefaultSSLSocketFactory(sclx.getSocketFactory());
URL url = new URL("https://myurl.server.com");
con = (HttpsURLConnection)url.openConnection();
System.out.println("Connection successfull");
//con.setSSLSocketFactory(sclx.getSocketFactory());
System.out.println("Token Id 026F800E-562D-4B0F-BC56-AC16895072F4");
if(con!=null)
{
System.out.println("Inside connection");
con.setRequestProperty("Content-Type","application/json;charset=utf-8");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Accept-Charset", "UTF-8");
con.setRequestProperty("Token-Id","026F800E-562D-4B0F-BC56-AC16895072F4");
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setDefaultUseCaches(false);
con.setRequestMethod("POST");
con.connect();
OutputStreamWriter os = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
os.write("request String");
os.flush();
os.close();
InputStreamReader dis = new InputStreamReader(con.getInputStream(),"UTF-8");
if (null != dis)
{
System.out.println("Reading response from webservice 1");
BufferedReader reader = new BufferedReader(dis);
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}
catch(IOException ioex)
{
System.err.println("Exception : "+ioex);
e.printStackTrace();
}
catch(Exception ex){
ex.printStackTrace();
}
finally{
if(con != null) {
con.disconnect();
}
}
Its work on windows server but gives exception on linux server.
Please any one help me to resolved this.

Connecting to remote URL which requires authentication using Java

How do I connect to a remote URL in Java which requires authentication. I'm trying to find a way to modify the following code to be able to programatically provide a username/password so it doesn't throw a 401.
URL url = new URL(String.format("http://%s/manager/list", _host + ":8080"));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
There's a native and less intrusive alternative, which works only for your call.
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
You can set the default authenticator for http requests like this:
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("username", "password".toCharArray());
}
});
Also, if you require more flexibility, you can check out the Apache HttpClient, which will give you more authentication options (as well as session support, etc.)
You can also use the following, which does not require using external packages:
URL url = new URL(“location address”);
URLConnection uc = url.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
uc.setRequestProperty ("Authorization", basicAuth);
InputStream in = uc.getInputStream();
If you are using the normal login whilst entering the username and password between the protocol and the domain this is simpler. It also works with and without login.
Sample URL: http://user:pass#example.com/url
URL url = new URL("http://user:pass#example.com/url");
URLConnection urlConnection = url.openConnection();
if (url.getUserInfo() != null) {
String basicAuth = "Basic " + new String(new Base64().encode(url.getUserInfo().getBytes()));
urlConnection.setRequestProperty("Authorization", basicAuth);
}
InputStream inputStream = urlConnection.getInputStream();
Please note in the comment, from valerybodak, below how it is done in an Android development environment.
As I have came here looking for an Android-Java-Answer I am going to do a short summary:
Use java.net.Authenticator as shown by James van Huis
Use Apache Commons HTTP Client, as in this Answer
Use basic java.net.URLConnection and set the Authentication-Header manually like shown here
If you want to use java.net.URLConnection with Basic Authentication in Android try this code:
URL url = new URL("http://www.example.com/resource");
URLConnection urlConnection = url.openConnection();
String header = "Basic " + new String(android.util.Base64.encode("user:pass".getBytes(), android.util.Base64.NO_WRAP));
urlConnection.addRequestProperty("Authorization", header);
// go on setting more request headers, reading the response, etc
Was able to set the auth using the HttpsURLConnection
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
String userpass = username + ":" + password;
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
//httpsurlconnection
conn.setRequestProperty("Authorization", basicAuth);
few of the changes fetched from this post. and Base64 is from java.util package.
Be really careful with the "Base64().encode()"approach, my team and I got 400 Apache bad request issues because it adds a \r\n at the end of the string generated.
We found it sniffing packets thanks to Wireshark.
Here is our solution :
import org.apache.commons.codec.binary.Base64;
HttpGet getRequest = new HttpGet(endpoint);
getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding());
private String getBasicAuthenticationEncoding() {
String userPassword = username + ":" + password;
return new String(Base64.encodeBase64(userPassword.getBytes()));
}
Hope it helps!
Use this code for basic authentication.
URL url = new URL(path);
String userPass = "username:password";
String basicAuth = "Basic " + Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);//or
//String basicAuth = "Basic " + new String(Base64.encode(userPass.getBytes(), Base64.No_WRAP));
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Authorization", basicAuth);
urlConnection.connect();
Since Java 9, you can do this
URL url = new URL("http://www.example.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setAuthenticator(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("USER", "PASS".toCharArray());
}
});
I'd like to provide an answer for the case that you do not have control over the code that opens the connection. Like I did when using the URLClassLoader to load a jar file from a password protected server.
The Authenticator solution would work but has the drawback that it first tries to reach the server without a password and only after the server asks for a password provides one. That's an unnecessary roundtrip if you already know the server would need a password.
public class MyStreamHandlerFactory implements URLStreamHandlerFactory {
private final ServerInfo serverInfo;
public MyStreamHandlerFactory(ServerInfo serverInfo) {
this.serverInfo = serverInfo;
}
#Override
public URLStreamHandler createURLStreamHandler(String protocol) {
switch (protocol) {
case "my":
return new MyStreamHandler(serverInfo);
default:
return null;
}
}
}
public class MyStreamHandler extends URLStreamHandler {
private final String encodedCredentials;
public MyStreamHandler(ServerInfo serverInfo) {
String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword();
this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes());
}
#Override
protected URLConnection openConnection(URL url) throws IOException {
String authority = url.getAuthority();
String protocol = "http";
URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile());
HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection();
connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
return connection;
}
}
This registers a new protocol my that is replaced by http when credentials are added. So when creating the new URLClassLoader just replace http with my and everything is fine. I know URLClassLoader provides a constructor that takes an URLStreamHandlerFactory but this factory is not used if the URL points to a jar file.
i did that this way you need to do this just copy paste it be happy
HttpURLConnection urlConnection;
String url;
// String data = json;
String result = null;
try {
String username ="user#gmail.com";
String password = "12345678";
String auth =new String(username + ":" + password);
byte[] data1 = auth.getBytes(UTF_8);
String base64 = Base64.encodeToString(data1, Base64.NO_WRAP);
//Connect
urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "Basic "+base64);
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
JSONObject obj = new JSONObject();
obj.put("MobileNumber", "+97333746934");
obj.put("EmailAddress", "danish.hussain#example.com");
obj.put("FirstName", "Danish");
obj.put("LastName", "Hussain");
obj.put("Country", "BH");
obj.put("Language", "EN");
String data = obj.toString();
//Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(data);
writer.close();
outputStream.close();
int responseCode=urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
}else {
// return new String("false : "+responseCode);
new String("false : "+responseCode);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
ANDROD IMPLEMENTATION
A complete method to request data/string response from web service requesting authorization with username and password
public static String getData(String uri, String userName, String userPassword) {
BufferedReader reader = null;
byte[] loginBytes = (userName + ":" + userPassword).getBytes();
StringBuilder loginBuilder = new StringBuilder()
.append("Basic ")
.append(Base64.encodeToString(loginBytes, Base64.DEFAULT));
try {
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", loginBuilder.toString());
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine())!= null){
sb.append(line);
sb.append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (null != reader){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Categories

Resources