'Facebook: Getting Incorrect Signature (104) when Getting Session Key
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">
<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!
Solution 1:[1]
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.
Solution 2:[2]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | fyasar |
| Solution 2 | Omnia |
