views:

4452

answers:

4

Hello there,

I am trying to use the HttpClient library (in order to call the Facebook API's REST end points) to obtain a session key and verify user...

My code is here:

RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
{ "classpath*:**/*applicationContext-test.xml" })
public class FacebookUserTest
{
    final String API_KEY = "9e2568d68f182a2957878f3acedd9453";
    final String SECRET = "f1298956895d39110be92a672e0d2284";
    final String TOKEN = "aa0c41aa4532053e8d0097844ab9bc7d";
    final String LOGIN = "http://www.facebook.com/login.php";
    final String HOST = "http://www.facebook.com/restserver.php";

    private static Logger log = 
        LoggerFactory.getLogger(FacebookUserTest.class);

    protected FacebookUser FacebookUser;

    @Test
    public void testFindUserBySessionKey() throws Exception
    {
        loginToFacebook();
        String sessionKey = getSessionKey();
    }

    public void loginToFacebook() throws Exception
    {
        HttpClient client = new HttpClient();
        client.setParams(new HttpClientParams());
        client.setState(new HttpState());

        GetMethod get = new GetMethod(LOGIN + "?api_key=" + API_KEY
            + "&v=1.0&auth_token=" + TOKEN);

        // Get login screen
        client.executeMethod(get);

        // Post credentials to login
        PostMethod post = new PostMethod(LOGIN);
        post.addParameter(new NameValuePair("api_key", API_KEY));
        post.addParameter(new NameValuePair("v", "1.0"));
        post.addParameter(new NameValuePair("auth_token", TOKEN));
        post.addParameter(new NameValuePair("email", "[email protected]"));
        post.addParameter(new NameValuePair("pass", "password"));
        client.executeMethod(post);
    }

    public String getSessionKey() throws Exception
    {
        HttpClient client = new HttpClient();

        // Obtain session key
        String host = "http://www.facebook.com/restserver.php";
        String sessSecret = "false";
        String toMd = "api_key=" + API_KEY + "auth_token=" + TOKEN
            + "format=xmlgenerate_session_secret=" + sessSecret
            + "method=facebook.auth.getSessionv=1.0" + SECRET;
         String md5 = Md5Utils.MD5(toMd);

         PostMethod post = new PostMethod(HOST);

         NameValuePair[] data = {
            new NameValuePair("api_key", API_KEY),
            new NameValuePair("auth_token", TOKEN),
            new NameValuePair("format", "xml"),
            new NameValuePair("generate_session_secret", SECRET),
            new NameValuePair("method", "auth.getSession"),
            new NameValuePair("sig", md5), new NameValuePair("v", "1.0")
         };

         post.setRequestBody(data);
         post.setRequestHeader("Content-Type",
            "application/x-www-form-urlencoded");
         post.setRequestHeader("User-Agent",
            "Facebook API PHP5 Client 1.1 (curl) 5");

         // execute method and handle any error responses.
         client.executeMethod(post);

         StringBuilder sb = new StringBuilder();
         byte[] b = new byte[4096];

         for (int n; (n = post.getResponseBodyAsStream().read(b)) != -1;) 
         {
             sb.append(new String(b, 0, n));
         }

         String sessionId = sb.toString();
         log.warn("Session Id: " + sessionId);

         return sessionId;
     }
}

When I run my JUnit test, this is what is printed from the console:

WARN : com.myapp.FacebookUserTest - Session Id: 

<?xml version="1.0" encoding="UTF-8"?>
<error_response xmlns="http://api.facebook.com/1.0/" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://api.facebook.com/1.0/
   http://api.facebook.com/1.0/facebook.xsd"&gt;
    <error_code>104</error_code>
    <error_msg>Incorrect signature</error_msg>
    <request_args list="true">
        <arg>
            <key>api_key</key>
            <value>9e2568d68f182a2957878f3acedd9453</value>
        </arg>
        <arg>
            <key>auth_token</key>
            <value>aa0c41aa4532053e8d0097844ab9bc7d</value>
        </arg>
        <arg>
            <key>format</key>
            <value>xml</value>
        </arg>
        <arg>
            <key>generate_session_secret</key>
            <value>f1298956895d39110be92a672e0d2284</value>
         </arg>
         <arg>
            <key>method</key>
            <value>auth.getSession</value>
         </arg>
         <arg>
             <key>sig</key>
             <value>fcf80d658f35d66396ac521da7102782</value>
         </arg>
         <arg>
             <key>v</key>
             <value>1.0</value>
          </arg>
     </request_args>
