0

We use Java 8 and msal4j version 0.6.0-preview. To connect to Kusto, we use JWT Token:

ConnectionStringBuilder csb = ConnectionStringBuilder.createWithAadAccessTokenAuthentication(resourceUri, accessToken);
Client kustoClient = ClientFactory.createClient(csb);

Inside thencreateWithAadAccessTokenAuthentication(), it is calling this ConnectionStringBuilder constructor:

public static ConnectionStringBuilder createWithAadAccessTokenAuthentication(String resourceUri, String token) {
        if (StringUtils.isEmpty(resourceUri)) {
            throw new IllegalArgumentException("resourceUri cannot be null or empty");
        } else if (StringUtils.isEmpty(token)) {
            throw new IllegalArgumentException("token cannot be null or empty");
        } else {
            ConnectionStringBuilder csb = new ConnectionStringBuilder(resourceUri);
            csb.accessToken = token;
            return csb;
        }
    }

it is setting every field to null except for clusterUri.

private ConnectionStringBuilder(String resourceUri) {
        this.clusterUri = resourceUri;
        this.usernameHint = null;
        this.applicationClientId = null;
        this.applicationKey = null;
        this.aadAuthorityId = null;
        this.x509Certificate = null;
        this.privateKey = null;
        this.accessToken = null;
        this.tokenProvider = null;
    }

Thus we got an error from createClient() method. Because it is calling ClientImpl(csb). host and auth are returning null, which triggers null pointer exception in this line: String auth = clusterUri.getAuthority().toLowerCase();

public static Client createClient(ConnectionStringBuilder csb) throws URISyntaxException {
        return new ClientImpl(csb);
    }

 public ClientImpl(ConnectionStringBuilder csb) throws URISyntaxException {
        String url = csb.getClusterUrl();
        URI clusterUri = new URI(url);
        String host = clusterUri.getHost();
        String auth = clusterUri.getAuthority().toLowerCase();
        if (host == null && auth.endsWith(";fed=true")) {
            url = (new URIBuilder()).setScheme(clusterUri.getScheme()).setHost(auth.substring(0, clusterUri.getAuthority().indexOf(";fed=true"))).toString();
            csb.setClusterUrl(url);
        }

        this.clusterUrl = url;
        this.aadAuthenticationHelper = TokenProviderFactory.createTokenProvider(csb);
        this.clientVersionForTracing = "Kusto.Java.Client";
        String version = Utils.getPackageVersion();
        if (StringUtils.isNotBlank(version)) {
            this.clientVersionForTracing = this.clientVersionForTracing + ":" + version;
        }

        if (StringUtils.isNotBlank(csb.getClientVersionForTracing())) {
            this.clientVersionForTracing = this.clientVersionForTracing + "[" + csb.getClientVersionForTracing() + "]";
        }

        this.applicationNameForTracing = csb.getApplicationNameForTracing();
    }

What are the other alternatives here?

superninja
  • 3,114
  • 7
  • 30
  • 63
  • 1. What version of the SDK are you using? "resourceUri"'s param name was changed in 2021 2. I don't see the problem with the flow. You provided a resource url in the ctor, why would "host" and "auth" return null? What did you give to the original ConnectionStringBuilder? – user3459685 Jun 13 '23 at 13:25

2 Answers2

1

Which version of the Kusto SDK are you using? Can you use any of the other AuthN options provided by the SDK itself, instead of acquiring the token manually and passing it's value to the SDK? It's generally more recommanded (less prone to long running errors due to token expiration)

P.S. It common to report such issues in the repo for the source code. :) https://github.com/Azure/azure-kusto-java/issues

1

After talking F2F we found the issue is with the value passed in the resourceUri param, while this expects a url of the cluster ("https://cluster.region.kusto.windows.net") the provided uri was the ARM resource uri hence no host and no auth sections of the URL were parsed by the call to new URI().

Ohad Bitton
  • 460
  • 2
  • 14