package org.fluxtream.connectors.beddit; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.fluxtream.core.Configuration; import org.fluxtream.core.auth.AuthHelper; import org.fluxtream.core.connectors.Connector; import org.fluxtream.core.domain.ApiKey; import org.fluxtream.core.domain.Guest; import org.fluxtream.core.services.GuestService; import org.fluxtream.core.services.JPADaoService; import org.fluxtream.core.utils.HttpUtils; import org.fluxtream.core.utils.UnexpectedHttpResponseCodeException; import org.joda.time.DateTimeConstants; import org.scribe.builder.ServiceBuilder; import org.scribe.model.Token; import org.scribe.model.Verifier; import org.scribe.oauth.OAuthService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import scala.xml.dtd.EMPTY; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.security.GeneralSecurityException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.*; /** * Created by candide on 09/02/15. */ @Controller @RequestMapping(value = "/beddit") public class BedditOAuth2Controller { private static final String BEDDIT_SERVICE = "bedditService"; private static final String BEDDIT_REQUEST_TOKEN = "bedditRequestToken"; private static final String BEDDIT_RENEWTOKEN_APIKEYID = "beddit.renewtoken.apiKeyId"; private static final Token EMPTY_TOKEN = null; @Autowired GuestService guestService; @Autowired JPADaoService jpaDaoService; @Autowired Configuration env; // this seems to be needed in order to be able to access the beddit servers from — at least – my local dev machine static void trustAllSSLCertificates() { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (GeneralSecurityException e) { } } @RequestMapping(value = "/token") public String getBedditToken(HttpServletRequest request) throws IOException, ServletException { if (env.get("development") != null && env.get("development").equals("true")) trustAllSSLCertificates(); OAuthService service = new ServiceBuilder() .provider(BedditApi.class) .apiKey(env.get("bedditConsumerKey")) .apiSecret(env.get("bedditConsumerSecret")) .callback(env.get("homeBaseUrl") + "beddit/upgradeToken") .build(); request.getSession().setAttribute(BEDDIT_SERVICE, service); // Obtain the Authorization URL String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN); final String apiKeyIdParameter = request.getParameter("apiKeyId"); if (apiKeyIdParameter != null) request.getSession().setAttribute(BEDDIT_RENEWTOKEN_APIKEYID, apiKeyIdParameter); return "redirect:" + authorizationUrl; } @RequestMapping(value = "/upgradeToken") public String upgradeToken(HttpServletRequest request) throws IOException, UnexpectedHttpResponseCodeException, NoSuchAlgorithmException, KeyManagementException { final String code = request.getParameter("code"); Map<String,String> parameters = new HashMap<String,String>(); parameters.put("grant_type", "authorization_code"); parameters.put("code", code); parameters.put("redirect_uri", env.get("homeBaseUrl") + "beddit/upgradeToken"); parameters.put("client_id", env.get("bedditConsumerKey")); parameters.put("client_secret", env.get("bedditConsumerSecret")); final String json = fetch("https://cloudapi.beddit.com/api/v1/auth/authorize", parameters); JSONObject token = JSONObject.fromObject(json); // Create the entry for this new apiKey in the apiKey table and populate // ApiKeyAttributes with all of the keys fro oauth.properties needed for // subsequent update of this connector instance. ApiKey apiKey; Guest guest = AuthHelper.getGuest(); final Connector connector = Connector.getConnector("beddit"); final String stateParameter = request.getParameter("state"); if (stateParameter !=null&&!StringUtils.isEmpty(stateParameter)) { long apiKeyId = Long.valueOf(stateParameter); apiKey = guestService.getApiKey(apiKeyId); } else { apiKey = guestService.createApiKey(guest.getId(), connector); } guestService.populateApiKey(apiKey.getId()); guestService.setApiKeyAttribute(apiKey, "accessToken", token.getString("access_token")); guestService.setApiKeyAttribute(apiKey, "userid", token.getString("user")); request.getSession().removeAttribute(BEDDIT_REQUEST_TOKEN); request.getSession().removeAttribute(BEDDIT_SERVICE); if (request.getSession().getAttribute(BEDDIT_RENEWTOKEN_APIKEYID) != null) { request.getSession().removeAttribute(BEDDIT_RENEWTOKEN_APIKEYID); return "redirect:/app/tokenRenewed/beddit"; } return "redirect:/app/from/beddit"; } public String fetch(String url, Map<String, String> params) throws UnexpectedHttpResponseCodeException, IOException, KeyManagementException, NoSuchAlgorithmException { HttpClient client = env.getHttpClient(); if (env.get("development") != null && env.get("development").equals("true")) { // HttpHost proxy = new HttpHost("127.0.0.1", 8888, "http"); // client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy); client = HttpUtils.httpClientTrustingAllSSLCerts(); } String content = ""; try { HttpPost post = new HttpPost(url); Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator(); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params.size()); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8")); HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { ResponseHandler<String> responseHandler = new BasicResponseHandler(); content = responseHandler.handleResponse(response); } else { throw new UnexpectedHttpResponseCodeException(response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase()); } } finally { client.getConnectionManager().shutdown(); } return content; } }