How to obtain all TLS sessions from SSLContext using IBMJSSE2 default provider? - java

I'm using as default provided for TLS connections the IBMJSSEProvider2 and I have the following code to show information regarding the TLS sessions:
SSLSessionContext sslSessionContext = SSLContext.getDefault().getClientSessionContext();
Enumeration<byte[]> sessionIds = sslSessionContext.getIds();
while (sessionIds.hasMoreElements()) {
SSLSession sslSession = sslSessionContext.getSession(sessionIds.nextElement());
writer.write("Client: " + sslSession.getPeerHost() + ":" + sslSession.getPeerPort() + "\n");
writer.write("\tProtocol: " + sslSession.getProtocol() + "\n");
writer.write("\tSessionID: " + byteArrayToHex(sslSession.getId()) + "\n");
writer.write("\tCipherSuite: " + sslSession.getCipherSuite() + "\n");
for (X509Certificate certificate : sslSession.getPeerCertificateChain()) {
writer.write("\tX509 Certificate: " + certificate.getSubjectDN() + "\n");
writer.write("\t\tIssuer: " + certificate.getIssuerDN().getName() + "\n");
writer.write("\t\tAlgorithm: " + certificate.getSigAlgName() + "\n");
writer.write("\t\tValidity: " + certificate.getNotAfter() + "\n");
}
}
The code above is running on an instance of WebSphere 8.5. When I run this algorithm it doesn't print any information about the connections I had made to any HTTPS URLs using a RestTemplate implementation from Spring 3.2.
Using other providers like from Oracle shows the information. Am I missing something to make it work?
I'm trying to make a simple solution to troubleshoot which TLS versions are supported by a live instance of WebSphere. This is, of course, not recommended for live clients.

The problem was that, probably, the underlying libraries are not using the default context on WebSphere. Therefore, I had to create a custom client to make it using a specific SSLContext so I can list all the information I need. Following is the code to achieve this:
private static String URL = "https://www.google.com";
private static String TRUST_STORE_FILE = "/Users/xpto/trust.p12";
private static String TRUST_STORE_PASS = "truststore";
private static String TRUST_STORE_TYPE = "PKCS12";
private static String TLS_VERSION = "TLSv1.2";
public static void main(String[] args) throws Exception {
KeyStore keyStore = KeyStore.getInstance(TRUST_STORE_TYPE);
keyStore.load(new FileInputStream(TRUST_STORE_FILE), TRUST_STORE_PASS.toCharArray());
SSLContext sslContext = SSLContexts
.custom()
.loadTrustMaterial(keyStore)
.useProtocol(TLS_VERSION)
.build();
HttpComponentsClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory(HttpClients
.custom()
.setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
.build());
RestTemplate restTemplate = new RestTemplate(clientFactory);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
print("Requesting: " + URL);
ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.GET, requestEntity, String.class);
print("Response: " + response.getBody());
printSSLContextInfo(sslContext);
}
private static void printSSLContextInfo(SSLContext sslContext) throws Exception {
print("-------------\nPrinting TLS Client Information");
SSLSessionContext sslSessionContext = sslContext.getClientSessionContext();
Enumeration<byte[]> sessionIds = sslSessionContext.getIds();
while (sessionIds.hasMoreElements()) {
SSLSession sslSession = sslSessionContext.getSession(sessionIds.nextElement());
print("Client: " + sslSession.getPeerHost() + ":" + sslSession.getPeerPort());
print("\tProtocol: " + sslSession.getProtocol());
print("\tSessionID: " + byteArrayToHex(sslSession.getId()));
print("\tCipherSuite: " + sslSession.getCipherSuite());
for (X509Certificate certificate : sslSession.getPeerCertificateChain()) {
print("\tX509 Certificate: " + certificate.getSubjectDN());
print("\t\tIssuer: " + certificate.getIssuerDN().getName());
print("\t\tAlgorithm: " + certificate.getSigAlgName());
print("\t\tValidity: " + certificate.getNotAfter());
}
}
}
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for (byte b : a)
sb.append(String.format("%02x", b));
return sb.toString();
}
public static void print(Object msg) {
System.out.println(msg);
}

Related

Oauth2 authentication with Private Key C#

