spring-projects/spring-security · error · BadCredentialsException

Kerberos authentication failed

Error message

Kerberos authentication failed

What it means

KerberosMultiTier.runAuthentication performs the GSS-API context establishment loop and wraps ANY exception occurring there (GSSException, IO problems, malformed tokens) in a BadCredentialsException with this message. It means the multi-tier Kerberos handshake failed.

Solutions

  1. Inspect the cause exception carried by the BadCredentialsException for the GSS-level reason.
  2. Verify the target service principal name matches the SPN registered in the KDC (setspn -L).
  3. Check clock skew (max 5 minutes) and that credentials/keytab are valid and not expired with klist/kinit.
  4. Confirm krb5.conf has the correct realm and KDC addresses.
  5. Ensure both peers use compatible mechanisms (Kerberos V5 Oid).

Example fix

// before
multiTier.authenticate(token, "HTTP/wrong-spn.example.com");
// after
multiTier.authenticate(token, "HTTP/service.example.com@EXAMPLE.COM");
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-checks before handshake
Files.exists(Path.of(keytab));
if (Math.abs(System.currentTimeMillis() - kdcTimeOffsetMs) > 300_000) LOG.warn("clock skew high");

Try / catch

try {
  multiTier.establish(...);
} catch (BadCredentialsException e) {
  Throwable root = e.getCause(); // GSSException with real reason
  LOG.error("Kerberos handshake failed: {}", root == null ? null : root.getMessage(), root);
  throw new AuthenticationServiceException("Kerberos handshake failed", root);
}

Prevention

When it happens

Trigger: runAuthentication catching any Exception while establishing the GSS security context: invalid/mismatched SPN (targetService), expired credentials/keytab, kerberos ticket rejection, or I/O failure exchanging tokens with the peer.

Common situations: Wrong targetServicePrincipalName (SPN not registered in KDC), clock skew between client and KDC, expired TGT, or krb5.conf pointing at the wrong realm/KDC.

Understand the failure class

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/2bebdea4d362ad92. Report an issue: GitHub.

Appendix: source

Thrown at kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/KerberosMultiTier.java:117

			securityContext.requestMutualAuth(false);
			securityContext.requestReplayDet(false);
			securityContext.requestSequenceDet(false);

			boolean established = false;

			byte[] outToken = new byte[0];

			while (!established) {
				byte[] inToken = new byte[0];
				outToken = securityContext.initSecContext(inToken, 0, inToken.length);

				established = securityContext.isEstablished();
			}

			jaasContext.addToken(targetService, outToken);
		}
		catch (Exception ex) {
			throw new BadCredentialsException("Kerberos authentication failed", ex);
		}
	}

	private static Oid createOid(String oid) {
		try {
			return new Oid(oid);
		}
		catch (GSSException ex) {
			throw new IllegalStateException("Unable to instantiate Oid: ", ex);
		}
	}

	private KerberosMultiTier() {
	}

}

View on GitHub (pinned to 96852e8860)