Http Binding - Add SPNEGO Authentication (Kerberos - NTLM) to binding

Hello Community,

I started using the HTTP binding to get some date from API endpoints. I recognized that there are only some real basic authentication methods. This is what I want to change here.

I’m pretty new to java and this is my chance to dig into authentication topics.

However, I already added some code for SPNGO Authentication to my fork, but it’s not functioning. Github Fork - Feature SPNEGO Auth

I used this information for help: SPNEGOAuthenticationTest.java

The error message from the log which occurring is:

[WARN ] [tp.internal.http.HttpResponseListener] - Requesting ‘http ://cronus:7048/BC/ODataV4/Company(‘CRONUS%20International%20Ltd.’)/SalesOrder’ (method=‘GET’, content=‘null’) failed: java.lang.RuntimeException: javax.security.auth.login.LoginException: KrbException: Cannot locate default realm

With Postman, the request is working based on NTLM Auth.

Could anybody have a look and help me find my mistake.

I’m using a Business Central container on my local system for the Odata API endpoint. But I think it could be any other Endpoint based on a NTLM authentication.

Short PS script to create their own Windows container. (BcContainerHelper is required)

$containerName = 'cronus'
$credential = Get-Credential -Message 'Using Windows authentication. Please enter your Windows credentials for the host computer.'
$auth = 'Windows'
$artifactUrl = Get-BcArtifactUrl -type 'OnPrem' -version '20.2.0.0' -country 'w1' -select 'Closest'
$licenseFile = 'C:\BC-licence.flf'
New-BcContainer `
    -accept_eula `
    -containerName $containerName `
    -credential $credential `
    -auth $auth `
    -artifactUrl $artifactUrl `
    -licenseFile $licenseFile `
    -includeAL `
    -updateHosts


After container is ready

Enter-BcContainer cronus
Set-NAVServerConfiguration BC -KeyName ServicesUseNTLMAuthentication -KeyValue true
Restart-NAVServerInstance BC

This is one of those rare cases where I’ve had to move a post into the Development category. Hopefully the right people will be more likely to see it here.

1 Like

I checked this with wire shark, and it seems that the request is canceled after first Request. With Postman it needs 3 request to get a 200 as a result.

  1. Request the server answers how to negotiate. → 401 and WWW-Authenticate: NTLM
  2. Request to negotiate NTLM parameters → 401 and answers with parameters
  3. Request with NTLM User Data → Series of acknowledgements and an answer to the request (200)

I am not sure if the HttpResponseListener can deal with this procedure. But as I said, I am not an expert in this field.

I have implemented SPNEGO in Java apps before and it hurt.
You really want to use Active Directory/Kerberos, not NTLM. I think NTLM is deprecated.
You might want to look into https://www.keycloak.org/ as an Open ID Connect server.
It handles all of the gory details.
The Http binding would then need to implement an Open ID Connect client to authenticate with the keycloak server and your API endpoints would need to accept OAuth2 tokens or Kerberos tickets for authentication. afaik SPNEGO is a browser flow based protocol. This would not be an out of the box solution.

I needed to get kerberos tickets from active directory and I could not use SPNEGO, I had to dig into keycloak to see how it got a kerb ticket. It was not easy.

Depending on the who the Principle is, and whether you want to use the workstation login credentials without the user entering them, SPNEGO may not be the answer.

Since you are making a API call from OH, I don’t expect you are having a user in a browser running a web app. Are you going to embed credentials somewhere in OH? Then I would not pursue SPNEGO.

That’s not secure.

I reasonably sure it can’t.

Can your API server accept OAuth2 web tokens as an authentication credential? Kerberos ticket?

At the moment not, I found an MS documentation that there is a possibility in my case, but it also needs a specific environment and also needs to be rolled out in the enterprise solution.

I found a solution to use an OAuth V2 token to get data from an API which required this method. This is already possible! Fill in the Header field the Authentication part like:

Authorization=<TokenType> <Token>
eg: “Authorization= Bearer ya29.a0Ael9sCN3qrUqzfa_gyv…”

Could also be added in the documentation as an example.

I turned this into a coded solution. I don’t like to get the log entry that no authentication is used (because there is no option for it).
Here you have my branch and can view my changes OAuthV2. Documentation will be added if solution is okay and a PR needs to be created.

But anyway, with the solution, it is still not possible to do an authentication based on (SPNEGO Kerberos NTLM). Not all Systems and created endpoints are based on the OAuth.

I was also analyzing further in this topic, but I also did not find a proper solution.

You are completely right with embed storing credentials in OH is not really nice way. At The moment, everything is saved in clear text in the config file. A general external credential store is missing, but this is another topic for another thread.

The question is if it’s possible to provide the request and the credential storage with the necessary information step by step. I haven’t found a good example where and how the Jetty.SPNEGO library is used. I am aware that the negotiation process is quite complex.

Furthermore, I am not experienced enough to say if it is possible to integrate this at all. If the answer is yes, then I need a concept on which points in the process what have to be added. I would like to provide it. If the answer is no. Then we can only need to check the OAuth Part and close this topic.