I am attempting to authenticate via Oauth2 to an API however, I had trouble creating the request because of a private key. I was provided a sample code by the vendor which is Java and I converted it over to C# but I can't seem to get the private key into the JWT request.
Side note, the client, secret and URL's have been masked for this example.
Working Java code
public class Test {
private static final String RSSO_URL = "https://test-dev.onbmc.com/rsso";
private static final String CLIENT_ID = "36fa1bd2-6f92-408e-b7e4-dd4df7a9cfaz";
private static final String CLIENT_SECRET = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjBgEAAoIBAQC169y6kMo/hZ/3oRFKwU1bxmzCJhWgH54j3Vn1JW4SmgO3rH5bHkVcqt03aaQmQms/fBDe2SlCKS3pxH6pVXB8aKQj8EOPWstwjvjsQrCiKLyqAMbc6E7IBVp1Dq77wFtv+P3fk80/9OA4a6ahr9Dp14+3YawyOU/5Ebf/i2WwKkySTgQOGLXvk3+LtsoODubMAnyJYWb6e+Uhrbn/vSqlGDDjGtANahw5oWjqFy8IYFttzMNB0VF2+sKIzGvQ+Izlo+u4wTgN7pB5g8bSz9Q92QzeWRVh7OCaef3L0i6Ozp3rO46bo3+G+QJdn4UKPcYMubtNGMC511aDU8Yay4IPAgMBAAECggEAMGTwMQk3ZDKN3XgRe4t0osdCNlufQRtoHC5UMeylHXmvJ3tRmbexx/cdqwgxTKQ6l4bPjhjC6wC9YASPlUhPRikoEQ9nSYljuSuveFo9VsXzel3+iOGbo4YZDC69yebf7CeWkZVl8m+X/ipVB4oXzz0y1Bu9jRbF+YIHKonQoU4MgsQQrYa8J8cSx75fkByNj9HdQtd99aK2jsMSArQ1R+PnUjDWpxlZBAowRmaw6iPWJbHmhLUSyrIvBJOo3fNZlXPS/S8jL5s0n137K640WFjy5LBakooHqmjfaFk/5z5krBaWaehDXU2AXLcKRQi946QhC99leSxBTastfjIh0QKBgQDZDZRME+GvJwnnMOht0BuVjcazCkY5LcfxD4vwQeK8p7zyqaxcvNu0+0ulKy+kqP6d/Q1ITIXlQDEA8a2d/iiOhSI84Y/g9az9ZSvRHH/Z5gRdRrymZJcqCzzpxjqi0uvaKOQUWwrKthnxnAS+1oJPlqOc1CtO/j4qzc7I2D7VxQKBgQDWkH5YTYLM5EWos1zdEmVqnIrUYbKlkyHJWSYnC/f5VsOoVEV4R1012w3HfwPceRjYOxeUtHTPN3MB9B5Xn5d3oBFBk8Md9phD5St9KXGakPY0sWC1yFEg8/Zr9fVm5jren6tJQmhKEeiV6DtueqQShEVVIEJixrQQkwFQ4SvJwwKBgCKh+Qyei38gEoNyGVQURaJ6Sb8dn5DWDjYXjfOa/6usdAigLCFr/P6Grk4/cs2qLV5WFz13AFJRCMCmz1YLTLtY4Nqn/wYdDSotb21hR8Ej44Rimg1OtZP+0QxYFdkPIJThu2rIEBPCNKeJhnRQ0+ARIDAQ5ownIxI/XoRLhNMlAoGAQl9mRgiMKrd+eOYrFtPm/Wi5ZWNncOKns/JY5AFGzyGw2rRe3QsuYUeG5qx61Eu9jL4S2FROQf+EGxmZ/T8ICuBAFkoQNIegqHgO0OPuGYM4NiqcoP77Ybc2BkWKiS81DMLVqI7bVfZePWkeYVmcwYGbNO8KuiV/dBUVdiCBfCMCgYEAoUvJefM+ENuhnxrH6A+4lEH4CI64gkQ5tkF3JeAMCiIov5OEuJx+65ULXeAwhrvcLB3Ginh0hI2RNQGV5iOeu0+sHmNA8yt0ivoCweNxiPM0RGWcH5FFBzI88WlGbMl0eg3NHt9jV5yTwNJYonjPFgCUkasaclhDZlZxgN891LA=";
private static final String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhY8LmtZ7fZOAX\n" +
"gw7SKyHzZ6Q0H0ss+3cJ7NEkEofUN2IfycE5u6eQb396uN16bzZaQcwnK9He3xwk\n" +
"3H4wWLzOUlhfuo87bJ34VdNBa1hfAk4iyk1ZgyufGy6MKgwycXhIl9wibX/f1fmF\n" +
"khHnkXVyYY5hSewceCT51bMzcv+psGf7KkN8jh/bRb+/GGfxVy13GKfFTzwY1Y7G\n" +
"SH7J00EaUQsEVCbkV3HK185v6t1fb2faao2imgj/Xqzc/DBbConBoF8/89SJSuf9\n" +
"1RVGdctNwqerMOUoDJ2ynHNqhbO3POq6O1XMi0c75q4xdtrNWLa8A5ONPUXDgIo/\n" +
"Ddwj1tTNAgMBAAECggEACG83yXNtfRWkzyxv3wyPKjEsM2kiYo4Mf9oVX4C0BYyH\n" +
"BwKBURxFIoIRprGJVD4aLhl9PtAEfA8kWfrIXB3N/viU5wwvtP0VEkh/7dhLB88p\n" +
"xmKEr39ZoAwf203tg+u8IRdRvRYU7Xbv7gAv3FcUqpGdBuYByHT0iUbmfFvm1l46\n" +
"HD2ypQFKr3a536w2sFR6XKK6G+Al69lyg0Hg4jXmmDMo+xoxqrJeYxT11G6iBWmy\n" +
"UXKDdOVx4BarT+dcnCUP0yahmQz08XObNDNphWG/aOFF6cMyU4hNkK9q0AC6sAzQ\n" +
"89dTVTPErjEJcJZ16mtI9nv5u4VKfbL1mU+ivb4pQQKBgQD+FdFx+BKojVYilT1i\n" +
"WMbXabRtm03NezgzSgIDKTxiewoQAy+n+InGPy2pz18/1DP8kasnsU8VZvRM7dXV\n" +
"lJTXrqOM/lMN8vMt7/fpz0PYEDP6Qz7CLxA0xEcW2qFR4RAQzq3xXIH/7M4VUZzD\n" +
"qzznD8aJaG5fsSExt7aITU984QKBgQDjFpVsxDxF3YZBhonuNaSrvTdDwbMqdCLT\n" +
"ZoXUL+4aKY78cD2FCfdqJ5O1uyrAqgCgjouiVnNRzDy3qSSGxaiwpI3+FA8cCNiS\n" +
"W0CE/urjDDeXU0Q5jDSBdljBF23wf9mNmXpgXSHfgQVTIiVMVD5tNhU/ORu5PXzo\n" +
"SdW67DLJbQKBgDYYbRQnrclG9hy8y2nh3svEDI70bq4d2tRIoG8N23ZYHcdU9lN7\n" +
"vdGAZ/dsWCodwse2N8tmm6DB36d1R36GeL4Gx3lgOEyS+iVAnvafkyEwKfDRWk47\n" +
"eObTFxONjqUBFsuNRUlK2b6kKygszQR3s6q6GBnvKviinJ+aLnmMhCzhAoGBAKLC\n" +
"gP6f87/kcmFsiFePYyMkTwPlRQDclEloZesbH1DpEG6mE7HS3t3a1+ec6puEPUbW\n" +
"ZAZKaATsmWgZdvCRosJYbtz4i4vQW0kq1id8feWV1BJJv9BvSQKxTBO5Mzb4q3jt\n" +
"0+RVW/3Rf3uCMbFvf/7OkJPr3o76HxhuMx3yRMRRAoGAZiFbVjd3EKUdyE0O3QSh\n" +
"46KzTdT0ENhBlN2dpCdJjHJm3Lcxa7uY4sxa8NqYUW0NO2qRSd42IKfGX3qqi7wf\n" +
"+rUFFixCzQOoucR/ekTw+542Nbc0QejAQ0SUDwgHWX8L8Yi+W3UsBL2YLLIw5ged\n" +
"7Ghsl3cgdKPMlAh1kzxsWic=";
public static JsonPath getOAuthToken() throws InvalidKeySpecException, NoSuchAlgorithmException {
return with().log().all()
.contentType(ContentType.URLENC)
.formParam("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")
.formParam("assertion", getClientJwt())
.formParam("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
.formParam("redirect_uri", "https://test-dev-restapi.us.onbmc.com/api/jwt/login")
.formParam("audience", "test-dev-restapi.us.onbmc.com")
.formParam("client_id", CLIENT_ID)
.formParam("client_secret", CLIENT_SECRET)
.when()
.post(RSSO_URL + "/oauth2/token")
.then()
.log().all()
.statusCode(HttpURLConnection.HTTP_OK)
.extract()
.response()
.getBody()
.jsonPath();
}
static String getClientJwt() throws InvalidKeySpecException, NoSuchAlgorithmException {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 1);
return Jwts.builder()
.signWith(loadPrivateKey(PRIVATE_KEY))
.setIssuer(CLIENT_ID)
.setSubject("JWT")
.setAudience("test-dev-restapi.us.onbmc.com")
.setExpiration(calendar.getTime())
.compact();
}
static PrivateKey loadPrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(privateKeyStr));
return kf.generatePrivate(keySpecPKCS8);
}
//#Test
public void getOauthAccessTokenUsingJwtGrantType() throws Exception {
System.out.println("Trying to get OAuth Access and Refresh tokens");
JsonPath response = getOAuthToken();
System.out.println("Access Token = " + response.getString("access_token"));
System.out.println("Refresh Token = " + response.getString("refresh_token"));
System.out.println("Expires in = " + response.getString("expires_in"));
System.out.println("OAuth2 Token was successfully obtained.");
}
public static void main(String str[]) throws Exception {
JsonPath response = getOAuthToken();
}
}
Converted Java code to C#
using java.security;
using java.security.spec;
using JWT;
using JWT.Algorithms;
using JWT.Builder;
using JWT.Serializers;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Authenticators;
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace TestApp
{
class Program
{
private static string RSSO_URL = "https://test-dev.onbmc.com/rsso";
`enter code here`private static string CLIENT_ID = "36fa1bd2-6f92-408e-b7e4-dd4df7a9cfaz";
private static string CLIENT_SECRET = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjBgEAAoIBAQC169y6kMo/hZ/3oRFKwU1bxmzCJhWgH54j3Vn1JW4SmgO3rH5bHkVcqt03aaQmQms/fBDe2SlCKS3pxH6pVXB8aKQj8EOPWstwjvjsQrCiKLyqAMbc6E7IBVp1Dq77wFtv+P3fk80/9OA4a6ahr9Dp14+3YawyOU/5Ebf/i2WwKkySTgQOGLXvk3+LtsoODubMAnyJYWb6e+Uhrbn/vSqlGDDjGtANahw5oWjqFy8IYFttzMNB0VF2+sKIzGvQ+Izlo+u4wTgN7pB5g8bSz9Q92QzeWRVh7OCaef3L0i6Ozp3rO46bo3+G+QJdn4UKPcYMubtNGMC511aDU8Yay4IPAgMBAAECggEAMGTwMQk3ZDKN3XgRe4t0osdCNlufQRtoHC5UMeylHXmvJ3tRmbexx/cdqwgxTKQ6l4bPjhjC6wC9YASPlUhPRikoEQ9nSYljuSuveFo9VsXzel3+iOGbo4YZDC69yebf7CeWkZVl8m+X/ipVB4oXzz0y1Bu9jRbF+YIHKonQoU4MgsQQrYa8J8cSx75fkByNj9HdQtd99aK2jsMSArQ1R+PnUjDWpxlZBAowRmaw6iPWJbHmhLUSyrIvBJOo3fNZlXPS/S8jL5s0n137K640WFjy5LBakooHqmjfaFk/5z5krBaWaehDXU2AXLcKRQi946QhC99leSxBTastfjIh0QKBgQDZDZRME+GvJwnnMOht0BuVjcazCkY5LcfxD4vwQeK8p7zyqaxcvNu0+0ulKy+kqP6d/Q1ITIXlQDEA8a2d/iiOhSI84Y/g9az9ZSvRHH/Z5gRdRrymZJcqCzzpxjqi0uvaKOQUWwrKthnxnAS+1oJPlqOc1CtO/j4qzc7I2D7VxQKBgQDWkH5YTYLM5EWos1zdEmVqnIrUYbKlkyHJWSYnC/f5VsOoVEV4R1012w3HfwPceRjYOxeUtHTPN3MB9B5Xn5d3oBFBk8Md9phD5St9KXGakPY0sWC1yFEg8/Zr9fVm5jren6tJQmhKEeiV6DtueqQShEVVIEJixrQQkwFQ4SvJwwKBgCKh+Qyei38gEoNyGVQURaJ6Sb8dn5DWDjYXjfOa/6usdAigLCFr/P6Grk4/cs2qLV5WFz13AFJRCMCmz1YLTLtY4Nqn/wYdDSotb21hR8Ej44Rimg1OtZP+0QxYFdkPIJThu2rIEBPCNKeJhnRQ0+ARIDAQ5ownIxI/XoRLhNMlAoGAQl9mRgiMKrd+eOYrFtPm/Wi5ZWNncOKns/JY5AFGzyGw2rRe3QsuYUeG5qx61Eu9jL4S2FROQf+EGxmZ/T8ICuBAFkoQNIegqHgO0OPuGYM4NiqcoP77Ybc2BkWKiS81DMLVqI7bVfZePWkeYVmcwYGbNO8KuiV/dBUVdiCBfCMCgYEAoUvJefM+ENuhnxrH6A+4lEH4CI64gkQ5tkF3JeAMCiIov5OEuJx+65ULXeAwhrvcLB3Ginh0hI2RNQGV5iOeu0+sHmNA8yt0ivoCweNxiPM0RGWcH5FFBzI88WlGbMl0eg3NHt9jV5yTwNJYonjPFgCUkasaclhDZlZxgN891LA=";
private static string PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhY8LmtZ7fZOAX\n" +
"gw7SKyHzZ6Q0H0ss+3cJ7NEkEofUN2IfycE5u6eQb396uN16bzZaQcwnK9He3xwk\n" +
"3H4wWLzOUlhfuo87bJ34VdNBa1hfAk4iyk1ZgyufGy6MKgwycXhIl9wibX/f1fmF\n" +
"khHnkXVyYY5hSewceCT51bMzcv+psGf7KkN8jh/bRb+/GGfxVy13GKfFTzwY1Y7G\n" +
"SH7J00EaUQsEVCbkV3HK185v6t1fb2faao2imgj/Xqzc/DBbConBoF8/89SJSuf9\n" +
"1RVGdctNwqerMOUoDJ2ynHNqhbO3POq6O1XMi0c75q4xdtrNWLa8A5ONPUXDgIo/\n" +
"Ddwj1tTNAgMBAAECggEACG83yXNtfRWkzyxv3wyPKjEsM2kiYo4Mf9oVX4C0BYyH\n" +
"BwKBURxFIoIRprGJVD4aLhl9PtAEfA8kWfrIXB3N/viU5wwvtP0VEkh/7dhLB88p\n" +
"xmKEr39ZoAwf203tg+u8IRdRvRYU7Xbv7gAv3FcUqpGdBuYByHT0iUbmfFvm1l46\n" +
"HD2ypQFKr3a536w2sFR6XKK6G+Al69lyg0Hg4jXmmDMo+xoxqrJeYxT11G6iBWmy\n" +
"UXKDdOVx4BarT+dcnCUP0yahmQz08XObNDNphWG/aOFF6cMyU4hNkK9q0AC6sAzQ\n" +
"89dTVTPErjEJcJZ16mtI9nv5u4VKfbL1mU+ivb4pQQKBgQD+FdFx+BKojVYilT1i\n" +
"WMbXabRtm03NezgzSgIDKTxiewoQAy+n+InGPy2pz18/1DP8kasnsU8VZvRM7dXV\n" +
"lJTXrqOM/lMN8vMt7/fpz0PYEDP6Qz7CLxA0xEcW2qFR4RAQzq3xXIH/7M4VUZzD\n" +
"qzznD8aJaG5fsSExt7aITU984QKBgQDjFpVsxDxF3YZBhonuNaSrvTdDwbMqdCLT\n" +
"ZoXUL+4aKY78cD2FCfdqJ5O1uyrAqgCgjouiVnNRzDy3qSSGxaiwpI3+FA8cCNiS\n" +
"W0CE/urjDDeXU0Q5jDSBdljBF23wf9mNmXpgXSHfgQVTIiVMVD5tNhU/ORu5PXzo\n" +
"SdW67DLJbQKBgDYYbRQnrclG9hy8y2nh3svEDI70bq4d2tRIoG8N23ZYHcdU9lN7\n" +
"vdGAZ/dsWCodwse2N8tmm6DB36d1R36GeL4Gx3lgOEyS+iVAnvafkyEwKfDRWk47\n" +
"eObTFxONjqUBFsuNRUlK2b6kKygszQR3s6q6GBnvKviinJ+aLnmMhCzhAoGBAKLC\n" +
"gP6f87/kcmFsiFePYyMkTwPlRQDclEloZesbH1DpEG6mE7HS3t3a1+ec6puEPUbW\n" +
"ZAZKaATsmWgZdvCRosJYbtz4i4vQW0kq1id8feWV1BJJv9BvSQKxTBO5Mzb4q3jt\n" +
"0+RVW/3Rf3uCMbFvf/7OkJPr3o76HxhuMx3yRMRRAoGAZiFbVjd3EKUdyE0O3QSh\n" +
"46KzTdT0ENhBlN2dpCdJjHJm3Lcxa7uY4sxa8NqYUW0NO2qRSd42IKfGX3qqi7wf\n" +
"+rUFFixCzQOoucR/ekTw+542Nbc0QejAQ0SUDwgHWX8L8Yi+W3UsBL2YLLIw5ged\n" +
"7Ghsl3cgdKPMlAh1kzxsWic=";
static void Main(string[] args)
{
try
{
//create RestSharp client and POST request object
var client = new RestClient(RSSO_URL + "/oauth2/token");
var request = new RestRequest();
request.Method = Method.Post;
client.Authenticator = new HttpBasicAuthenticator(CLIENT_ID, CLIENT_SECRET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
request.AddParameter("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
request.AddParameter("redirect_uri", "https://test-dev-restapi.us.onbmc.com/api/jwt/login");
request.AddParameter("audience", "test-dev-restapi.us.onbmc.com");
request.AddParameter("client_id", CLIENT_ID);
request.AddParameter("client_secret", CLIENT_SECRET);
request.AddParameter("assertion", Program.getClientJwt());
RestResponse response = client.Execute(request);
//return an AccessToken
var poo = JsonConvert.DeserializeObject(response.Content);
}
catch(Exception ex)
{
}
}
public static string getClientJwt() {
DateTime exp = DateTime.UtcNow.AddYears(1);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(PRIVATE_KEY));
var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var token = new JwtSecurityToken(CLIENT_ID, "miamidade-dev-restapi.us.onbmc.com", null, null, DateTime.UtcNow.AddYears(1), signIn);
return new JwtSecurityTokenHandler().WriteToken(token);
}
public static PrivateKey loadPrivateKey(String privateKeyStr)
{
KeyFactory kf = KeyFactory.getInstance("RSA");
byte[] decodedBytes = Convert.FromBase64String(privateKeyStr);
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(decodedBytes);
return kf.generatePrivate(keySpecPKCS8);
}
}
}
When I send the request, I get the error
{"error_description":"Not valid request, JWT is rejected","error":"invalid_grant"}

java.lang.NoSuchMethodError: okhttp3.internal.Internal.initializeInstanceForTests() When creating a Mock Server on Android

java.lang.NoSuchMethodError: okhttp3.internal.Internal.initializeInstanceForTests() When creating a Mock Server on Android
I tried to update the dependency but it did not work.
I am new to Android Unit testing and I want to test if the API call is successful or not. I am working on the Open Source Project on https://github.com/commons-app/apps-android-commons (leaderboard branch)
java.lang.NoSuchMethodError: okhttp3.internal.Internal.initializeInstanceForTests()V
at okhttp3.mockwebserver.MockWebServer.<clinit>(MockWebServer.java:103)
at fr.free.nrw.commons.leaderboard.LeaderboardApiTest.initTest(LeaderboardApiTest.java:35)
public class LeaderboardApiTest {
MockWebServer server;
#Before
public void initTest() {
server = new MockWebServer();
}
#Before
public void setUp() throws IOException {
server.enqueue(new MockResponse().setBody("{\n"
+ " \"status\": 200,\n"
+ " \"username\": \"user\",\n"
+ " \"category_count\": 0,\n"
+ " \"limit\": null,\n"
+ " \"avatar\": \"avatar\",\n"
+ " \"offset\": null,\n"
+ " \"duration\": \"all_time\",\n"
+ " \"leaderboard_list\": [\n"
+ " {\n"
+ " \"username\": \"user\",\n"
+ " \"category_count\": 0,\n"
+ " \"avatar\": \"avatar\",\n"
+ " \"rank\": 1\n"
+ " }\n"
+ " ],\n"
+ " \"category\": \"used\",\n"
+ " \"rank\": 1\n"
+ "}"));
server.start();
}
#Test
public void apiTest() throws IOException, JSONException {
HttpUrl httpUrl = HttpUrl.parse(NetworkingModule.TEST_TOOLS_FORGE_URL);
LeaderboardResponse response = sendRequest(new OkHttpClient(), httpUrl);
Assert.assertEquals("avatar", response.getAvatar());
Assert.assertEquals("username", response.getUsername());
Assert.assertEquals(Integer.valueOf(0), response.getRank());
Assert.assertEquals(Integer.valueOf(0), response.getCategoryCount());
}
private LeaderboardResponse sendRequest(OkHttpClient okHttpClient, HttpUrl httpUrl)
throws IOException, JSONException {
Request request = new Builder().url(httpUrl).build();
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
Gson gson = new Gson();
return gson.fromJson(response.body().toString(), LeaderboardResponse.class);
}
return null;
}
#After
public void shutdown() throws IOException {
server.shutdown();
}
}
Updating the Okhttp version fixed the problem
configurations.all {
exclude module: 'okhttp-ws'
}
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
implementation 'com.squareup.okhttp3:okhttp-ws:3.4.1'
testImplementation "com.squareup.okhttp3:mockwebserver:4.8.0"
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.8.0'

