org.infoscoop.request.SignedAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.infoscoop.request.SignedAuthenticator.java

Source

/* infoScoop OpenSource
 * Copyright (C) 2010 Beacon IT Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0-standalone.html>.
 */

package org.infoscoop.request;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import net.oauth.client.OAuthClient;
import net.oauth.client.httpclient3.HttpClient3;
import net.oauth.signature.RSA_SHA1;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infoscoop.acl.SecurityController;
import org.infoscoop.dao.OAuthCertificateDAO;
import org.infoscoop.dao.model.OAuthCertificate;
import org.infoscoop.util.RequestUtil;

public class SignedAuthenticator implements Authenticator {
    public static final OAuthClient CLIENT = new OAuthClient(new HttpClient3());
    private static final String PUBLIC_KEY_NAME = "public.cer";

    private static Log log = LogFactory.getLog(SignedAuthenticator.class);

    public SignedAuthenticator() {
    }

    public void doAuthentication(HttpClient client, ProxyRequest request, HttpMethod method, String uid, String pwd)
            throws ProxyAuthenticationException {
        try {
            OAuthConsumer consumer = newConsumer();
            OAuthAccessor accessor = new OAuthAccessor(consumer);

            Map<String, String> optionParams = new HashMap<String, String>(request.getFilterParameters());

            String targetUrlPath = analyzeUrl(request.getTargetURL(), optionParams);

            String userId = SecurityController.getPrincipalByType("UIDPrincipal").getName();
            optionParams.put("opensocial_viewer_id", userId);
            optionParams.put("opensocial_owner_id", userId);
            optionParams.put("opensocial_app_url", request.getRequestHeader("gadgetUrl"));
            optionParams.put("opensocial_app_id", request.getRequestHeader("moduleId"));
            optionParams.put("opensocial_instance_id", request.getRequestHeader("moduleId"));
            optionParams.put("xoauth_signature_publickey", PUBLIC_KEY_NAME);
            optionParams.put("xoauth_public_key", PUBLIC_KEY_NAME);

            Map<String, String> postParams = new HashMap<String, String>();
            String contentType = request.getRequestHeader("Content-Type");
            if (contentType != null && contentType.startsWith("application/x-www-form-urlencoded")
                    && method.getName().equalsIgnoreCase("POST")) {

                String charset = RequestUtil.getCharset(contentType);
                postParams = RequestUtil.parseRequestBody(request.getRequestBody(), charset);
                optionParams.putAll(postParams);
            }

            OAuthMessage message = new OAuthMessage(method.getName(), targetUrlPath, optionParams.entrySet());
            message.addRequiredParameters(accessor);
            List<Map.Entry<String, String>> authParams = message.getParameters();
            List<NameValuePair> queryParams = buildQueryParams(authParams, postParams);
            method.setQueryString((NameValuePair[]) queryParams.toArray(new NameValuePair[0]));

        } catch (Exception e) {
            throw new ProxyAuthenticationException(e);
        }
    }

    public int getCredentialType() {
        return 3;
    }

    protected OAuthConsumer newConsumer() throws ProxyAuthenticationException {
        OAuthCertificate certificate = OAuthCertificateDAO.newInstance().get();
        if (certificate == null)
            throw new ProxyAuthenticationException("a container's certificate is not set.");
        OAuthServiceProvider serviceProvider = new OAuthServiceProvider(null, null, null);
        OAuthConsumer consumer = new OAuthConsumer(null, certificate.getConsumerKey(), null, serviceProvider);
        consumer.setProperty("oauth_signature_method", "RSA-SHA1");
        consumer.setProperty(RSA_SHA1.PRIVATE_KEY, certificate.getPrivateKey());

        return consumer;
    }

    private static String getRequestUrl(URL url) {
        StringBuilder requestUrl = new StringBuilder();
        String scheme = url.getProtocol();
        int port = url.getPort();

        requestUrl.append(scheme);
        requestUrl.append("://");
        requestUrl.append(url.getHost());

        if ((port != -1) && ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443))) {
            requestUrl.append(":");
            requestUrl.append(port);
        }

        requestUrl.append(url.getPath());
        return requestUrl.toString();
    }

    private String analyzeUrl(String url, Map<String, String> optionParams) throws MalformedURLException {
        URL u = new URL(url);
        String query = u.getQuery();
        if (query != null) {
            String[] params = query.split("&");
            for (int i = 0; i < params.length; i++) {
                try {
                    String[] param = splitParameter(params[i].split("="));
                    String name = URLDecoder.decode(param[0], "UTF-8");
                    if (name.startsWith("oauth") || name.startsWith("xoauth") || name.startsWith("opensocial"))
                        continue;
                    optionParams.put(name, URLDecoder.decode(param[1], "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
        return getRequestUrl(u);
    }

    private List<NameValuePair> buildQueryParams(List<Map.Entry<String, String>> authParams,
            Map<String, String> postParams) {

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : authParams) {
            if (postParams.keySet().contains(entry.getKey())) {
                postParams.remove(entry.getKey());
                continue;
            }

            params.add(new NameValuePair(entry.getKey(), entry.getValue()));
        }
        return params;
    }

    private static String[] splitParameter(String[] params) {
        String[] sp = new String[2];
        switch (params.length) {
        case 1:
            sp[0] = params[0];
            sp[1] = "";
            break;
        case 2:
            sp = params;
            break;
        }
        return sp;
    }
}