Unable to authenticate Kusto Client using JWTToken

75 Views Asked by At

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?

2

There are 2 best solutions below

0
Ohad Bitton On BEST ANSWER

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().

0
Yochai Gilad On

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