es.tid.fiware.rss.oauth.service.OauthManager.java Source code

Java tutorial

Introduction

Here is the source code for es.tid.fiware.rss.oauth.service.OauthManager.java

Source

/**
 * Revenue Settlement and Sharing System GE
 * Copyright (C) 2011-2014, Javier Lucio - lucio@tid.es
 * Telefonica Investigacion y Desarrollo, S.A.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package es.tid.fiware.rss.oauth.service;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;

import es.tid.fiware.rss.common.properties.AppProperties;
import es.tid.fiware.rss.exception.RSSException;
import es.tid.fiware.rss.exception.UNICAExceptionType;
import es.tid.fiware.rss.oauth.model.ApplicationInfo;
import es.tid.fiware.rss.oauth.model.OauthLoginWebSessionData;
import es.tid.fiware.rss.oauth.model.Role;
import es.tid.fiware.rss.oauth.model.ValidatedToken;

@Service
public class OauthManager {
    private static final Logger log = LoggerFactory.getLogger(OauthManager.class);
    /**
     * private properties.
     */
    private String clientId;
    private String clientSecret;
    private String baseSite;
    private String authorizeUrl;
    private String accessTokenUrl;
    private String callbackURL;
    private String externalLogin;
    private String useOauth = "";
    private String userInfoUrl;
    private String getApplicationsUrl;
    private String grantedRole;
    private final String authMethod = "Basic ";
    @Autowired
    @Qualifier(value = "oauthProperties")
    private AppProperties oauthProperties;
    /**
     * 
     */
    private final DefaultHttpClient httpclient = new DefaultHttpClient();
    /**
     * handler that manages responses
     */
    private ResponseHandler handler = new ResponseHandler();

    /**
     * Read needed properties from file.
     */
    @PostConstruct
    private void readProperties() throws Exception {
        externalLogin = oauthProperties.getProperty("config.externalLogin");
        baseSite = oauthProperties.getProperty("config.baseUrl");
        clientId = oauthProperties.getProperty("config.client_id");
        clientSecret = oauthProperties.getProperty("config.client_secret");
        authorizeUrl = oauthProperties.getProperty("config.authorizeUrl");
        accessTokenUrl = oauthProperties.getProperty("config.accessTokenUrl");
        callbackURL = oauthProperties.getProperty("config.callbackURL");
        userInfoUrl = oauthProperties.getProperty("config.userInfoUrl");
        grantedRole = oauthProperties.getProperty("config.grantedRole");
        getApplicationsUrl = oauthProperties.getProperty("config.getApplications");
        useOauth = oauthProperties.getProperty("config.useOauth");
        // avoid certificate checking for problems regarding with them.
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        ctx.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", ssf, 443));
    }

    /**
     * Destroy connection.
     */
    @PreDestroy
    private void destroyConnection() {
        httpclient.getConnectionManager().shutdown();
    }

    /**
     * @return the grantedRole
     */
    public String getGrantedRole() {
        return grantedRole;
    }

    /**
     * Get authentication header.
     * 
     * @return
     */
    public String buildHeader() {
        String pair = clientId + ":" + clientSecret;
        String encoded = new String(Base64.encodeBase64(pair.getBytes()));
        String authentication = authMethod + encoded;
        return authentication;
    }

    /**
     * Check if external login is allowed.
     * 
     * @return
     */
    public boolean hasExternalLogin() {
        if ("Y".equalsIgnoreCase(externalLogin)) {
            return true;
        }
        return false;
    }

    /**
     * Get authorization Url.
     * 
     * @return
     */
    public String getAuthorizationUrl() {
        return this.baseSite + this.authorizeUrl + "?response_type=code&client_id=" + this.clientId
                + "&state=xyz&redirect_uri=" + this.callbackURL;
    }

    /**
     * Get token url.
     * 
     * @param code
     * @return
     */
    public String getTokenUrl(String code) {
        return this.baseSite + this.accessTokenUrl + "?grant_type=authorization_code&code=" + code
                + "&redirect_uri=" + this.callbackURL;
    }

    /**
     * Get user Info Url.
     * 
     * @param token
     * @return
     */
    public String getInfoUserUrl(String token) {
        return this.baseSite + this.userInfoUrl + token;
    }

    /**
     * Get user Info Url.
     * 
     * @param actorId
     * @param token
     * @return
     */
    public String getAplicationsUrl(String actorId, String token) {
        return this.baseSite + this.getApplicationsUrl + actorId + "&access_token=" + token;
    }

    /**
     * Get token data.
     * 
     * @param code
     *            Code to build url.
     * @throws Exception
     */
    public OauthLoginWebSessionData getToken(String code) throws Exception {
        OauthManager.log.debug("getToken method");
        // grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
        // &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcallback_url
        try {
            OauthManager.log.debug("Code:" + code);
            HttpPost httppost = new HttpPost(getTokenUrl(code));
            httppost.addHeader("Authorization", buildHeader());
            httppost.addHeader("Content-Type", "application/x-www-form-urlencoded");

            OauthManager.log.debug("executing request" + httppost.getRequestLine());
            // send request
            HttpResponse response = httpclient.execute(httppost, handler);
            OauthManager.log.debug("----------------------------------------");
            OauthManager.log.debug(response.getStatusLine().toString());
            if (handler.hasContent()) {
                OauthManager.log.debug("----------------------------------------");
                OauthManager.log.debug("Response content:");
                OauthManager.log.debug(handler.getResponseContent());
                if (handler.getStatus() != 200) {
                    OauthManager.log
                            .error("Error Status different to 200 received " + handler.getResponseContent());
                    throw new RSSException(handler.getResponseContent());
                }
                ObjectMapper mapper = new ObjectMapper();
                /*
                 * {
                 * "access_token":"2YotnFZFEjr1zCsicMWpAA",
                 * "token_type":"bearer",
                 * "expires_in":3600,
                 * "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
                 * }
                 */
                OauthLoginWebSessionData session = mapper.readValue(handler.getResponseContent(),
                        OauthLoginWebSessionData.class);
                return session;
            } else if (handler.getStatus() != 200) {
                OauthManager.log.error("Error Status different to 200 received " + handler.getResponseContent());
                throw new RSSException(handler.getResponseContent());
            }
            return null;
        } catch (RSSException ex) {
            throw ex;
        } catch (Exception e) {
            OauthManager.log.error("Error obtaining token:" + e.toString(), e);
            throw new Exception("Error obtaining token: " + e.toString());
        } finally {
            httpclient.getConnectionManager().closeExpiredConnections();
        }

    }

    /**
     * Check if the user has permissions to access to web.
     * 
     * @param session
     * @throws Exception
     */
    public void checkUserPermisions(OauthLoginWebSessionData session) throws Exception {
        OauthManager.log.debug("getUserInfo method");
        ValidatedToken userPermission = getUserInfo(session.getAccessToken());
        session.setEmail(userPermission.getEmail());
        if (null != userPermission.getRoles() && userPermission.getRoles().size() > 0) {
            for (Role role : userPermission.getRoles()) {
                if (grantedRole.equalsIgnoreCase(role.getName())) {
                    session.setRole(role.getName());
                    break;
                }
            }
        } else {
            // no roles --> not allowed to enter
            OauthManager.log.debug("Access not granted for this user.");
            String[] args = { "Restricted Area" };
            throw new RSSException(UNICAExceptionType.CONSUMER_LOGIN_NOT_ALLOWED, args);
        }
    }

    /**
     * Get user Info.
     * 
     * @param token
     * @return
     * @throws Exception
     */
    public ValidatedToken getUserInfo(String token) throws Exception {
        OauthManager.log.debug("getUserInfo method. Token: {}", token);
        try {
            HttpGet httpget = new HttpGet(getInfoUserUrl(token));
            OauthManager.log.debug("executing request" + httpget.getRequestLine());
            // send request
            HttpResponse response = httpclient.execute(httpget, handler);
            OauthManager.log.debug("----------------------------------------");
            OauthManager.log.debug(response.getStatusLine().toString());
            if (handler.hasContent()) {
                OauthManager.log.debug("----------------------------------------");
                OauthManager.log.debug("Response content:");
                OauthManager.log.debug(handler.getResponseContent());
                if (handler.getStatus() != 200) {
                    OauthManager.log
                            .error("Error Status different to 200 received " + handler.getResponseContent());
                    throw new RSSException(handler.getResponseContent());
                }
                ObjectMapper mapper = new ObjectMapper();
                ValidatedToken session = mapper.readValue(handler.getResponseContent(), ValidatedToken.class);
                return session;
            } else if (handler.getStatus() != 200) {
                OauthManager.log.error("Error Status different to 200 received " + handler.getResponseContent());
                throw new RSSException(handler.getResponseContent());
            }
            return null;
        } catch (RSSException ex) {
            throw ex;
        } catch (Exception e) {
            OauthManager.log.error("Error obtaining token:" + e.toString(), e);
            throw new Exception("Error obtaining token: " + e.toString());
        } finally {
            httpclient.getConnectionManager().closeExpiredConnections();
        }
    }

    /**
     * Get applications by client id.
     * 
     * @param userToken
     * @param actorId
     * @return
     * @throws Exception
     */
    public ApplicationInfo[] getClientIdApplications(String userToken, String actorId) throws Exception {
        OauthManager.log.debug("getClientIdApplications method. Token: {}", userToken);
        try {
            HttpGet httpget = new HttpGet(getAplicationsUrl(actorId, userToken));
            OauthManager.log.debug("executing request" + httpget.getRequestLine());
            // send request
            HttpResponse response = httpclient.execute(httpget, handler);
            OauthManager.log.debug("----------------------------------------");
            OauthManager.log.debug(response.getStatusLine().toString());
            if (handler.hasContent()) {
                OauthManager.log.debug("----------------------------------------");
                OauthManager.log.debug("Response content:");
                if (handler.getStatus() != 200) {
                    OauthManager.log
                            .error("Error Status different to 200 received " + handler.getResponseContent());
                    throw new RSSException(handler.getResponseContent());
                }
                OauthManager.log.debug(handler.getResponseContent());
                ObjectMapper mapper = new ObjectMapper();
                ApplicationInfo[] applications = mapper.readValue(handler.getResponseContent(),
                        ApplicationInfo[].class);
                return applications;
            } else if (handler.getStatus() != 200) {
                OauthManager.log.error("Error Status different to 200 received " + handler.getResponseContent());
                throw new Exception(handler.getResponseContent());
            }
            return null;
        } catch (RSSException ex) {
            throw ex;
        } catch (Exception e) {
            OauthManager.log.error("Error obtaining information:" + e.toString(), e);
            throw new Exception("Error obtaining information: " + e.toString());
        } finally {
            httpclient.getConnectionManager().closeExpiredConnections();
        }

    }

    /**
     * Check if the user has sent a valid token.
     * 
     * @param userToken
     * @throws Exception
     */
    public ValidatedToken checkAuthenticationToken(String userToken) throws Exception {
        OauthManager.log.debug("Into checkAuthenticationToken. Token:" + userToken);
        if ("Y".equalsIgnoreCase(useOauth)) {
            if (null != userToken && userToken.length() > 0) {
                // Get user Info
                return getUserInfo(userToken);
                /*
                 * ValidatedToken userInfo = getUserInfo(userToken);
                 * // check user token
                 * ApplicationInfo[] applications = getClientIdApplications(userToken, userInfo.getActorId());
                 * // Finally check if the user has access to the application.
                 * checkApplictionIds(applications);
                 */
            } else {
                String[] args = { "X-Auth-Token header is required" };
                throw new RSSException(UNICAExceptionType.INVALID_OAUTH_TOKEN, args);
            }
        }
        return null;
    }

    /**
     * Check the existence of application Id.
     * 
     * @param applications
     */
    public void checkApplictionIds(ApplicationInfo[] applications) throws Exception {
        boolean found = false;
        if (null != applications && applications.length > 0) {
            for (ApplicationInfo application : applications) {
                if (application.getId().equalsIgnoreCase(this.clientId)) {
                    found = true;
                    break;
                }
            }
        }
        if (!found) {
            String[] args = { "User has not permission" };
            throw new RSSException(UNICAExceptionType.INVALID_OAUTH_TOKEN, args);
        }

    }

}