{"record":{"id":"2f692a8de4a25044","repo":"apereo/cas","slug":"duo-security-authentication-has-failed","errorCode":null,"errorMessage":"Duo Security authentication has failed","messagePattern":"Duo Security authentication has failed","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-duo-core/src/main/java/org/apereo/cas/adaptors/duo/authn/DuoSecurityAuthenticationHandler.java","lineNumber":142,"sourceCode":"        } catch (final Throwable e) {\n            LoggingUtils.error(LOGGER, e);\n        }\n        throw new FailedLoginException(\"Duo Security universal prompt authentication has failed\");\n    }\n\n    private AuthenticationHandlerExecutionResult authenticateDuoApiCredential(\n        final DuoSecurityDirectCredential credential) throws FailedLoginException {\n        try {\n            val duoAuthenticationService = multifactorAuthenticationProvider.getObject().getDuoAuthenticationService();\n            if (duoAuthenticationService.authenticate(credential).isSuccess()) {\n                val principal = resolvePrincipal(credential.getPrincipal());\n                LOGGER.debug(\"Duo Security has successfully authenticated [{}]\", principal.getId());\n                return createHandlerResult(credential, principal, new ArrayList<>());\n            }\n        } catch (final Exception e) {\n            LoggingUtils.error(LOGGER, e);\n        }\n        throw new FailedLoginException(\"Duo Security authentication has failed\");\n    }\n}\n","sourceCodeStart":124,"sourceCodeEnd":145,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-duo-core/src/main/java/org/apereo/cas/adaptors/duo/authn/DuoSecurityAuthenticationHandler.java#L124-L145","documentation":"Duo Security's Authentication API rejected the authentication attempt or the API call failed. DuoSecurityAuthenticationHandler.authenticateDuoApiCredential catches all exceptions (logging them) and then unconditionally throws FailedLoginException, so any Duo API/network/config failure surfaces as this generic failure message. It means CAS could not produce a successful Duo authentication result for the credential.","triggerScenarios":"doAuthentication calls the Duo auth API and either the signed response cannot be verified, the Duo service returns an error (invalid integration key/secret, expired license, blocked user), the network call fails/times out, or the returned payload yields no principal — the catch block swallows the cause and rethrows this FailedLoginException.","commonSituations":"Wrong duoIntegrationKey/secretKey/apiHostname in cas.authn.duo properties; Duo Admin Console not registering the CAS host; firewall/proxy blocking outbound HTTPS to api-*.duosecurity.com; clock skew breaking signed response validation; user not enrolled in Duo.","solutions":["Check the server log just above the exception: LoggingUtils.error(LOGGER, e) records the real root cause (network, signature, or API error) and fix that first","Verify cas.authn.duo.[name].duoIntegrationKey, secretKey and apiHostname match the Duo Admin Console protection values","Confirm the CAS server can reach https://<api-host>.duosecurity.com (curl test; check proxies/firewalls/TLS trust)","Ensure the user is enrolled in the Duo application and the account is not locked/bypass-expired"],"exampleFix":"// before (properties)\ncas.authn.duo.duo-api-host=api-wrong-host.duosecurity.com\n// after\ncas.authn.duo.duo-api-host=api-XXXXXXXX.duosecurity.com","handlingStrategy":"try-catch","validationCode":"// before calling authentication, verify config\nif (duoProps.getApiHostname() == null || duoProps.getSecretKey() == null || duoProps.getDuoIntegrationKey() == null)\n    throw new IllegalStateException(\"Duo integration keys/apiHostname must be configured\");","typeGuard":null,"tryCatchPattern":"try {\n    handlerResult = doAuthentication(credential);\n} catch (FailedLoginException e) {\n    LOGGER.error(\"Duo auth failed; inspect earlier LoggingUtils stack trace for root cause\", e);\n    return redirectToDuoErrorScreen(e);\n}","preventionTips":["Log/inspect the swallowed root-cause exception logged by LoggingUtils before this error","Test outbound HTTPS to the Duo API host from the CAS server during deployment","Keep Duo Admin Console integration values and CAS properties in sync","Enroll test users before rollout to catch enrollment issues early"],"tags":["duo","mfa","authentication"],"backgroundTag":"api-error-response","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"}