First post here so please be gentle.
I'm building a facebook chat client, using Smack library.
I'm using X-FACEBOOK-PLATFORM method in order not to save any passwords. I had it working properly using oauth 1.0, and want to change it to 2.0, cause of the october 1st deadline ;p. From what I understand the only thing I'd have to do in order to migrate to 2.0 is removing "sig" and "session_key" parameters and adding an "access_token" parameter, but I'm getting an "SASL authentication X-FACEBOOK-PLATFORM failed: not-authorized:".
I'm using this custom SASLMechanism class:
package smackresearching;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import 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 {
public static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String accessToken = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException {
// Send the authentication to the server
getSASLAuthentication().send(new AuthMechanism(getName(), ""));
}
#Override
public void authenticate(String apiKey, String host, String accessToken) throws IOException, XMPPException {
this.apiKey = apiKey;
this.accessToken = accessToken;
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));
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 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(accessToken, "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));
}
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;
}
}
And this is the Main code:
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
// config.setDebuggerEnabled(true);
XMPPConnection connection = new XMPPConnection(config);
try {
//ESTA LINEA HACE QUE NO DE TIMEOUT
SmackConfiguration.setPacketReplyTimeout(15000);
XMPPConnection.DEBUG_ENABLED = true;
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
connection.connect();
String apiKey = "3290282390339";
String accessToken = "ADSJGFGFKDKSJKSJD0-43DKJSDJKSDKJSD094JJSDKJSDKJDSNDSKJEWEWNSDLkljdkjs";
connection.login(apiKey, accessToken);
...
Thanks in advance for any advice.
There is a missing ampersand for the access_token parameter in the composedResponse string. Is this a typo?
Could you post the authenticationText you are sending?
Related
How to get OAuth2.0 access token using refresh token in scala .
Sample code using the HttpsURLConnection, without any libraries
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class Sample_OAuth {
public static void main(String[] args) throws Exception {
Sample_OAuth outhDriver = new Sample_OAuth();
outhDriver.sendRefreshTokenRequestWithOnlyHeader(null);
}
/**
* Send refresh token request to 3rd party with client cred either in body or
* request header.
*
* #param conn
* #param mapListTagToMetaDataName
* #return
* #throws Exception
*/
private Map<String, Object> sendRefreshTokenRequestWithOnlyHeader(Map<String, String> mapListTagToMetaDataName)
throws Exception {
String tokenUrl = "https://xyz.snowflakecomputing.com/oauth/token-request";
URL url = new URL(tokenUrl);
StringBuilder stringBuilder = new StringBuilder();
appendURLParam(stringBuilder, "grant_type", "refresh_token", true);
appendURLParam(stringBuilder, "refresh_token", "ver:2-hint:2065896170862-did:1003-ETMsDgAAAYWAOC1cABRBRVMvQ0JDL1BLQ1M1UGFkZGluZwEAABAAEDu3hgX2UvrDbaMif7uC+ygAAADwoZhxL+aOCvvsmNh0wy0FdNGuDRLCtOq7iQTsZPPmfkRZJnkj3nXgKDxTFeFOmty4ej/O6Fsf17HfNvKdLrqfN3V29FkFQ5S+FktFIznTSjtd7+xaMS+sPEAyey2SFfbSyMvrknjq9F+CQZ50H181OO8Ak4v1uW4ON9Q1UBRd9ywM2Yg5g59hPgy90jtAW0DPQ8gvfAwRJCgg2wzV7tXrQ1H2TQhFEkQH418s5pSNB5V6BSW0fFqOUW3O8X4MmHcWcpTbghZ5aga8+dSKSR8jd2KMmfawyXMdkIYdWEsrpcJozuYDAjFwIT1lkqLxqBnuABQIbwjao0KeWXYU3sYanTb0WoR4Ng==",
false);
String clientRequestType = "Basic Auth Header";
return sendOAuthRequestWithHeader(mapListTagToMetaDataName, url, stringBuilder.toString());
}
private static void appendURLParam(StringBuilder stringBuilder, String name, String value, boolean appendAmpersand)
throws UnsupportedEncodingException {
/*
* if (StringUtil.isNullOrEmptyTrim(name) ||
* StringUtil.isNullOrEmptyTrim(value)) { //log.error(String.
* format("Either Auth attr name : %s or value : %s is Null or empty", name,
* value)); return; }
*/
stringBuilder.append(name);
stringBuilder.append("=");
stringBuilder.append(URLEncoder.encode(value, "UTF-8"));
//stringBuilder.append(value);
if (appendAmpersand) {
stringBuilder.append("&");
}
}
private Map<String, Object> sendOAuthRequestWithHeader(Map<String, String> mapListTagToMetaDataName, URL url,
String postBody) throws Exception {
String clientId = "S0RpOorCRUQOqVncoxc8fXUO22A=";
String client_secret = "MHTOaEmQeLB359K+kEAs/+2ow4AcmqD5/ABckC4E2fQ=";
clientId = clientId + ":" + client_secret;
// Should not be MIME-encode since value is used as a HTTP header and MIME adds
// new lines if over 76 characters
String value = java.util.Base64.getEncoder().encodeToString(clientId.getBytes());
return sendOAuthRequest(url, postBody, value);
}
private Map<String, Object> sendOAuthRequest(URL url, String postBody, String authorizationHeader) throws Exception {
HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
urlConn.setRequestMethod("POST");
urlConn.addRequestProperty("Accept", "application/json");
if (notNullOrEmptyTrim(authorizationHeader)) {
urlConn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConn.addRequestProperty("Authorization", "Basic " + authorizationHeader);
}
return sendAccessTokenRequest(urlConn, postBody);
}
public Map<String, Object> getToken(String tokenUrl, String requestBody, String authorizationHeader)
throws Exception {
// LOG.info("Request : getToken "+ tokenUrl);
URL url = new URL(tokenUrl);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.addRequestProperty("Accept", "application/json");
if (null != authorizationHeader && !authorizationHeader.isEmpty()) {
urlConnection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.addRequestProperty("Authorization", "Basic " + authorizationHeader);
}
return sendAccessTokenRequest(urlConnection, requestBody);
}
private Map<String, Object> sendAccessTokenRequest(HttpsURLConnection urlConn, String postBody) throws Exception {
// Write to input stream
try {
//optional
enableAllSSLCert(urlConn);
urlConn.setDoOutput(true);
//optional
urlConn.setHostnameVerifier((name, session) -> true);
DataOutputStream outputStream = new DataOutputStream(urlConn.getOutputStream());
outputStream.writeBytes(postBody);
outputStream.flush();
outputStream.close();
int responseCode = urlConn.getResponseCode();
InputStream is = null;
// LOG.info(" response code is:" + responseCode);
if (responseCode >= 200 && responseCode < 400) {
is = urlConn.getInputStream();
} else {
// LOG.error("Error, sendOAuthRequest response code is:" + responseCode);
is = urlConn.getErrorStream();
}
// Read response
String response = null;
if (null != is) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder stringBuilder = new StringBuilder();
while (true) {
String line = bufferedReader.readLine();
if (line == null) {
break;
} else {
stringBuilder.append(line);
}
}
response = stringBuilder.toString();
bufferedReader.close();
}
// Logging in case of error
if (responseCode != 200) {
// LOG.error("Get Token error response : " + response);
}
System.out.println(response);
Map<String, Object> retValue = new HashMap<>();
retValue.put("errorCode", responseCode);
retValue.put("token", response);
return retValue;
} catch (Exception exp) {
// LOG.info(" Exception while getting Access Token:", exp);
throw exp;
}
}
public static boolean notNullOrEmptyTrim(String str) {
return !isNullOrEmptyTrim(str);
}
public static boolean isNullOrEmptyTrim(String s) {
return s == null || s.trim().isEmpty();
}
/**
* Enable https client for all SSL cert
*
* #param urlConn
* #throws NoSuchAlgorithmException
* #throws KeyManagementException
*/
private void enableAllSSLCert(HttpsURLConnection urlConn) throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAllTrustManager() }, new java.security.SecureRandom());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = (hostname, session) -> true;
urlConn.setHostnameVerifier(allHostsValid);
}
/**
* Override Trust All trust manager
*/
private class TrustAllTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I searched many places to find ways to integrate facebook chat into Android/Smack but none of them worked completely. Could someone provide a working example that works with the latest version of the API?
Authenticating using X-FACEBOOK-PLATFORM SASLAuthentication. Verified working on 14 Jan 2014 with Android 4.2.2.
The jabber ID is not username#chat.facebook.com. It is resolved to a numeric id that you can check against the roster.
ChatActivity.java
public void connectToFb() throws XMPPException {
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM",SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
config.setSASLAuthenticationEnabled(true);
config.setSecurityMode(SecurityMode.required);
config.setSendPresence(false);
XMPPConnection xmpp = new XMPPConnection(config);
try {
xmpp.connect();
xmpp.login(Session.getActiveSession().getApplicationId(), Session.getActiveSession().getAccessToken(), "Application");
//send a chat message
ChatManager chatmanager = xmpp.getChatManager();
Chat newChat = chatmanager.createChat("<jabber-id-here>#chat.facebook.com", new MessageListener() {
#Override
public void processMessage(Chat chat, Message msg) {
Log.d("test", "message sent = "+ msg);
}
});
newChat.sendMessage("Cowdy!");
//get roster
Roster roster = xmpp.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
System.out.println("Connected!");
System.out.println("\n\n" + entries.size() + " buddy(ies):");
for (RosterEntry entry : entries) {
Log.i("test", entry.getName());
Log.i("test", entry.getUser());
}
} catch (XMPPException e) {
xmpp.disconnect();
e.printStackTrace();
}
}
SASLXFacebookPlatformMechanism.java
public class SASLXFacebookPlatformMechanism extends SASLMechanism {
public static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String accessToken = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException {
// Send the authentication to the server
getSASLAuthentication().send(new AuthMechanism(getName(), ""));
}
#Override
public void authenticate(String apiKey, String host, String accessToken) throws IOException, XMPPException {
this.apiKey = apiKey;
this.accessToken = accessToken;
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));
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 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(accessToken, "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));
}
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;
}
}
Authentication flow using SASL/Plain (when username and password are supplied)
Refer to Android Facebook chat example project
I'm trying to connect to Facebook chat api via SMACK using the code below but I always receive X-FACEBOOK-PLATFORM failed: not-authorized. I have a valid token with xmpp permission but I think I'm missing something... it's working with user/pass, but not with accessToken.
Thanks for your help guys, this thing is driving me crazy.
public class FacebookChatSample {
public static void main( )
{
String accessToken = //internet example "AAACjg0Eh1N8BAFuhUFZAN0EteV6pjZAsZAI46i8oV3iVmyLdaKiwaBcM5DPFjbEZAq9LZAZAA0qXsvaXkKB7SqnhubzlUAK7tmr3UYLaeQgaXSJ6EZCKn2G";
String consumerKey = //internet example "179784128779487";
long targetFacebookId = 550121201669650L;
String toID = "1002221765";
String message = "HELLOOOOO FROM MY JAVA PROGRAM!!";
XMPPConnection connection = createXMPPConnection();
try
{
connection.connect();
connection.login( consumerKey, accessToken );
String to = String.format( "-%d#chat.facebook.com", Long.valueOf( targetFacebookId ) );
Chat chat = connection.getChatManager().createChat( to, null );
chat.sendMessage( message );
}
catch( XMPPException e )
{
e.printStackTrace();
}
finally
{
connection.disconnect();
}
}
private static synchronized XMPPConnection createXMPPConnection()
{
SASLAuthentication.registerSASLMechanism(
SASLXFacebookPlatformMechanism.NAME,
SASLXFacebookPlatformMechanism.class );
SASLAuthentication.supportSASLMechanism(
SASLXFacebookPlatformMechanism.NAME, 0 );
ConnectionConfiguration configuration = new ConnectionConfiguration(
"chat.facebook.com", 5222 );
configuration.setSASLAuthenticationEnabled( true );
return new XMPPConnection( configuration );
}
public static class SASLXFacebookPlatformMechanism extends SASLMechanism
{
public static final String NAME = "X-FACEBOOK-PLATFORM";
public SASLXFacebookPlatformMechanism(
SASLAuthentication saslAuthentication )
{
super( saslAuthentication );
}
private String apiKey = "";
private String accessToken = "";
#Override
protected void authenticate() throws IOException, XMPPException
{
AuthMechanism stanza = new AuthMechanism( getName(), null );
getSASLAuthentication().send( stanza );
}
#SuppressWarnings( "hiding" )
#Override
public void authenticate( String apiKey, String host, String accessToken )
throws IOException, XMPPException
{
if( apiKey == null || accessToken == null )
{
throw new IllegalStateException( "Invalid parameters!" );
}
this.apiKey = apiKey;
this.accessToken = accessToken;
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 decodedResponse = new String(
org.jivesoftware.smack.util.Base64.decode( challenge ) );
Map<String, String> parameters = getQueryMap( decodedResponse );
String version = "1.0";
String nonce = parameters.get( "nonce" );
String method = parameters.get( "method" );
Long callId = Long.valueOf( System.currentTimeMillis() );
String composedResponse = String
.format(
"method=%s&nonce=%s&access_token=%s&api_key=%s&call_id=%s&v=%s",
URLEncoder.encode( method, "UTF-8" ),
URLEncoder.encode( nonce, "UTF-8" ),
URLEncoder.encode( this.accessToken, "UTF-8" ),
URLEncoder.encode( this.apiKey, "UTF-8" ),
callId, URLEncoder.encode( version, "UTF-8" ) );
response = composedResponse.getBytes();
}
String authenticationText = "";
if( response != null )
{
authenticationText = org.jivesoftware.smack.util.Base64
.encodeBytes(
response,
org.jivesoftware.smack.util.Base64.DONT_BREAK_LINES );
}
Response stanza = new Response( authenticationText );
getSASLAuthentication().send( stanza );
}
private Map<String, String> getQueryMap( String query )
{
String[] params = query.split( "&" );
Map<String, String> map = new HashMap<String, String>();
for( String param : params )
{
String name = param.split( "=" )[0];
String value = param.split( "=" )[1];
map.put( name, value );
}
return map;
}
}
}
My God, I have been struggling with this forever as well. I just figured it out! Once I got it, it seemed so easy, but the confusing thing is the problem that seems to come from XMPP is actually a problem with Facebook. I think your problem (my problem was) that Facebook requires you to request application specific login permissions that have nothing to do with the XMPP protocol. If you look at the Chat API specifications, it says you need to request xmpp_login extended permission for your application if you're using X-FACEBOOK-PLATFORM. You have to do this through the session object in the Facebook SDK you used to get your session_token.
Here is the code I used:
session.requestNewReadPermissions(new NewPermissionsRequest(getActivity(), Arrays.asList("xmpp_login")));
As soon as I did that it worked like a charm. Last caveat is that you need to make sure the popup dialog asking the user to grant your app this extended permission comes up and gets the required permission BEFORE you moved on and try to xmpp.login. Otherwise you'll have the same problem as your app will request permission but not actually get permission.
I hope this works for you.
I would like to create some unit tests for inserting data to QuickBooks Online. I am having a problem with the authentication step:
public DataServices Authenticate(IntuitServicesType intuitDataServicesType)
{
DataServices dataServices = null;
string accessToken = HttpContext.Current.Session["accessToken"].ToString();
string accessTokenSecret = HttpContext.Current.Session["accessTokenSecret"].ToString();
string companyID = HttpContext.Current.Session["realm"].ToString();
// now auth to IA
OAuthRequestValidator oauthValidator = new OAuthRequestValidator(accessToken, accessTokenSecret, ConfigurationManager.AppSettings["consumerKey"].ToString(), ConfigurationManager.AppSettings["consumerSecret"].ToString());
ServiceContext context = new ServiceContext(oauthValidator, accessToken, companyID, intuitDataServicesType);
dataServices = new DataServices(context);
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
HttpContext.Current.Session["DataServices"] = dataServices;
}
return dataServices;
}
In my unit test project, which has no user interface, how can I obtain an access token and an access token secret? I cannot log into Intuit from that area.
[TestMethod()]
public void AuthorizeWithHeadersTest()
{
string accessToken = ConfigurationManager.AppSettings["AccessTokenQBD"];
string accessTokenSecret = ConfigurationManager.AppSettings["AccessTokenSecretQBD"];
string consumerKey = ConfigurationManager.AppSettings["ConsumerKeyQBD"];
string consumerKeySecret = ConfigurationManager.AppSettings["ConsumerSecretQBD"];
string requestUri = "https://appcenter.intuit.com/Developer/Create";
WebRequest webRequest = WebRequest.Create(requestUri);
webRequest.Headers.Add("ContentType", "text/xml");
OAuthRequestValidator target = new OAuthRequestValidator(accessToken, accessTokenSecret, consumerKey, consumerKeySecret);
target.Authorize(webRequest, string.Empty);
Assert.IsTrue(webRequest.Headers.Count > 0);
}
I'm sharing a sample standalone java code snippet. You can try the same in .net
From appcenter, you can create an app to get consumer key, consumer secret and app token.
Using apiexplorer and the above consumer key, consumer secret, you can get access tokens.
AppCenter - https://appcenter.intuit.com/
Apiexplorer - https://developer.intuit.com/apiexplorer?apiname=V2QBO
You can set all the 5 values in the standalone program(setupQBO method). It will work fine.
import java.util.ArrayList;
import java.util.List;
import com.intuit.ds.qb.PartyType;
import com.intuit.ds.qb.QBCustomer;
import com.intuit.ds.qb.QBCustomerService;
import com.intuit.ds.qb.QBInvalidContextException;
import com.intuit.ds.qb.QBObjectFactory;
import com.intuit.ds.qb.QBServiceFactory;
import com.intuit.platform.client.PlatformSessionContext;
import com.intuit.platform.client.PlatformServiceType;
import com.intuit.platform.client.security.OAuthCredentials;
import org.slf4j.Logger;
// QBO API Docs - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0400_quickbooks_online/Customer
// JavaDocs - http://developer-static.intuit.com/SDKDocs/QBV2Doc/ipp-java-devkit-2.0.10-SNAPSHOT-javadoc/
public class CodegenStubCustomerall {
static String accesstoken = "";
static String accessstokensecret = "";
static String appToken = "";
static String oauth_consumer_key = "";
static String oauth_consumer_secret = "";
static String realmID = "";
static String dataSource = "";
final PlatformSessionContext context;
public CodegenStubCustomerall(PlatformSessionContext context) {
this.context = context;
}
public void testAdd(){
try {
QBCustomer entityPojo = QBObjectFactory.getQBObject(context, QBCustomer.class);
entityPojo.setName("TestQBCustomer12345");
entityPojo.setTypeOf(PartyType.PERSON);
QBCustomerService service = QBServiceFactory.getService(context, QBCustomerService.class);
QBCustomer qbQBCustomer = service.addCustomer(context, entityPojo);
} catch (QBInvalidContextException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public List<QBCustomer> testGetAll() {
final List<QBCustomer> entityList = new ArrayList<QBCustomer>();
try {
QBCustomerService service = QBServiceFactory.getService(context, QBCustomerService.class);
List<QBCustomer> qbCustomerList = service.findAll(context, 1,100);
for (QBCustomer each : qbCustomerList) {
entityList.add(each);
}
} catch (QBInvalidContextException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return entityList;
}
public static void main(String args[]) {
PlatformSessionContext context = getPlatformContext("QBO");
CodegenStubCustomerall testObj = new CodegenStubCustomerall(context);
testObj.testGetAll();
}
public static PlatformSessionContext getPlatformContext(String dataSource) {
PlatformServiceType serviceType = null;
if (dataSource.equalsIgnoreCase("QBO")) {
serviceType = PlatformServiceType.QBO;
setupQBO();
}
final OAuthCredentials oauthcredentials = new OAuthCredentials(
oauth_consumer_key, oauth_consumer_secret, accesstoken,
accessstokensecret);
final PlatformSessionContext context = new PlatformSessionContext(
oauthcredentials, appToken, serviceType, realmID);
return context;
}
private static void setupQBO() {
System.out.println("QBO token setup");
accesstoken = "replace your tokens";
accessstokensecret = "replace your tokens";
appToken = "replace your tokens";
oauth_consumer_key = "replace your tokens";
oauth_consumer_secret = "replace your tokens";
realmID = "7123456720";
dataSource = "QBO";
}
}
For sample .net code, you can refer this link.
https://developer.intuit.com/docs/0025_quickbooksapi/0055_devkits/0100_ipp_.net_devkit/0299_synchronous_calls/0001_data_service_apis
Thanks
I am trying to integrate facebook chat using smack API.But i get an error telling authentication failed using digest md5...
Here s the code for authentication:
SASLAuthentication.registerSASLMechanism("DIGEST-MD5", SASLDigestMD5Mechanism.class);
SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 0);
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222);
connection = new XMPPConnection(config);
config.setSASLAuthenticationEnabled(true);
connection.connect();
connection.login(userName, password);
below is the error i get wen i run it:
Exception in thread "main" SASL authentication failed using mechanism DIGEST-MD5:
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:325)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
at JabberSmackAPIFacebook.login(JabberSmackAPIFacebook.java:31)
at JabberSmackAPIFacebook.main(JabberSmackAPIFacebook.java:77)
I can successfully connect to gtalk but am having no success vit fb...
can sumone tel me wat s the problem
For me the solution was to not include the host part in the username when calling login() without DNS SRV and not agains the Google Talk services. This is also described in the ignite forums.
E.g.
connection.login("user#jabber.org", "password", "resource");
becomes
connection.login("user", "password", "resource");
There is a huge thread at Ignite that deals with this issue. You may want to take a look at it as there are several solutions for Java and Android given that seem to work.
I have succesfully connected using DIGEST-MD5 to facebook, the code you have posted looks good.
But still we need to check the contents of your SASLDigestMD5Mechanism class
I have used the class provided in here with success
http://community.igniterealtime.org/message/200878#200878
Also you have to notice that in the DIGEST-MD5 mechanism you have to login with your facebook username and not with the email address. By default the facebook accounts don't have a username, you have to create one fisrt, you can check that in here:
http://www.facebook.com/username/
MainActivity.java
public class MainActivity extends Activity {
XMPPConnection xmpp;
ArrayList<HashMap<String, String>> friends_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Session.openActiveSession(this, true, new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
if ( session.isOpened()){
new testLoginTask().execute();
}
}
});
}
private class testLoginTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
testLogin();
return null;
}
}
private void testLogin(){
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
config.setDebuggerEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
config.setTruststoreType("AndroidCAStore");
config.setTruststorePassword(null);
config.setTruststorePath(null);
} else {
config.setTruststoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null)
path = System.getProperty("java.home") + File.separator + "etc"
+ File.separator + "security" + File.separator
+ "cacerts.bks";
config.setTruststorePath(path);
}
xmpp = new XMPPConnection(config);
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM",SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
try {
xmpp.connect();
Log.i("XMPPClient","Connected to " + xmpp.getHost());
} catch (XMPPException e1) {
Log.i("XMPPClient","Unable to " + xmpp.getHost());
e1.printStackTrace();
}
try {
String apiKey = Session.getActiveSession().getApplicationId();
String sessionKey = Session.getActiveSession().getAccessToken();
String sessionSecret = "replace with your app secret key";
xmpp.login(apiKey + "|" + sessionKey, sessionSecret , "Application");
Log.i("XMPPClient"," its logined ");
Log.i("Connected",""+xmpp.isConnected());
if ( xmpp.isConnected()){
Presence presence = new Presence(Presence.Type.available);
xmpp.sendPacket(presence);
}
} catch (XMPPException e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
SASLXFacebookPlatformMechanism.java
public class SASLXFacebookPlatformMechanism extends SASLMechanism{
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String accessToken = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMechanism(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
#Override
protected void authenticate() throws IOException, XMPPException {
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
#Override
public void authenticate(String apiKey, String host, String accessToken) throws IOException, XMPPException {
if (apiKey == null || accessToken == null) {
throw new IllegalArgumentException("Invalid parameters");
}
this.apiKey = apiKey;
this.accessToken = accessToken;
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 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(accessToken, "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));
}
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;
}
}