com.openshift.internal.restclient.authorization.AuthorizationClient.java Source code

Java tutorial

Introduction

Here is the source code for com.openshift.internal.restclient.authorization.AuthorizationClient.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Red Hat, Inc. Distributed under license by Red Hat, Inc.
 * All rights reserved. This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Red Hat, Inc.
 ******************************************************************************/
package com.openshift.internal.restclient.authorization;

import java.io.Closeable;
import java.io.IOException;
import java.net.ProxySelector;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.params.HttpParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.openshift.restclient.IClient;
import com.openshift.restclient.ISSLCertificateCallback;
import com.openshift.restclient.NoopSSLCertificateCallback;
import com.openshift.restclient.OpenShiftException;
import com.openshift.restclient.authorization.IAuthorizationClient;
import com.openshift.restclient.authorization.IAuthorizationContext;
import com.openshift.restclient.authorization.IAuthorizationDetails;
import com.openshift.restclient.authorization.IAuthorizationStrategy;
import com.openshift.restclient.authorization.ResourceForbiddenException;
import com.openshift.restclient.authorization.TokenAuthorizationStrategy;
import com.openshift.restclient.authorization.UnauthorizedException;
import com.openshift.restclient.http.IHttpClient;

/**
 * @author Jeff Cantrill
 */
public class AuthorizationClient implements IAuthorizationClient {
    private static final Logger LOG = LoggerFactory.getLogger(IAuthorizationClient.class);

    private static final int TIMEOUT = 10 * 1000; //10 seconds

    private SSLContext sslContext;
    private X509HostnameVerifier hostnameVerifier = new AllowAllHostnameVerifier();
    private IClient openshiftClient;

    public AuthorizationClient(IClient client) {
        this.openshiftClient = client;
        setSSLCertificateCallback(new NoopSSLCertificateCallback());
    }

    @Override
    public IAuthorizationDetails getAuthorizationDetails(final String baseURL) {
        try {
            getContextUsingCredentials(baseURL, null);
            return new AuthorizationDetails(String.format("%s/oauth/token/request", baseURL));
        } catch (UnauthorizedException e) {
            return e.getAuthorizationDetails();
        }
    }

    @Override
    public IAuthorizationContext getContext(final String baseURL) {
        OpenShiftCredentialsProvider credentialsProvider = new OpenShiftCredentialsProvider();
        openshiftClient.getAuthorizationStrategy().accept(credentialsProvider);
        final IAuthorizationStrategy configuredAuthStrategy = openshiftClient.getAuthorizationStrategy();
        try {
            final String token = credentialsProvider.getToken();
            openshiftClient.setAuthorizationStrategy(new TokenAuthorizationStrategy(token));
            return new AuthorizationContext(token, null, openshiftClient.getCurrentUser(),
                    credentialsProvider.getScheme());
        } catch (ResourceForbiddenException e) {
            //the response if token is invalid because we tried to
            //get the current user
        } catch (UnauthorizedException e) {
            openshiftClient.setAuthorizationStrategy(configuredAuthStrategy);
            return getContextUsingCredentials(baseURL, credentialsProvider);
        } finally {
            openshiftClient.setAuthorizationStrategy(configuredAuthStrategy);
        }
        return getContextUsingCredentials(baseURL, credentialsProvider);

    }

    private IAuthorizationContext getContextUsingCredentials(final String baseURL,
            CredentialsProvider credentialsProvider) {

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        try {
            OpenShiftAuthorizationRedirectStrategy redirectStrategy = new OpenShiftAuthorizationRedirectStrategy(
                    openshiftClient);
            RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT)
                    .setConnectTimeout(TIMEOUT).setConnectionRequestTimeout(TIMEOUT)
                    .setStaleConnectionCheckEnabled(true).build();
            client = HttpClients.custom().setRedirectStrategy(redirectStrategy)
                    .setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
                    .setHostnameVerifier(hostnameVerifier).setDefaultCredentialsProvider(credentialsProvider)
                    .setSslcontext(sslContext).setDefaultRequestConfig(defaultRequestConfig).build();
            HttpGet request = new HttpGet(new URIBuilder(String.format("%s/oauth/authorize", baseURL))
                    .addParameter("response_type", "token")
                    .addParameter("client_id", "openshift-challenging-client").build());
            request.addHeader("X-CSRF-Token", "1");
            response = client.execute(request);
            return redirectStrategy.getAuthorizationContext();
        } catch (URISyntaxException e) {
            throw new OpenShiftException(e, String
                    .format("Unvalid URI while trying to get an authorization context for server %s", baseURL));
        } catch (ClientProtocolException e) {
            throw new OpenShiftException(e, String.format(
                    "Client protocol exception while trying to get authorization context for server %s", baseURL));
        } catch (IOException e) {
            throw new OpenShiftException(e,
                    String.format("%s while trying to get an authorization context for server %s",
                            e.getClass().getName(), baseURL));
        } finally {
            close(response);
            close(client);
        }

    }

    private void close(Closeable closer) {
        if (closer == null)
            return;
        try {
            closer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setSSLCertificateCallback(ISSLCertificateCallback callback) {
        X509TrustManager trustManager = null;
        if (callback != null) {
            trustManager = createCallbackTrustManager(callback);
        }
        try {
            this.sslContext = SSLContext.getInstance("TLS");
            this.sslContext.init(null, new TrustManager[] { trustManager }, null);
        } catch (NoSuchAlgorithmException e) {
            LOG.warn("Could not install trust manager callback", e);
            this.sslContext = null;
        } catch (KeyManagementException e) {
            LOG.warn("Could not install trust manager callback", e);
            this.sslContext = null;
        }
    }

    // TODO REPLACE me with osjc impl
    private X509TrustManager createCallbackTrustManager(ISSLCertificateCallback sslAuthorizationCallback) {
        X509TrustManager trustManager = null;
        try {
            trustManager = getCurrentTrustManager();
            if (trustManager == null) {
                LOG.warn("Could not install trust manager callback, no trustmanager was found.");
            } else {
                trustManager = new CallbackTrustManager(trustManager, sslAuthorizationCallback);
            }
        } catch (GeneralSecurityException e) {
            LOG.warn("Could not install trust manager callback.", e);
        }
        return trustManager;
    }

    // TODO replace me with OSJC implementation
    private X509TrustManager getCurrentTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore) null);

        X509TrustManager x509TrustManager = null;
        for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
            if (trustManager instanceof X509TrustManager) {
                x509TrustManager = (X509TrustManager) trustManager;
                break;
            }
        }
        return x509TrustManager;
    }

    // TODO - Replace me with instance in OSJC
    private static class CallbackTrustManager implements X509TrustManager {

        private X509TrustManager trustManager;
        private ISSLCertificateCallback callback;

        private CallbackTrustManager(X509TrustManager currentTrustManager, ISSLCertificateCallback callback)
                throws NoSuchAlgorithmException, KeyStoreException {
            this.trustManager = currentTrustManager;
            this.callback = callback;
        }

        public X509Certificate[] getAcceptedIssuers() {
            return trustManager.getAcceptedIssuers();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            try {
                trustManager.checkServerTrusted(chain, authType);
            } catch (CertificateException e) {
                if (!callback.allowCertificate(chain)) {
                    throw e;
                }
            }
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            trustManager.checkServerTrusted(chain, authType);
        }
    }
}