{"record":{"id":"970e1601f0c6fe05","repo":"apereo/cas","slug":"unable-to-grant-access-to-s","errorCode":null,"errorMessage":"Unable to grant access to %s","messagePattern":"Unable to grant access to (.+?)","errorType":"exception","errorClass":"InsufficientAuthenticationException","httpStatus":401,"severity":"error","filePath":"support/cas-server-support-palantir/src/main/java/org/apereo/cas/config/CasPalantirCasAuthenticationConfiguration.java","lineNumber":132,"sourceCode":"\n    @Bean\n    @ConditionalOnMissingBean(name = \"palantirUserDetailsService\")\n    public AuthenticationUserDetailsService palantirUserDetailsService(\n        final CasConfigurationProperties casProperties) {\n        return (AuthenticationUserDetailsService<CasAssertionAuthenticationToken>) token -> {\n            val assertion = token.getAssertion();\n            val attributes = assertion.getPrincipal().getAttributes();\n            val username = assertion.getPrincipal().getName();\n\n            val casAuthentication = casProperties.getPalantir().getCasAuthentication();\n            val requiredAttributeName = casAuthentication.getRequiredAttributeName();\n            val requiredAttributeValue = RegexUtils.createPattern(casAuthentication.getRequiredAttributeValue());\n\n            val requiredAttributeValues = CollectionUtils.toCollection(attributes.get(requiredAttributeName));\n            if (requiredAttributeValues.stream().noneMatch(value -> RegexUtils.find(requiredAttributeValue, value.toString()))) {\n                LOGGER.warn(\"Required attribute [{}] with value [{}] is not found in the CAS assertion for user [{}]\",\n                    requiredAttributeName, requiredAttributeValue.pattern(), username);\n                throw new InsufficientAuthenticationException(\"Unable to grant access to %s\".formatted(username));\n            }\n\n            val authorities = CollectionUtils.toCollection(attributes.get(\"role\"))\n                .stream()\n                .map(role -> Strings.CI.startsWith(role.toString(), \"ROLE_\") ? role.toString() : \"ROLE_\" + role)\n                .map(String::toUpperCase)\n                .map(SimpleGrantedAuthority::new)\n                .collect(Collectors.toList());\n            authorities.add(new SimpleGrantedAuthority(\"ROLE_USER\"));\n            return new User(username, \"N/A\", authorities);\n        };\n    }\n\n    @Bean\n    @ConditionalOnMissingBean(name = \"palantirTicketValidator\")\n    public TicketValidator palantirTicketValidator(\n        @Qualifier(WebApplicationService.BEAN_NAME_FACTORY)\n        final ServiceFactory<WebApplicationService> webApplicationServiceFactory,","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-palantir/src/main/java/org/apereo/cas/config/CasPalantirCasAuthenticationConfiguration.java#L114-L150","documentation":"Thrown by palantirUserDetailsService when the authenticated CAS assertion does not contain the configured required attribute with a value matching the configured regex (casAuthentication.requiredAttributeName / requiredAttributeValue). CAS Palantir support gates access on this attribute before granting authorities. If no attribute value matches, the user is rejected with an Spring Security InsufficientAuthenticationException and access is denied.","triggerScenarios":"A user logs in via the Palantir integration and the assertion's attribute named by cas.authn.palantir[0].required-attribute-name is missing, or none of its values matches the regex cas.authn.palantir[0].required-attribute-value.","commonSituations":"Attribute not released by the identity provider or attribute repository policy; wrong attribute name configured (case/scope mismatch like uid vs login); regex too strict (e.g. expecting an exact group name but attribute contains extra whitespace or different casing); attribute populated only for some users.","solutions":["Log the assertion attributes (the warn line prints the attribute name and pattern) and verify the attribute is actually present on the assertion; fix the attribute release/source if missing.","Correct cas.authn.palantir.required-attribute-name to the exact attribute key returned by the attribute repository.","Loosen or correct cas.authn.palantir.required-attribute-value regex (it is compiled with RegexUtils.createPattern, full Java regex semantics).","Test the regex against real attribute values using a Java regex tester before deploying."],"exampleFix":"// before\ncas.authn.palantir.required-attribute-name=memberOf\ncas.authn.palantir.required-attribute-value=^CN=palantir-users.*\n// after\ncas.authn.palantir.required-attribute-name=groups\ncas.authn.palantir.required-attribute-value=CN=palantir-users","handlingStrategy":"validation","validationCode":"// Verify the assertion carries the required attribute before login\nMap<String, Object> attrs = assertion.getAttributes();\nPattern p = Pattern.compile(requiredAttributeValue);\nboolean ok = attrs.getOrDefault(requiredAttributeName, List.of()).stream()\n    .anyMatch(v -> p.matcher(v.toString()).find());\nif (!ok) { throw new IllegalStateException(\"Missing required attribute \" + requiredAttributeName); }","typeGuard":null,"tryCatchPattern":"try { authManager.authenticate(token); } catch (InsufficientAuthenticationException e) { LOGGER.warn(\"Palantir access denied: {}\", e.getMessage()); throw new AccessDeniedException(\"access denied\"); }","preventionTips":["Confirm attribute release policies include the required attribute for all intended users.","Test required-attribute-value regexes against real production attribute values.","Log assertion attributes in a staging environment before tightening the filter."],"tags":["authentication","configuration","attributes","spring-security"],"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"}