{"record":{"id":"2bebdea4d362ad92","repo":"spring-projects/spring-security","slug":"kerberos-authentication-failed","errorCode":null,"errorMessage":"Kerberos authentication failed","messagePattern":"Kerberos authentication failed","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/KerberosMultiTier.java","lineNumber":117,"sourceCode":"\t\t\tsecurityContext.requestMutualAuth(false);\n\t\t\tsecurityContext.requestReplayDet(false);\n\t\t\tsecurityContext.requestSequenceDet(false);\n\n\t\t\tboolean established = false;\n\n\t\t\tbyte[] outToken = new byte[0];\n\n\t\t\twhile (!established) {\n\t\t\t\tbyte[] inToken = new byte[0];\n\t\t\t\toutToken = securityContext.initSecContext(inToken, 0, inToken.length);\n\n\t\t\t\testablished = securityContext.isEstablished();\n\t\t\t}\n\n\t\t\tjaasContext.addToken(targetService, outToken);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new BadCredentialsException(\"Kerberos authentication failed\", ex);\n\t\t}\n\t}\n\n\tprivate static Oid createOid(String oid) {\n\t\ttry {\n\t\t\treturn new Oid(oid);\n\t\t}\n\t\tcatch (GSSException ex) {\n\t\t\tthrow new IllegalStateException(\"Unable to instantiate Oid: \", ex);\n\t\t}\n\t}\n\n\tprivate KerberosMultiTier() {\n\t}\n\n}\n","sourceCodeStart":99,"sourceCodeEnd":134,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/KerberosMultiTier.java#L99-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"Wrong targetServicePrincipalName (SPN not registered in KDC), clock skew between client and KDC, expired TGT, or krb5.conf pointing at the wrong realm/KDC.","solutions":["Inspect the cause exception carried by the BadCredentialsException for the GSS-level reason.","Verify the target service principal name matches the SPN registered in the KDC (setspn -L).","Check clock skew (max 5 minutes) and that credentials/keytab are valid and not expired with klist/kinit.","Confirm krb5.conf has the correct realm and KDC addresses.","Ensure both peers use compatible mechanisms (Kerberos V5 Oid)."],"exampleFix":"// before\nmultiTier.authenticate(token, \"HTTP/wrong-spn.example.com\");\n// after\nmultiTier.authenticate(token, \"HTTP/service.example.com@EXAMPLE.COM\");","handlingStrategy":"try-catch","validationCode":"// pre-checks before handshake\nFiles.exists(Path.of(keytab));\nif (Math.abs(System.currentTimeMillis() - kdcTimeOffsetMs) > 300_000) LOG.warn(\"clock skew high\");","typeGuard":null,"tryCatchPattern":"try {\n  multiTier.establish(...);\n} catch (BadCredentialsException e) {\n  Throwable root = e.getCause(); // GSSException with real reason\n  LOG.error(\"Kerberos handshake failed: {}\", root == null ? null : root.getMessage(), root);\n  throw new AuthenticationServiceException(\"Kerberos handshake failed\", root);\n}","preventionTips":["Keep service principal names exact and registered in the KDC.","Monitor clock skew and refresh keytabs/TGTs before expiry.","Validate krb5.conf realm/KDC settings in CI-like environment checks."],"tags":["kerberos","gss-api","authentication-failed"],"backgroundTag":"kerberos-authentication-failed","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}