Refactored classes in thematically packages
[facebook-errors] / src / main / java / de / juplo / facebook / SignedRequestAwareAuthorizationCodeAccessTokenProvider.java
diff --git a/src/main/java/de/juplo/facebook/SignedRequestAwareAuthorizationCodeAccessTokenProvider.java b/src/main/java/de/juplo/facebook/SignedRequestAwareAuthorizationCodeAccessTokenProvider.java
deleted file mode 100644 (file)
index fcae74a..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-package de.juplo.facebook;
-
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import org.apache.commons.codec.binary.Base64;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
-import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
-import org.springframework.security.oauth2.client.token.AccessTokenRequest;
-import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
-import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
-
-
-/**
- * This class extends {@link AuthorizationCodeAccessTokenProvider} and adds
- * support for signed requests, which are issued by Facebook, if the Canvas-
- * or Tab-Page of a Facebook-App is accessed for the first time.
- *
- * @author Kai Moritz
- */
-public class SignedRequestAwareAuthorizationCodeAccessTokenProvider
-    extends AuthorizationCodeAccessTokenProvider
-{
-  private final Logger log =
-      LoggerFactory.getLogger(SignedRequestAwareAuthorizationCodeAccessTokenProvider.class);
-  private final static Pattern pattern =
-      Pattern.compile("([a-zA-Z0-9_-]+)\\.([a-zA-Z0-9_-]+)");
-
-  public final static String PARAM_SIGNED_REQUEST = "signed_request";
-
-
-  private String secret;
-  private ObjectMapper objectMapper;
-
-
-  @Override
-  public OAuth2AccessToken obtainAccessToken(
-      OAuth2ProtectedResourceDetails details,
-      AccessTokenRequest parameters
-      )
-  {
-    try
-    {
-      return super.obtainAccessToken(details, parameters);
-    }
-    catch (UserRedirectRequiredException redirect)
-    {
-      log.debug("no valid access-token available: checking for signed request");
-
-      if (!parameters.containsKey(PARAM_SIGNED_REQUEST))
-      {
-        log.info(
-            "parameter " + PARAM_SIGNED_REQUEST + " is not present"
-            );
-        throw redirect;
-      }
-
-      String signed_request = parameters.get(PARAM_SIGNED_REQUEST).get(0);
-
-      Matcher matcher = pattern.matcher(signed_request);
-      if (!matcher.matches())
-      {
-        log.error("invalid signed_request: {}", signed_request);
-        throw redirect;
-      }
-
-      String signature = matcher.group(1);
-      String rawdata = matcher.group(2);
-
-      String data;
-      try
-      {
-        data = new String(Base64.decodeBase64(rawdata), "UTF-8");
-        log.debug("JSON-data: {}", data);
-      }
-      catch (UnsupportedEncodingException e)
-      {
-        log.error("error while decoding data: {}", e.getMessage());
-        throw redirect;
-      }
-
-      JsonNode json;
-      try
-      {
-        json = objectMapper.readTree(data);
-      }
-      catch (IOException e)
-      {
-        log.error("error \"{}\" while parsing JSON-data: {}", e, data);
-        throw redirect;
-      }
-
-      String algorithm = "";
-      try
-      {
-        algorithm = json.get("algorithm").asText();
-      }
-      catch (NullPointerException e) {}
-      if (algorithm.isEmpty())
-      {
-        log.error("field \"algorithm\" is missing: {}", data);
-        throw redirect;
-      }
-      algorithm = algorithm.replaceAll("-", "");
-
-      String check;
-      try
-      {
-        SecretKeySpec key = new SecretKeySpec(secret.getBytes("UTF-8"), algorithm);
-        Mac mac = Mac.getInstance(algorithm);
-        mac.init(key);
-        byte[] hmacData = mac.doFinal(rawdata.getBytes("UTF-8"));
-        check = new String(Base64.encodeBase64URLSafe(hmacData), "UTF-8");
-      }
-      catch (
-          UnsupportedEncodingException |
-          NoSuchAlgorithmException |
-          InvalidKeyException |
-          IllegalStateException e
-          )
-      {
-        log.error("signature check failed!", e);
-        throw redirect;
-      }
-      if (!check.equals(signature))
-      {
-        log.error("signature does not match!");
-        throw redirect;
-      }
-
-      /**
-       * Extract additional information and store it in the token
-       * See:
-       * https://developers.facebook.com/docs/reference/login/signed-request/
-       * TODO:
-       * - Attribute "code"
-       */
-      Map<String,Object> additionalInformation = new HashMap<>();
-      try
-      {
-        additionalInformation.put(
-            "issued_at",
-            new Date(json.get("issued_at").getLongValue()*1000L)
-            );
-        Map<String,Object> user = new HashMap<>();
-        user.put(
-            "country",
-            json.get("user").get("country").asText()
-            );
-        user.put(
-            "locale",
-            json.get("user").get("locale").asText()
-            );
-        user.put(
-            "age_min",
-            json.get("user").get("age").get("min").getNumberValue()
-            );
-        if (json.get("user") != null && json.get("user").get("max") != null)
-          user.put(
-              "age_max",
-              json.get("user").get("age").get("max").getNumberValue()
-              );
-        additionalInformation.put("user", user);
-        if (json.get("app_data") != null)
-          additionalInformation.put("app_data", json.get("app_data").asText());
-        if (json.get("page") != null)
-        {
-          Map<String,Object> page = new HashMap<>();
-          page.put("id", json.get("page").get("id").asText());
-          page.put("liked", json.get("page").get("liked").asBoolean());
-          page.put("admin", json.get("page").get("admin").asBoolean());
-          additionalInformation.put("page", page);
-        }
-      }
-      catch (NullPointerException e)
-      {
-        log.warn("expected additional data is missing: {}", data);
-      }
-
-      DefaultOAuth2AccessToken token = null;
-      try
-      {
-        String value = json.get("oauth_token").asText();
-        if (value.isEmpty())
-        {
-          log.error("field \"oauth_token\" is missing: {}", data);
-          throw redirect;
-        }
-        token = new DefaultOAuth2AccessToken(value);
-        token.setExpiration(new Date(json.get("expires").getLongValue()*1000L));
-
-        additionalInformation.put(
-            "user_id",
-            json.get("user_id").asText()
-            );
-
-        token.setAdditionalInformation(additionalInformation);
-      }
-      catch (NullPointerException e)
-      {
-        if (token == null)
-        {
-          log.error("field \"oauth_token\" is missing: {}", data);
-          throw redirect;
-        }
-        else
-          log.warn("expected additional data is missing: {}", data);
-      }
-
-      return token;
-    }
-  }
-
-
-  public String getSecret()
-  {
-    return secret;
-  }
-
-  public void setSecret(String secret)
-  {
-    this.secret = secret;
-  }
-
-  public ObjectMapper getObjectMapper()
-  {
-    return objectMapper;
-  }
-
-  public void setObjectMapper(ObjectMapper objectMapper)
-  {
-    this.objectMapper = objectMapper;
-  }
-}