de.anycook.social.facebook.FacebookHandler.java Source code

Java tutorial

Introduction

Here is the source code for de.anycook.social.facebook.FacebookHandler.java

Source

/*
 * This file is part of anycook. The new internet cookbook
 * Copyright (C) 2014 Jan Graegger
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see [http://www.gnu.org/licenses/].
 */

package de.anycook.social.facebook;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

import de.anycook.conf.Configuration;
import de.anycook.upload.UserUploader;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.FacebookApi;
import org.scribe.model.Token;
import org.scribe.oauth.OAuthService;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class FacebookHandler {

    private final static Logger LOGGER = LogManager.getLogger(FacebookHandler.class);
    public final static String APP_ID = Configuration.getInstance().getFacebookAppId();
    private final static String APP_SECRET = Configuration.getInstance().getFacebookAppSecret();

    private OAuthService service;

    public FacebookHandler() {
        service = new ServiceBuilder().provider(FacebookApi.class).apiKey(APP_ID).apiSecret(APP_SECRET)
                .callback("http://test.anycook.de/anycook/NewFacebookUser").build();
    }

    public String getAuthURL() {
        Token requestToken = service.getRequestToken();
        return service.getAuthorizationUrl(requestToken);
    }

    @SuppressWarnings("unchecked")
    public static String publishtoWall(long facebookID, String accessToken, String message, String header)
            throws IOException {
        StringBuilder out = new StringBuilder();
        StringBuilder data = new StringBuilder();
        data.append("access_token=").append(URLEncoder.encode(accessToken, "UTF-8"));
        data.append("&message=").append(URLEncoder.encode(message, "UTF-8"));
        data.append("&name=").append(URLEncoder.encode(header, "UTF-8"));

        URL url = new URL("https://api.facebook.com/" + facebookID + "/feed");
        URLConnection conn = url.openConnection();
        conn.setDoOutput(true);
        try (OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream())) {
            wr.write(data.toString());
            wr.flush();

            try (BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                String line;
                while ((line = rd.readLine()) != null) {
                    out.append(line);
                }
            }
        }

        return out.toString();
    }

    public static String getPermissions(String accessToken, long facebookID) throws IOException {
        StringBuilder out = new StringBuilder();

        String data = "?access_token=" + accessToken;
        URL url = new URL("https://api.facebook.com/" + facebookID + "/permissions" + data);
        URLConnection conn = url.openConnection();
        //conn.setDoOutput(true);
        //OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        //wr.write(data);
        //wr.flush();

        try (BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
            String line;
            while ((line = rd.readLine()) != null) {
                out.append(line);
            }
        }

        return out.toString();
    }

    public static FacebookRequest decode(String input) throws IOException {
        String[] split = input.split("\\.");
        String sig = decodeBase64(split[0]);
        String data = decodeBase64(split[1]);
        if (verifySigSHA256(sig, split[1])) {
            LOGGER.debug(data);
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(data, FacebookRequest.class);
        }
        throw new IOException("failed to parse fb request");

    }

    public static String getUsersOAuthToken(long facebook_id) throws IOException {
        URL url = new URL("https://graph.facebook.com/anycook.oauth/access_token?" + "client_id=" + APP_ID + "&"
                + "client_secret=" + APP_SECRET + "&" + "grant_type=client_credentials");
        URLConnection urlconnection = url.openConnection();
        BufferedReader rd = new BufferedReader(new InputStreamReader(urlconnection.getInputStream()));
        String response = rd.readLine();
        return response.split("=")[1];

    }

    public static boolean verifySigSHA256(String sig, String payload) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret = new SecretKeySpec(APP_SECRET.getBytes(), "HmacSHA256");
            mac.init(secret);
            byte[] digest = mac.doFinal(payload.getBytes());
            String expected_sig = new String(digest);
            if (sig.equals(expected_sig)) {
                return true;
            }
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            LOGGER.error(e, e);
        }
        LOGGER.error("signatures are not the same!");
        return false;
    }

    public static boolean verifySigMD5(String sig, String payload) {
        String tocheck = payload + APP_SECRET;
        String expected_sig = null;
        try {
            expected_sig = DigestUtils.md5Hex(tocheck.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            LOGGER.error(e);
        }
        if (sig.equals(expected_sig)) {
            return true;
        }
        LOGGER.error("signatures are not the same!");
        return false;

    }

    private static String decodeBase64(String input) {
        return new String(new Base64(true).decode(input));
    }

    public static String getFacebookImagePath(Long facebook_id) {
        return "https://graph.facebook.com/" + facebook_id + "/picture";
    }

    public static String saveImage(long facebook_id) throws SQLException, IOException {
        UserUploader up = new UserUploader();
        String imageName = up.saveFBURLImage(getFacebookImagePath(facebook_id));
        LOGGER.info("uploaded new FB image");
        return imageName;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class FacebookRequest {

        public String algorithm;

        public String code;

        public long expires;

        public long issued_at;

        public String oauth_token;

        public Map<String, String> registration;

        public Map<String, String> registration_metadata;

        public Map<String, String> user;
        public String user_id;
    }

}