Testing the existence of a File using Apache Camel

I want to test if a given file exists at a remote SFTP server using Apache Camel.
The method has to return true if exists, false if not and an Exception in case
the client cannot get connected (timeout, wrong username/password, etc).
In fact to test if I can get logged in to the server is not a major problem
to test if the given file exists. Just send a request to the SFTP server, download=false and noop=true
and this is pretty much what it has to be done. An empty file will be downloaded to my TMP directory
in case the file exists, no file will be downloaded. In case I cannot logged in to the server an own Exception is thrown
(CannotConnectException).
My point is that I cannot catch this exception at my client.
I am pretty sure I am doing something wrong, but I do not know what.
I was thinking as a work around to set some error value in returned file is case I cannot get connected, but
this looks like a "hack" to me. Is there any way to catch the thrown exception? If not, what is the best way to
get an Exception my client in case I cannot get connected?
My code is as follows:
public final class MyFtpClient {
private static final Logger LOG = LoggerFactory.getLogger(MyFtpClient.class);
// Client settings
static String localPath = File.separator + "tmp";
public enum Existence{
EXIST, NOT_EXIST, UNKNOWN
}
private MyFtpClient() {
}
private static Existence doesFileExistAtServer(Main main, String protocol, String user, String password,
String server, int port, String filePathAtServer, String filenameAtServer, String localPath)
{
boolean fileExist = false;
try {
main.addRouteBuilder(new MyFtpClientRouteBuilder(protocol, user, password, server, port, filePathAtServer,
filenameAtServer, localPath));
main.start();
Thread.sleep(5000);
main.stop();
String filePath = localPath + File.separator + filenameAtServer;
File f = new File(filePath);
fileExist = f.exists();
if (fileExist) {
f.delete(); // Just delete it.
return Existence.EXIST;
} else {
return Existence.NOT_EXIST;
}
// I CANNOT CATCH THIS EXCEPTION
} catch (Exception e) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Cannot Connect to the Sftp Server " + server);
LOG.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Cannot Connect to the Sftp Server " + server);
LOG.info(e.getMessage());
return Existence.UNKNOWN;
}
}
public static void main(String[] args) throws Exception {
String protocol = "sftp";
int port = 22;
String server;
String user;
String password;
String filePathAtServer;
String filenameAtServer;
boolean fileExist;
Main main = new Main();
server = "unknown.com";
user = "demo";
password = "password";
filePathAtServer = "/";
filenameAtServer = "readme.txt";
doesFileExistAtServer(main, protocol, user, password, server, port, filePathAtServer, filenameAtServer, localPath);
LOG.info("\nThe accesibility of the file 1 " + filenameAtServer + " at the server " + server + " is " + fileExist + "\n")
}
Whereas my RouteBuilder looks as follows:
public class MyFtpClientRouteBuilder extends RouteBuilder {
private static final Logger LOG =
LoggerFactory.getLogger(MyFtpClientRouteBuilder.class);
String protocol = "sftp";
int port = 22;
String server;
String user;
String password;
String filePathAtServer;
String filenameAtServer;
String localPath;
boolean fileExist;
public MyFtpClientRouteBuilder(String protocol, String user, String password, String server, int port,
String filePathAtServer, String filenameAtServer, String localPath) {
super();
this.protocol = protocol;
this.user = user;
this.password = password;
this.server = server;
this.port = port;
this.filePathAtServer = filePathAtServer;
this.filenameAtServer = filenameAtServer;
this.localPath = localPath;
}
private static String generateFromUri(String protocol, String user, String password, String server, int port,
String path, String filename) {
final String downloadFalse = "download=false"; // NO, DO NOT Download the file
final String fastExistsCheck = "fastExistsCheck=true";
final String doNothing = "noop=true"; // Just connect, but DO NOTHING
final String connectFail = "throwExceptionOnConnectFailed=true"; // Just in case a connection fails
final String maxReconnect = "maximumReconnectAttempts=0";
final String bridgeError = "consumer.bridgeErrorHandler=true";
return protocol + "://" + user + "#" + server + ":" + port + path + "?" + "fileName=" + filename + "&"
+ downloadFalse + "&"
+ "password=" + password
+ "&" + fastExistsCheck
+ "&" + connectFail
+ "&" + doNothing
+ "&" + maxReconnect
+ "&" + bridgeError;
}
private static String generateLocalUri(String path) {
final String protocol = "file";
final String allowNullBody = "allowNullBody=true";
final String doNothing = "noop=true";
final String fileExist = "fileExist=move";
final String moveExisting = "moveExisting=oldFile";
return protocol + ":" + path + "?" + allowNullBody + "&" + doNothing + "&" + fileExist + "&" + moveExisting;
}
#Override
public void configure() throws CannotConnectException {
final String fromSftpServer = generateFromUri(protocol, user, password, server, port, filePathAtServer, filenameAtServer);
LOG.info("From: " + fromSftpServer);
final String toLocal = generateLocalUri(localPath);
LOG.info("To: " + toLocal);
onException(GenericFileOperationFailedException.class, JSchException.class)
//.handled(true)
.throwException(new CannotConnectException("Cannot connect to the remote SFTP server " + server))
.log("Cannot connect to the remote SFTP server " + server)
.maximumRedeliveries(0)
.to(toLocal)
.continued(false) // Either handled(true) or continue(false) but NOT both together
.end();
from(fromSftpServer).to(toLocal);
}
}

