X-Git-Url: https://juplo.de/gitweb/?p=website;a=blobdiff_plain;f=dist%2Ffacebook-utils-2.5.0%2Fxref%2Fde%2Fjuplo%2Ffacebook%2Ftoken%2FSignedRequestAwareAuthorizationCodeAccessTokenProvider.html;fp=dist%2Ffacebook-utils-2.5.0%2Fxref%2Fde%2Fjuplo%2Ffacebook%2Ftoken%2FSignedRequestAwareAuthorizationCodeAccessTokenProvider.html;h=0000000000000000000000000000000000000000;hp=5b65226f186e565f4f093b35282b3c765c438712;hb=b293b312d6f0dd8b2dc716375fd442dd295a9942;hpb=9179a67d9952d3b63e95686dbd6cacd3c9e13cb2 diff --git a/dist/facebook-utils-2.5.0/xref/de/juplo/facebook/token/SignedRequestAwareAuthorizationCodeAccessTokenProvider.html b/dist/facebook-utils-2.5.0/xref/de/juplo/facebook/token/SignedRequestAwareAuthorizationCodeAccessTokenProvider.html deleted file mode 100644 index 5b65226f..00000000 --- a/dist/facebook-utils-2.5.0/xref/de/juplo/facebook/token/SignedRequestAwareAuthorizationCodeAccessTokenProvider.html +++ /dev/null @@ -1,261 +0,0 @@ - - -
--1 package de.juplo.facebook.token; -2 -3 -4 import java.io.IOException; -5 import java.io.UnsupportedEncodingException; -6 import java.security.InvalidKeyException; -7 import java.security.NoSuchAlgorithmException; -8 import java.util.Date; -9 import java.util.HashMap; -10 import java.util.Map; -11 import java.util.regex.Matcher; -12 import java.util.regex.Pattern; -13 import javax.crypto.Mac; -14 import javax.crypto.spec.SecretKeySpec; -15 import org.apache.commons.codec.binary.Base64; -16 import org.codehaus.jackson.JsonNode; -17 import org.codehaus.jackson.map.ObjectMapper; -18 import org.slf4j.Logger; -19 import org.slf4j.LoggerFactory; -20 import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; -21 import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; -22 import org.springframework.security.oauth2.client.token.AccessTokenRequest; -23 import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider; -24 import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -25 import org.springframework.security.oauth2.common.OAuth2AccessToken; -26 -27 -28 /** -29 * This class extends {@link AuthorizationCodeAccessTokenProvider} and adds -30 * support for signed requests, which are issued by Facebook, if the Canvas- -31 * or Tab-Page of a Facebook-App is accessed for the first time. -32 * -33 * @author Kai Moritz -34 */ -35 public class SignedRequestAwareAuthorizationCodeAccessTokenProvider -36 extends AuthorizationCodeAccessTokenProvider -37 { -38 private final Logger log = -39 LoggerFactory.getLogger(SignedRequestAwareAuthorizationCodeAccessTokenProvider.class); -40 private final static Pattern pattern = -41 Pattern.compile("([a-zA-Z0-9_-]+)\\.([a-zA-Z0-9_-]+)"); -42 -43 public final static String PARAM_SIGNED_REQUEST = "signed_request"; -44 -45 -46 private String secret; -47 private ObjectMapper objectMapper; -48 -49 -50 @Override -51 public OAuth2AccessToken obtainAccessToken( -52 OAuth2ProtectedResourceDetails details, -53 AccessTokenRequest parameters -54 ) -55 { -56 try -57 { -58 return super.obtainAccessToken(details, parameters); -59 } -60 catch (UserRedirectRequiredException redirect) -61 { -62 log.debug("no valid access-token available: checking for signed request"); -63 -64 if (!parameters.containsKey(PARAM_SIGNED_REQUEST)) -65 { -66 log.info( -67 "parameter " + PARAM_SIGNED_REQUEST + " is not present" -68 ); -69 throw redirect; -70 } -71 -72 String signed_request = parameters.get(PARAM_SIGNED_REQUEST).get(0); -73 -74 Matcher matcher = pattern.matcher(signed_request); -75 if (!matcher.matches()) -76 { -77 log.error("invalid signed_request: {}", signed_request); -78 throw redirect; -79 } -80 -81 String signature = matcher.group(1); -82 String rawdata = matcher.group(2); -83 -84 String data; -85 try -86 { -87 data = new String(Base64.decodeBase64(rawdata), "UTF-8"); -88 log.debug("JSON-data: {}", data); -89 } -90 catch (UnsupportedEncodingException e) -91 { -92 log.error("error while decoding data: {}", e.getMessage()); -93 throw redirect; -94 } -95 -96 JsonNode json; -97 try -98 { -99 json = objectMapper.readTree(data); -100 } -101 catch (IOException e) -102 { -103 log.error("error \"{}\" while parsing JSON-data: {}", e, data); -104 throw redirect; -105 } -106 -107 String algorithm = ""; -108 try -109 { -110 algorithm = json.get("algorithm").asText(); -111 } -112 catch (NullPointerException e) {} -113 if (algorithm.isEmpty()) -114 { -115 log.error("field \"algorithm\" is missing: {}", data); -116 throw redirect; -117 } -118 algorithm = algorithm.replaceAll("-", ""); -119 -120 String check; -121 try -122 { -123 SecretKeySpec key = new SecretKeySpec(secret.getBytes("UTF-8"), algorithm); -124 Mac mac = Mac.getInstance(algorithm); -125 mac.init(key); -126 byte[] hmacData = mac.doFinal(rawdata.getBytes("UTF-8")); -127 check = new String(Base64.encodeBase64URLSafe(hmacData), "UTF-8"); -128 } -129 catch ( -130 UnsupportedEncodingException | -131 NoSuchAlgorithmException | -132 InvalidKeyException | -133 IllegalStateException e -134 ) -135 { -136 log.error("signature check failed!", e); -137 throw redirect; -138 } -139 if (!check.equals(signature)) -140 { -141 log.error("signature does not match!"); -142 throw redirect; -143 } -144 -145 /** -146 * Extract additional information and store it in the token -147 * See: -148 * https://developers.facebook.com/docs/reference/login/signed-request/ -149 * TODO: -150 * - Attribute "code" -151 */ -152 Map<String,Object> additionalInformation = new HashMap<>(); -153 try -154 { -155 additionalInformation.put( -156 "issued_at", -157 new Date(json.get("issued_at").getLongValue()*1000L) -158 ); -159 Map<String,Object> user = new HashMap<>(); -160 user.put( -161 "country", -162 json.get("user").get("country").asText() -163 ); -164 user.put( -165 "locale", -166 json.get("user").get("locale").asText() -167 ); -168 user.put( -169 "age_min", -170 json.get("user").get("age").get("min").getNumberValue() -171 ); -172 if (json.get("user") != null && json.get("user").get("max") != null) -173 user.put( -174 "age_max", -175 json.get("user").get("age").get("max").getNumberValue() -176 ); -177 additionalInformation.put("user", user); -178 if (json.get("app_data") != null) -179 additionalInformation.put("app_data", json.get("app_data").asText()); -180 if (json.get("page") != null) -181 { -182 Map<String,Object> page = new HashMap<>(); -183 page.put("id", json.get("page").get("id").asText()); -184 page.put("liked", json.get("page").get("liked").asBoolean()); -185 page.put("admin", json.get("page").get("admin").asBoolean()); -186 additionalInformation.put("page", page); -187 } -188 } -189 catch (NullPointerException e) -190 { -191 log.warn("expected additional data is missing: {}", data); -192 } -193 -194 DefaultOAuth2AccessToken token = null; -195 try -196 { -197 String value = json.get("oauth_token").asText(); -198 if (value.isEmpty()) -199 { -200 log.error("field \"oauth_token\" is missing: {}", data); -201 throw redirect; -202 } -203 token = new DefaultOAuth2AccessToken(value); -204 token.setExpiration(new Date(json.get("expires").getLongValue()*1000L)); -205 -206 additionalInformation.put( -207 "user_id", -208 json.get("user_id").asText() -209 ); -210 -211 token.setAdditionalInformation(additionalInformation); -212 } -213 catch (NullPointerException e) -214 { -215 if (token == null) -216 { -217 log.error("field \"oauth_token\" is missing: {}", data); -218 throw redirect; -219 } -220 else -221 log.warn("expected additional data is missing: {}", data); -222 } -223 -224 return token; -225 } -226 } -227 -228 -229 public String getSecret() -230 { -231 return secret; -232 } -233 -234 public void setSecret(String secret) -235 { -236 this.secret = secret; -237 } -238 -239 public ObjectMapper getObjectMapper() -240 { -241 return objectMapper; -242 } -243 -244 public void setObjectMapper(ObjectMapper objectMapper) -245 { -246 this.objectMapper = objectMapper; -247 } -248 } --