{"record":{"id":"565d1eabcb27fdea","repo":"apereo/cas","slug":"provided-authentication-result-is-undefined-to-eva","errorCode":null,"errorMessage":"Provided authentication result is undefined to evaluate for mixed principals","messagePattern":"Provided authentication result is undefined to evaluate for mixed principals","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/cas-server-core/src/main/java/org/apereo/cas/DefaultCentralAuthenticationService.java","lineNumber":409,"sourceCode":"            .build();\n        enforceRegisteredServiceAccess(audit);\n    }\n\n    protected @Nullable Principal rebuildStatelessTicketPrincipal(final ServiceTicket serviceTicket) throws Throwable {\n        val authentication = serviceTicket.getAuthentication();\n        return configurationContext.getPrincipalResolver()\n            .resolve(new BasicIdentifiableCredential(\n                    Objects.requireNonNull(authentication).getPrincipal().getId()),\n                Optional.of(authentication.getPrincipal()), Optional.empty(),\n                Optional.of(serviceTicket.getService()));\n    }\n\n    private static @Nullable Authentication evaluatePossibilityOfMixedPrincipals(\n        @Nullable final AuthenticationResult context,\n        final TicketGrantingTicket ticketGrantingTicket) {\n        if (context == null) {\n            val error = \"Provided authentication result is undefined to evaluate for mixed principals\";\n            LOGGER.warn(error);\n            return null;\n        }\n        val currentAuthentication = context.getAuthentication();\n        if (currentAuthentication != null) {\n            val original = ticketGrantingTicket.getAuthentication();\n            if (!currentAuthentication.getPrincipal().equals(Objects.requireNonNull(original).getPrincipal())) {\n                throw new MixedPrincipalException(currentAuthentication,\n                    currentAuthentication.getPrincipal(), original.getPrincipal());\n            }\n        }\n        return currentAuthentication;\n    }\n\n    @RequiredArgsConstructor\n    private final class ServiceTicketGrantor implements CheckedSupplier<Ticket> {\n        private final String ticketGrantingTicketId;\n        private final Service service;\n        private final @Nullable AuthenticationResult authenticationResult;","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core/src/main/java/org/apereo/cas/DefaultCentralAuthenticationService.java#L391-L427","documentation":"evaluatePossibilityOfMixedPrincipals in DefaultCentralAuthenticationService warns and returns null when a null AuthenticationResult is supplied while comparing the TGT's principal with a new authentication result. It guards the mixed-principal detection during TGT re-establishment; null means the check could not be performed, so the caller treats it as 'no mixed principal detected'.","triggerScenarios":"Calling grantTicketGrantingTicket/evaluatePossibilityOfMixedPrincipals (via CentralAuthenticationService flows) with a null AuthenticationResult context alongside an existing TicketGrantingTicket — e.g. an SSO session refresh where no fresh authentication result was built.","commonSituations":"Custom authentication flows or protocol handlers (SAML/OIDC delegating flows) that re-use a TGT without producing a new AuthenticationResult; misconfigured service ticket grant flows that pass a null result after a failed authentication attempt.","solutions":["Ensure an AuthenticationResult is built and passed whenever a TGT is presented for re-evaluation","Check the authentication handler chain: a failed/aborted authentication produces a null result — fix the underlying authentication failure first","If the null result is intentional (pure SSO re-use), treat the warn as benign and confirm mixed-principal policy tolerates it","Review custom CentralAuthenticationService call sites for paths that skip authentication result creation"],"exampleFix":"// before\nacs.grantTicketGrantingTicket(tgtId, null);\n// after\nval result = authenticationResultBuilder.build(fixedCredentials, service);\nacs.grantTicketGrantingTicket(tgtId, result);","handlingStrategy":"validation","validationCode":"if (authenticationResult == null) {\n    throw new IllegalArgumentException(\"AuthenticationResult required when a TGT is presented\");\n}","typeGuard":"boolean canEvaluate = context != null && context.getAuthentication() != null && ticketGrantingTicket.getAuthentication() != null;","tryCatchPattern":null,"preventionTips":["Always build an AuthenticationResult before granting a TGT","Do not call grantServiceTicket/grantTicketGrantingTicket with null results on SSO re-use paths","Audit custom protocol handlers for null AuthenticationResult paths"],"tags":["authentication","principal","sso"],"backgroundTag":"null-argument","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"}