{"record":{"id":"57f9b725b091900d","repo":"apereo/cas","slug":"ntlm-not-allowed","errorCode":null,"errorMessage":"NTLM not allowed","messagePattern":"NTLM not allowed","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-spnego/src/main/java/org/apereo/cas/support/spnego/authentication/handler/support/JcifsSpnegoAuthenticationHandler.java","lineNumber":51,"sourceCode":"public class JcifsSpnegoAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {\n\n    private final BlockingQueue<List<Authentication>> authenticationsPool;\n\n    private final SpnegoProperties spnegoProperties;\n\n    public JcifsSpnegoAuthenticationHandler(final SpnegoProperties spnegoProperties,\n                                            final PrincipalFactory principalFactory,\n                                            final BlockingQueue<List<Authentication>> authenticationsPool) {\n        super(spnegoProperties.getName(), principalFactory, spnegoProperties.getOrder());\n        this.spnegoProperties = spnegoProperties;\n        this.authenticationsPool = authenticationsPool;\n    }\n\n    @Override\n    protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws Throwable {\n        val spnegoCredential = (SpnegoCredential) credential;\n        if (!spnegoProperties.isNtlmAllowed() && spnegoCredential.isNtlm()) {\n            throw new FailedLoginException(\"NTLM not allowed\");\n        }\n\n        try {\n            LOGGER.debug(\"Waiting for connection to validate SPNEGO Token\");\n            val poolTimeoutInMilliseconds = Beans.newDuration(spnegoProperties.getPoolTimeout()).toMillis();\n            val authentications = authenticationsPool.poll(poolTimeoutInMilliseconds, TimeUnit.MILLISECONDS);\n            if (authentications != null) {\n                try {\n                    return doInternalAuthentication(authentications, spnegoCredential, service);\n                } finally {\n                    authenticationsPool.add(authentications);\n                    LOGGER.debug(\"Returned connection to pool\");\n                }\n            }\n            throw new FailedLoginException(\"Cannot get connection from pool to validate SPNEGO Token\");\n        } catch (final InterruptedException e) {\n            throw new FailedLoginException(\"Thread interrupted while waiting for connection to validate SPNEGO Token\");\n        }","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-spnego/src/main/java/org/apereo/cas/support/spnego/authentication/handler/support/JcifsSpnegoAuthenticationHandler.java#L33-L69","documentation":"JcifsSpnegoAuthenticationHandler validates SPNEGO/Kerberos tokens via JCIFS. When the incoming SPNEGO credential carries an NTLM token but spnegoProperties.isNtlmAllowed() is false, the handler immediately fails authentication with FailedLoginException because NTLM is a weaker protocol than Kerberos and is disabled by policy.","triggerScenarios":"A Windows client that is not domain-joined (or cannot reach the KDC) falls back to NTLM and sends an NTLM token (starting with 'NTLMSSP') while cas.authn.spnego.ntlmAllowed=false.","commonSituations":"Client machine off the corporate network/VPN so Kerberos fails and the browser downgrades to NTLM; browser not configured for integrated Windows auth against the CAS host; spnego/kerberos KDC unreachable causing NTLM fallback.","solutions":["Set cas.authn.spnego.ntlm-allowed=true if NTLM fallback is acceptable in your environment.","Fix client-side Kerberos: ensure the client is domain-joined, can reach the KDC, and SPNs for the CAS hostname are registered correctly.","Configure browsers to enable integrated Windows authentication for the CAS host so proper Kerberos tokens are sent.","Exclude the CAS host from IE/Chrome local-intranet exceptions that force NTLM."],"exampleFix":"// before\ncas.authn.spnego.ntlm-allowed=false\n// after (if NTLM fallback is acceptable)\ncas.authn.spnego.ntlm-allowed=true","handlingStrategy":"validation","validationCode":"// before enabling, verify clients can produce Kerberos tokens\n// on a Windows client: klist must show a TGT for the domain\nklist get krbtgt/CORP.LOCAL","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set ntlm-allowed=false deliberately and ensure all clients are domain-joined","Register SPNs for the CAS hostname so clients use Kerberos, not NTLM","Configure browsers' intranet/integrated-auth settings via GPO","Monitor failed logins with 'NTLM not allowed' to find downgrade-prone clients"],"tags":["spnego","kerberos","ntlm","authentication"],"backgroundTag":"authentication-required","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}