apereo/cas · error · InsufficientAuthenticationException

Unable to grant access to

Error message

Unable to grant access to %s

What it means

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.

Solutions

  1. 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.
  2. Correct cas.authn.palantir.required-attribute-name to the exact attribute key returned by the attribute repository.
  3. Loosen or correct cas.authn.palantir.required-attribute-value regex (it is compiled with RegexUtils.createPattern, full Java regex semantics).
  4. Test the regex against real attribute values using a Java regex tester before deploying.

Example fix

// before
cas.authn.palantir.required-attribute-name=memberOf
cas.authn.palantir.required-attribute-value=^CN=palantir-users.*
// after
cas.authn.palantir.required-attribute-name=groups
cas.authn.palantir.required-attribute-value=CN=palantir-users
Defensive patterns

Strategy: validation

Validate before calling

// Verify the assertion carries the required attribute before login
Map<String, Object> attrs = assertion.getAttributes();
Pattern p = Pattern.compile(requiredAttributeValue);
boolean ok = attrs.getOrDefault(requiredAttributeName, List.of()).stream()
    .anyMatch(v -> p.matcher(v.toString()).find());
if (!ok) { throw new IllegalStateException("Missing required attribute " + requiredAttributeName); }

Try / catch

try { authManager.authenticate(token); } catch (InsufficientAuthenticationException e) { LOGGER.warn("Palantir access denied: {}", e.getMessage()); throw new AccessDeniedException("access denied"); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/970e1601f0c6fe05. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-palantir/src/main/java/org/apereo/cas/config/CasPalantirCasAuthenticationConfiguration.java:132

    @Bean
    @ConditionalOnMissingBean(name = "palantirUserDetailsService")
    public AuthenticationUserDetailsService palantirUserDetailsService(
        final CasConfigurationProperties casProperties) {
        return (AuthenticationUserDetailsService<CasAssertionAuthenticationToken>) token -> {
            val assertion = token.getAssertion();
            val attributes = assertion.getPrincipal().getAttributes();
            val username = assertion.getPrincipal().getName();

            val casAuthentication = casProperties.getPalantir().getCasAuthentication();
            val requiredAttributeName = casAuthentication.getRequiredAttributeName();
            val requiredAttributeValue = RegexUtils.createPattern(casAuthentication.getRequiredAttributeValue());

            val requiredAttributeValues = CollectionUtils.toCollection(attributes.get(requiredAttributeName));
            if (requiredAttributeValues.stream().noneMatch(value -> RegexUtils.find(requiredAttributeValue, value.toString()))) {
                LOGGER.warn("Required attribute [{}] with value [{}] is not found in the CAS assertion for user [{}]",
                    requiredAttributeName, requiredAttributeValue.pattern(), username);
                throw new InsufficientAuthenticationException("Unable to grant access to %s".formatted(username));
            }

            val authorities = CollectionUtils.toCollection(attributes.get("role"))
                .stream()
                .map(role -> Strings.CI.startsWith(role.toString(), "ROLE_") ? role.toString() : "ROLE_" + role)
                .map(String::toUpperCase)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new User(username, "N/A", authorities);
        };
    }

    @Bean
    @ConditionalOnMissingBean(name = "palantirTicketValidator")
    public TicketValidator palantirTicketValidator(
        @Qualifier(WebApplicationService.BEAN_NAME_FACTORY)
        final ServiceFactory<WebApplicationService> webApplicationServiceFactory,

View on GitHub (pinned to e7288fc434)