Make a connection to ASI Granite

I need to make a connection to the Granite Database using the ASI installed on the WebLogic application server 10.3.6.
The programming language is Java:
public void connect() throws Exception {
if (prop != null) {
ConnectionFactoryASI.setProtocol(prop);
ConnectionFactoryASI.setDataObjectFactoryType(prop);
serviceFactory = ConnectionFactoryASI.getServiceFactory(prop);
} else {
serviceFactory = ConnectionFactoryASI.getServiceFactory(user);
}
dataObjectFactory = serviceFactory.getDataObjectFactory();
setUser(serviceFactory.getClientSession().getLoginName());
logger.debug("ASI HostName: " + serviceFactory.getClientSession().getHostName()
+ ", DatabaseName: " + serviceFactory.getClientSession().getDatabaseName()
+ ", DbHostName: " + serviceFactory.getClientSession().getDbHostName());
}
It does not connect and gives me a connection error.
the ASI need a connection ticketName, without which you can not open a connection.
Here is the correct code, I added the parameter written above:
public void connect(String ticketName) throws Exception {
if (prop != null) {
ConnectionFactoryASI.setProtocol(prop);
ConnectionFactoryASI.setDataObjectFactoryType(prop);
serviceFactory = ConnectionFactoryASI.getServiceFactory(prop, ticketName);
} else {
serviceFactory = ConnectionFactoryASI.getServiceFactory(ticketName, user);
}
dataObjectFactory = serviceFactory.getDataObjectFactory();
setUser(serviceFactory.getClientSession().getLoginName());
logger.debug("ASI HostName: " + serviceFactory.getClientSession().getHostName()
+ ", DatabaseName: " + serviceFactory.getClientSession().getDatabaseName()
+ ", DbHostName: " + serviceFactory.getClientSession().getDbHostName());
}

