Hi,
I need to make a simple HTTP Post call by passing kerberos ticket (SPNEGO) authenticated to get the results from another system on AEM 6.5.21.
This is the snippet that I am using:
DefaultHttpClient httpclient = new DefaultHttpClient();
System.setProperty("java.security.krb5.conf", "C:/Windows/krb5.ini");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
NegotiateSchemeFactory nsf = new NegotiateSchemeFactory();
httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, nsf);
List<String> authpref = new ArrayList<>();
authpref.add(AuthPolicy.SPNEGO);
httpclient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref);
HttpPost request = new HttpPost("url");
HttpEntity entity = new StringEntity(jsonPayload, "UTF-8");
HttpResponse response = httpclient.execute(request);
I know that DefaultHttpClient is deprecated. (Planning to changing that once I get the success response)
I am not able to get the kerberos ticket, even after passing the krb5.ini file location. I have manually created the krb5.ini file with kbc and other required details in the specified location, but I get 401 unauthorized on trying to make the call.
Has anyone faced similar error. Anyone input will be helpful. Thank you.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
The DefaultHttpClient you're using is not only deprecated but may also have version-specific issues with SPNEGO: https://andriymz.github.io/kerberos/spnego-authentication-fails-to-https-service.
Your current implementation has potential issues:
Missing Credentials Provider: Your code sets up the NegotiateSchemeFactory but doesn't configure a credentials provider to supply the user credentials.
Incorrect Authentication Preference: You're setting PROXY_AUTH_PREF when you likely need AuthPNames.TARGET_AUTH_PREF for direct server authentication.
Request Entity Not Set: In your code snippet, you create a StringEntity but don't actually set it on the request.
Potential krb5.ini Issues: The content and format of your krb5.ini file might not be correctly configured for your Kerberos realm.
Updated version (AI generated):
// Import necessary classes
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.impl.auth.SPNegoSchemeFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.params.AuthPNames;
import org.apache.http.client.params.ClientPNames;
import java.util.ArrayList;
import java.util.List;
// Set Kerberos properties
System.setProperty("java.security.krb5.conf", "C:/Windows/krb5.ini");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
// Create and configure the HTTP client
DefaultHttpClient httpClient = new DefaultHttpClient();
// Create SPNEGO authentication scheme
SPNegoSchemeFactory spnegoSchemeFactory = new SPNegoSchemeFactory(true);
httpClient.getAuthSchemes().register("negotiate", spnegoSchemeFactory);
// Set authentication preference for target (not proxy)
List<String> authPrefs = new ArrayList<>();
authPrefs.add("negotiate");
httpClient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authPrefs);
// Enable automatic authentication
httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, true);
// Create and configure the request
HttpPost request = new HttpPost("https://your-target-server.com/api/endpoint");
request.setHeader("Content-Type", "application/json");
// Set the request entity
StringEntity entity = new StringEntity(jsonPayload, "UTF-8");
request.setEntity(entity);
// Execute the request
HttpResponse response = httpClient.execute(request);
// Process the response
int statusCode = response.getStatusLine().getStatusCode();
// Handle response accordingly
Check your krb5.ini file, it should contain at minimum:
[libdefaults]
default_realm = YOUR_REALM.COM
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
[realms]
YOUR_REALM.COM = {
kdc = kdc1.your_realm.com
kdc = kdc2.your_realm.com (if applicable)
admin_server = kdc1.your_realm.com
}
[domain_realm]
.your_domain.com = YOUR_REALM.COM
your_domain.com = YOUR_REALM.COM
Ensure that the target service has the appropriate SPN registered, typically in the format HTTP/fully.qualified.hostname@REALM2. For Windows-based servers, you can register SPNs using the setspn command:
setspn -A HTTP/fully.qualified.hostname.com DOMAIN\service_account
Before running your Java application, verify that you can manually obtain a Kerberos ticket:
kinit username@REALM
klist
Test the endpoint using cURL with Kerberos authentication to verify the server configuration:
curl -i --negotiate -u : -v https://your-target-server.com/api/endpoint
Analyze the debug output enabled by sun.security.krb5.debug=true for specific error messages about:
Failed credential acquisition
Incorrect Service Principal Name formats
KDC communication issues
For HTTPS connections, some environments require channel binding (extended protection). If your environment supports HTTPS with channel binding, you may need to explicitly enable or disable this feature depending on your server configuration.
Your HTTP 401 error is likely caused by one of several common Kerberos configuration issues. If problems persist after implementing these changes, focus on the debug output to identify specific authentication failures in the Kerberos negotiation process. The error messages in the Kerberos debug logs will typically point to configuration issues with either the client or server setup.
Views
Likes
Replies