</error_response>

Could it be my MD5Utils code:

 public class Md5Utils
 {
      private static String convertToHex(byte[] data)
      {
           StringBuffer buf = new StringBuffer();
           for (int i = 0; i < data.length; i++) {
               int halfbyte = (data[i] >>> 4) & 0x0F;
               int two_halfs = 0;
               do {
                   if ((0 <= halfbyte) && (halfbyte <= 9))
                       buf.append((char) ('0' + halfbyte));
                   else
                      buf.append((char) ('a' + (halfbyte - 10)));
                      halfbyte = data[i] & 0x0F;
               }
               while (two_halfs++ < 1);
            }
        return buf.toString();
      }

  public static String MD5(String text) 
  throws NoSuchAlgorithmException, UnsupportedEncodingException {
      MessageDigest md;
      md = MessageDigest.getInstance("MD5");
      byte[] md5hash = new byte[32];
      md.update(text.getBytes("iso-8859-1"), 0, text.length());
      md5hash = md.digest();
      return convertToHex(md5hash);
   }
}

What am I possibly doing wrong to generate an incorrect signature?

Would really appreciate it if someone could help me or point me in the right direction...

Happy programming and thanks for reading!

A: 

Try this

    string GenerateSignature(IDictionary<string, string> parameters)
    {
        StringBuilder signatureBuilder = new StringBuilder();

        // Sort the keys of the method call in alphabetical order
        List<string> keyList = ParameterDictionaryToList(parameters);
        keyList.Sort();

        // Append all the parameters to the signature input paramaters
        foreach (string key in keyList)
            signatureBuilder.Append(String.Format(CultureInfo.InvariantCulture, "{0}={1}", key, parameters[key]));

        // Append the secret to the signature builder
        signatureBuilder.Append(ConfigurationManager.AppSettings["FBApiSecret"]);

        MD5 md5 = MD5.Create();
        // Compute the MD5 hash of the signature builder
        byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(signatureBuilder.ToString().Trim()));

        // Reinitialize the signature builder to store the actual signature
        signatureBuilder = new StringBuilder();

        // Append the hash to the signature
        foreach (byte hashByte in hash)
            signatureBuilder.Append(hashByte.ToString("x2", CultureInfo.InvariantCulture));

        return signatureBuilder.ToString();
    }

    string CreateHTTPParameterList(IDictionary<string, string> parameterList)
    {
        StringBuilder queryBuilder = new StringBuilder();
        parameterList.Add("api_key", ConfigurationManager.AppSettings["FBApiKey"]);
        parameterList.Add("v", "1.0");
        parameterList.Add("call_id", DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture));
        parameterList.Add("sig", GenerateSignature(parameterList));
        //parameterList.Add("sig", _sig);

        // Build the query
        foreach (KeyValuePair<string, string> kvp in parameterList)
        {
            queryBuilder.Append(kvp.Key);
            queryBuilder.Append("=");
            queryBuilder.Append(HttpUtility.UrlEncode(kvp.Value));
            queryBuilder.Append("&");
        }
        queryBuilder.Remove(queryBuilder.Length - 1, 1);

        return queryBuilder.ToString();
    }

Example usage :

        Dictionary<string, string> parameterList = new Dictionary<string, string>();
        parameterList.Add("auth_token", authCode);
        parameterList.Add("format", "json");
        parameterList.Add("method", "facebook.auth.getSession");

        string req = CreateHTTPParameterList(parameterList);

I tryed to copy / paste these codes from my old project. I hope it will be help to you.

fyasar
A: 

you have an error in your parameter you send in generate_session_secret your secret code , it must be true or false

you set: new NameValuePair("generate_session_secret", SECRET),

there are conflict in your parameter that u set in post and the signature

Omnia
A: 

Is it work with you? since i want to do the same but in java

Omnia
A: 

I've the same issuecan anyone able to slove this....

pavan