XMPP with Java Asmack library supporting X-FACEBOOK-PLATFORM

I'm trying to make a Facebook Chat on Android with the Smack library. I've read the Chat API from Facebook, but I cannot understand how I have to authenticate with Facebook using this library.
Can anyone point me how to accomplish this?
Update: According to the no.good.at.coding answer, I have this code adapted to the Asmack library. All works fine except I receive as response to the login: not-authorized. Here is the code I use:
public class SASLXFacebookPlatformMechanism extends SASLMechanism
{
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String applicationSecret = "";
private String sessionKey = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication)
{
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException
{
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
#Override
public void authenticate(String apiKeyAndSessionKey, String host,
String applicationSecret) throws IOException, XMPPException
{
if (apiKeyAndSessionKey == null || applicationSecret == null)
{
throw new IllegalArgumentException("Invalid parameters");
}
String[] keyArray = apiKeyAndSessionKey.split("\\|", 2);
if (keyArray.length < 2)
{
throw new IllegalArgumentException(
"API key or session key is not present");
}
this.apiKey = keyArray[0];
Log.d("API_KEY", apiKey);
this.applicationSecret = applicationSecret;
Log.d("SECRET_KEY", applicationSecret);
this.sessionKey = keyArray[1];
Log.d("SESSION_KEY", sessionKey);
this.authenticationId = sessionKey;
this.password = applicationSecret;
this.hostname = host;
String[] mechanisms = { "DIGEST-MD5" };
Map<String, String> props = new HashMap<String, String>();
this.sc =
Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
this);
authenticate();
}
#Override
protected String getName()
{
return NAME;
}
#Override
public void challengeReceived(String challenge) throws IOException
{
byte[] response = null;
if (challenge != null)
{
String decodedChallenge = new String(Base64.decode(challenge));
Log.d("DECODED", decodedChallenge);
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis() / 1000L;
String sig =
"api_key=" + apiKey + "call_id=" + callId + "method="
+ method + "nonce=" + nonce + "session_key="
+ sessionKey + "v=" + version + applicationSecret;
try
{
sig = md5(sig);
sig = sig.toUpperCase();
} catch (NoSuchAlgorithmException e)
{
throw new IllegalStateException(e);
}
String composedResponse =
"api_key=" + URLEncoder.encode(apiKey, "utf-8")
+ "&call_id=" + callId + "&method="
+ URLEncoder.encode(method, "utf-8") + "&nonce="
+ URLEncoder.encode(nonce, "utf-8")
+ "&session_key="
+ URLEncoder.encode(sessionKey, "utf-8") + "&v="
+ URLEncoder.encode(version, "utf-8") + "&sig="
+ URLEncoder.encode(sig, "utf-8");
Log.d("COMPOSED", composedResponse);
response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null)
{
authenticationText =
Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
private Map<String, String> getQueryMap(String query)
{
Map<String, String> map = new HashMap<String, String>();
String[] params = query.split("\\&");
for (String param : params)
{
String[] fields = param.split("=", 2);
map.put(fields[0], (fields.length > 1 ? fields[1] : null));
}
return map;
}
private String md5(String text) throws NoSuchAlgorithmException,
UnsupportedEncodingException
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(text.getBytes("utf-8"), 0, text.length());
return convertToHex(md.digest());
}
private String convertToHex(byte[] data)
{
StringBuilder buf = new StringBuilder();
int len = data.length;
for (int i = 0; i < len; i++)
{
int halfByte = (data[i] >>> 4) & 0xF;
int twoHalfs = 0;
do
{
if (0 <= halfByte && halfByte <= 9)
{
buf.append((char) ('0' + halfByte));
}
else
{
buf.append((char) ('a' + halfByte - 10));
}
halfByte = data[i] & 0xF;
} while (twoHalfs++ < 1);
}
return buf.toString();
}
}
And this, is the communication with the server with the sent and received messages:
PM SENT (1132418216): <stream:stream to="chat.facebook.com" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
PM RCV (1132418216): <?xml version="1.0"?><stream:stream id="C62D0F43" from="chat.facebook.com" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xml:lang="en"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>X-FACEBOOK-PLATFORM</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms></stream:features>
PM SENT (1132418216): <auth mechanism="X-FACEBOOK-PLATFORM" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth>
PM RCV (1132418216): <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dmVyc2lvbj0xJm1ldGhvZD1hdXRoLnhtcHBfbG9naW4mbm9uY2U9NzFGNkQ3Rjc5QkIyREJCQ0YxQTkwMzA0QTg3OTlBMzM=</challenge>
PM SENT (1132418216): <response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">YXBpX2tleT0zMWYzYjg1ZjBjODYwNjQ3NThiZTZhOTQyNjVjZmNjMCZjYWxsX2lkPTEzMDA0NTYxMzUmbWV0aG9kPWF1dGgueG1wcF9sb2dpbiZub25jZT03MUY2RDdGNzlCQjJEQkJDRjFBOTAzMDRBODc5OUEzMyZzZXNzaW9uX2tleT0yNjUzMTg4ODNkYWJhOGRlOTRiYTk4ZDYtMTAwMDAwNTAyNjc2Nzc4JnY9MS4wJnNpZz04RkRDRjRGRTgzMENGOEQ3QjgwNjdERUQyOEE2RERFQw==</response>
PM RCV (1132418216): <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
As read in the developers Facebook forum, it is needed to disable the "Disable Deprecated Auth Methods" setting from the Facebook settings page of your app. But, even doing that, I can't login. And the session key is the second part of the OAuth token in the form AAA|BBB|CCC, I mean, BBB.
Finally, thanks to the no.good.at.coding code and the suggestion of harism, I've been able to connect to the Facebook chat. This code is the Mechanism for the Asmack library (the Smack port for Android). For the Smack library is necessary to use the no.good.at.coding mechanism.
SASLXFacebookPlatformMechanism.java:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
import org.apache.harmony.javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.Base64;
public class SASLXFacebookPlatformMechanism extends SASLMechanism
{
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String applicationSecret = "";
private String sessionKey = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication)
{
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException
{
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
#Override
public void authenticate(String apiKeyAndSessionKey, String host,
String applicationSecret) throws IOException, XMPPException
{
if (apiKeyAndSessionKey == null || applicationSecret == null)
{
throw new IllegalArgumentException("Invalid parameters");
}
String[] keyArray = apiKeyAndSessionKey.split("\\|", 2);
if (keyArray.length < 2)
{
throw new IllegalArgumentException(
"API key or session key is not present");
}
this.apiKey = keyArray[0];
this.applicationSecret = applicationSecret;
this.sessionKey = keyArray[1];
this.authenticationId = sessionKey;
this.password = applicationSecret;
this.hostname = host;
String[] mechanisms = { "DIGEST-MD5" };
Map<String, String> props = new HashMap<String, String>();
this.sc =
Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
this);
authenticate();
}
#Override
public void authenticate(String username, String host, CallbackHandler cbh)
throws IOException, XMPPException
{
String[] mechanisms = { "DIGEST-MD5" };
Map<String, String> props = new HashMap<String, String>();
this.sc =
Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
cbh);
authenticate();
}
#Override
protected String getName()
{
return NAME;
}
#Override
public void challengeReceived(String challenge) throws IOException
{
byte[] response = null;
if (challenge != null)
{
String decodedChallenge = new String(Base64.decode(challenge));
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis();
String sig =
"api_key=" + apiKey + "call_id=" + callId + "method="
+ method + "nonce=" + nonce + "session_key="
+ sessionKey + "v=" + version + applicationSecret;
try
{
sig = md5(sig);
} catch (NoSuchAlgorithmException e)
{
throw new IllegalStateException(e);
}
String composedResponse =
"api_key=" + URLEncoder.encode(apiKey, "utf-8")
+ "&call_id=" + callId + "&method="
+ URLEncoder.encode(method, "utf-8") + "&nonce="
+ URLEncoder.encode(nonce, "utf-8")
+ "&session_key="
+ URLEncoder.encode(sessionKey, "utf-8") + "&v="
+ URLEncoder.encode(version, "utf-8") + "&sig="
+ URLEncoder.encode(sig, "utf-8");
response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null)
{
authenticationText =
Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
private Map<String, String> getQueryMap(String query)
{
Map<String, String> map = new HashMap<String, String>();
String[] params = query.split("\\&");
for (String param : params)
{
String[] fields = param.split("=", 2);
map.put(fields[0], (fields.length > 1 ? fields[1] : null));
}
return map;
}
private String md5(String text) throws NoSuchAlgorithmException,
UnsupportedEncodingException
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(text.getBytes("utf-8"), 0, text.length());
return convertToHex(md.digest());
}
private String convertToHex(byte[] data)
{
StringBuilder buf = new StringBuilder();
int len = data.length;
for (int i = 0; i < len; i++)
{
int halfByte = (data[i] >>> 4) & 0xF;
int twoHalfs = 0;
do
{
if (0 <= halfByte && halfByte <= 9)
{
buf.append((char) ('0' + halfByte));
}
else
{
buf.append((char) ('a' + halfByte - 10));
}
halfByte = data[i] & 0xF;
} while (twoHalfs++ < 1);
}
return buf.toString();
}
}
To use it:
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
XMPPConnection xmpp = new XMPPConnection(config);
try
{
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
xmpp.connect();
xmpp.login(apiKey + "|" + sessionKey, sessionSecret, "Application");
} catch (XMPPException e)
{
xmpp.disconnect();
e.printStackTrace();
}
apiKey is the API key given in the application settings page in Facebook. sessionKey is the second part of the access token. If the token is in this form, AAA|BBB|CCC, the BBB is the session key. sessionSecret is obtained using the old REST API with the method auth.promoteSession. To use it, it's needed to make a Http get to this url:
https://api.facebook.com/method/auth.promoteSession?access_token=yourAccessToken
Despite of the Facebook Chat documentation says that it's needed to use your application secret key, only when I used the key that returned that REST method I was able to make it works. To make that method works, you have to disable the Disable Deprecated Auth Methods option in the Advance tab in your application settings.
I'd used this about 6 months ago with Smack (not asmack) so I'm not sure how it'll hold up now but here goes, hope it helps!
I found an implementation of Facebook's X-FACEBOOK-PLATFORM authentication mechanism on the Ignite Realtime Smack forum where someone got it from the fbgc project. You'll find the a ZIP with the SASLXFacebookPlatformMechanism.java source in the answer I linked to. You can use it as follows:
public void login() throws XMPPException
{
SASLAuthentication.registerSASLMechanism(SASLXFacebookPlatformMechanism.NAME,
SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism(SASLXFacebookPlatformMechanism.NAME, 0);
ConnectionConfiguration connConfig = new ConnectionConfiguration(host, port);
XMPPConnection connection = new XMPPConnection(connConfig);
connection.connect();
log.info("XMPP client connected");
connection.login(Utils.FB_APP_ID + "|" + this.user.sessionId, Utils.FB_APP_SECRET, "app_name");
log.info("XMPP client logged in");
}
I was doing this on the server without an SDK. I don't remember the details (and the Facebook documentation isn't very good) but from what I can tell from my code, after getting the user to authorize the app, I get a callback request from Facebook with a code parameter. I open a URLConnection to https://graph.facebook.com/oauth/access_token?client_id=<app_id>&redirect_uri=http://myserver/context/path/&client_secret=<app_secret>&code=<code>. The response should be the access token where the session id is the part after the | - something of the form XXX|<sessionId>.
Here's code I've been using successfully for authentication. Maybe this helps even though this is not related to Smack in any way. You can get sessionKey from access token received from FB, and for getting sessionSecret I've been using oldish REST API;
http://developers.facebook.com/docs/reference/rest/auth.promoteSession/
private final void processChallenge(XmlPullParser parser, Writer writer,
String sessionKey, String sessionSecret) throws IOException,
NoSuchAlgorithmException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, null, "challenge");
String challenge = new String(Base64.decode(parser.nextText(),
Base64.DEFAULT));
String params[] = challenge.split("&");
HashMap<String, String> paramMap = new HashMap<String, String>();
for (int i = 0; i < params.length; ++i) {
String p[] = params[i].split("=");
p[0] = URLDecoder.decode(p[0]);
p[1] = URLDecoder.decode(p[1]);
paramMap.put(p[0], p[1]);
}
String api_key = "YOUR_API_KEY";
String call_id = "" + System.currentTimeMillis();
String method = paramMap.get("method");
String nonce = paramMap.get("nonce");
String v = "1.0";
StringBuffer sigBuffer = new StringBuffer();
sigBuffer.append("api_key=" + api_key);
sigBuffer.append("call_id=" + call_id);
sigBuffer.append("method=" + method);
sigBuffer.append("nonce=" + nonce);
sigBuffer.append("session_key=" + sessionKey);
sigBuffer.append("v=" + v);
sigBuffer.append(sessionSecret);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sigBuffer.toString().getBytes());
byte[] digest = md.digest();
StringBuffer sig = new StringBuffer();
for (int i = 0; i < digest.length; ++i) {
sig.append(Integer.toHexString(0xFF & digest[i]));
}
StringBuffer response = new StringBuffer();
response.append("api_key=" + URLEncoder.encode(api_key));
response.append("&call_id=" + URLEncoder.encode(call_id));
response.append("&method=" + URLEncoder.encode(method));
response.append("&nonce=" + URLEncoder.encode(nonce));
response.append("&session_key=" + URLEncoder.encode(sessionKey));
response.append("&v=" + URLEncoder.encode(v));
response.append("&sig=" + URLEncoder.encode(sig.toString()));
StringBuilder out = new StringBuilder();
out.append("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>");
out.append(Base64.encodeToString(response.toString().getBytes(),
Base64.NO_WRAP));
out.append("</response>");
writer.write(out.toString());
writer.flush();
}
I'm sorry to make new answer but I had to include the new code #YShinkarev sorry for being late
By modifying #Adrian answer to make challengeReceived we can use APIKey and accessToken all I modified was the composedResponse
#Override
public void challengeReceived(String challenge) throws IOException {
byte[] response = null;
if (challenge != null) {
String decodedChallenge = new String(Base64.decode(challenge));
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis();
String composedResponse = "api_key="
+ URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId
+ "&method=" + URLEncoder.encode(method, "utf-8")
+ "&nonce=" + URLEncoder.encode(nonce, "utf-8")
+ "&access_token="
+ URLEncoder.encode(access_token, "utf-8") + "&v="
+ URLEncoder.encode(version, "utf-8");
response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null) {
authenticationText = Base64.encodeBytes(response,
Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
What do you want to do?
If you just want to login on FB chat, you connect to FB just like any other XMPP server.
I would look at and use "Authenticating with Username/Password" from Chat API, wich is supported by Smack. Unless I would like to write an FaceBook-application. Then I would try to login in with "Authenticating with Facebook Platform".
So, just use Smack to connect to FB chat as you would do with your ordinary Jabber client.
For the username, use your Facebook username. (see http://www.facebook.com/username/ )
For the domain, use: chat.facebook.com
For the password, use your Facebook password
Turn off SSL and TSL
Set connect port to: 5222 (which is the default for XMPP)
Set connect server to chat.facebook.com

Categories