AnsweredAssumed Answered

Access to OSISoft Web API across the internet with only kerberos authentication enabled

Question asked by ThierryD on Oct 14, 2017

Hello,

 

A customer using OSISoft gave me the address of a web site where I can browse their OSISoft web services:

http s://server.domain.com:port/piwebapi/dataservers

 

I was also given a username (user@domain.com) and password. Using these info and Chrome, I am able to browse the Web API without problems.

 

When I try to do the same thing from Java code, I get 401 errors.

 

When I go to http s://server.domain.com:port/piwebapi/system/configuration, it shows that only Kerberos is enabled.

 

This is the first part that confuses me. I thought Kerberos required a "domain controller in the middle" to work. I am able to access the web site through the internet without sharing a domain controller.

 

The second part that confuses me is what Chrome does exactly that my Java client doesn't.


What I really want is to access the Web API through Java. I use the apache http client libraries.

 

This is the code I tried (from code gathered in various sites):

 

            String protocol = properties.getProperty("protocol");

            String host = properties.getProperty("host");

            String port = properties.getProperty("port");

            String uri = protocol + "://" + host + ":" + port + "/" + "piwebapi/dataservers";

            HttpGet httpGet = new HttpGet(uri);

            String username = properties.getProperty("username");

            String password = properties.getProperty("password");

            HttpClient httpClient = getHttpClient(username, password); // see code below

            ArrayList<String> authPrefs = new ArrayList<>();

            authPrefs.add(AuthSchemes.KERBEROS); // I tried just about every AuthSchemes option here

            RequestConfig config = RequestConfig.custom().setTargetPreferredAuthSchemes(authPrefs).setProxyPreferredAuthSchemes(authPrefs).build();

            httpGet.setConfig(config);

            HttpResponse httpResponse = httpClient.execute(httpGet);

            String jsonString = EntityUtils.toString(httpResponse.getEntity());

 

public static CloseableHttpClient getHttpClient(String username, String password) {

        try {

            System.setProperty("java.security.auth.login.config", "login.conf");

            System.setProperty("java.security.krb5.conf", "krb5.conf");

            System.setProperty("sun.security.krb5.debug", "true");

            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

           

            Credentials credentials = new Credentials() {

                @Override

                public String getPassword() {

                    return password;

                }

                @Override

                public Principal getUserPrincipal() {

                    return new Principal() {

                        @Override

                        public String getName() {

                            return username;

                        }

                    };

                }

            };

 

 

            CredentialsProvider provider = new BasicCredentialsProvider();

            provider.setCredentials(new AuthScope(null, -1, null), credentials);

 

            // use the TrustSelfSignedStrategy to allow Self Signed Certificates

            SSLContext sslContext = SSLContextBuilder

                    .create()

                    .loadTrustMaterial(new TrustSelfSignedStrategy())

                    .build();

 

 

            // we can optionally disable hostname verification.

            // if you don't want to further weaken the security, you don't have to include this.

            HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

 

            // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy

            // and allow all hosts verifier.

            SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

 

            // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory

            return HttpClients

                    .custom()

                    .setSSLSocketFactory(connectionFactory)

                    .setDefaultCredentialsProvider(provider)

                    .build();

        } catch (Exception ex) {

            Logger.getLogger(HttpClientUtil.class.getName()).log(Level.SEVERE, null, ex);

            return null;

        }

    }

 

Help is appreciated !

Outcomes