
com.threerings.facebook.SignedRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ooo-facebook Show documentation
Show all versions of ooo-facebook Show documentation
Various Facebook helper bits used by OOO.
The newest version!
package com.threerings.facebook;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONException;
import org.json.JSONObject;
import com.threerings.servlet.util.Parameters;
/**
* Decodes a signed_request from Facebook.
*/
public class SignedRequest
{
public SignedRequest (Parameters params, String appSecret)
{
_present = params.has("signed_request");
if (!_present) {
_token = null;
_userId = null;
return;
}
String param = params.get("signed_request");
List split = Lists.newArrayList(PERIOD_SPLITTER.split(param));
Preconditions.checkArgument(split.size() == 2,
"Not properly period delimited [req=%s]", param);
String encodedJson = split.get(1);
String json = new String(new Base64(true).decode(encodedJson), Charsets.UTF_8);
JSONObject obj;
try {
obj = new JSONObject(json);
} catch (JSONException je) {
throw new RuntimeException("Invalid json [json=" + json + ", req=" + param + "]", je);
}
String algorithm = obj.optString("algorithm");
checkArg("HMAC-SHA256".equals(algorithm), "Improper algorithm in json", param, json);
long issuedAt = obj.optLong("issued_at");
checkArg(System.currentTimeMillis() / 1000 - ONE_HOUR < issuedAt, "More than an hour old",
param, json);
SecretKey key = new SecretKeySpec(appSecret.getBytes(Charsets.UTF_8), "HMACSHA256");
Mac mac;
try {
mac = Mac.getInstance("HMACSHA256");
mac.init(key);
} catch (GeneralSecurityException gse) {
throw new RuntimeException("Unable to initialize HMACSHA256. JVM busted?", gse);
}
byte[] digest = mac.doFinal(encodedJson.getBytes(Charsets.UTF_8));
checkArg(Arrays.equals(new Base64(true).decode(split.get(0)), digest),
"Invalid signature", param, json);
_token = obj.optString("oauth_token", null);
_userId = obj.optString("user_id", null);
}
public String getUserId ()
{
if (!isAuthorized()) {
throw new RuntimeException("No userId. Call isAuthorized before calling getUserId");
}
return _userId;
}
public String getToken ()
{
if (!isAuthorized()) {
throw new RuntimeException("No token. Call isAuthorized before calling getToken");
}
return _token;
}
public boolean isAuthorized ()
{
return _token != null;
}
public boolean isPresent ()
{
return _present;
}
protected void checkArg (boolean condition, String msg, String param, String json)
{
Preconditions.checkArgument(condition, msg + " [req=%s, json=%s]", param, json);
}
protected final boolean _present;
protected final String _token, _userId;
protected static final int ONE_HOUR = 60 * 60;
protected static final Splitter PERIOD_SPLITTER = Splitter.on('.');
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy