{"record":{"id":"bb9529ed67ca092f","repo":"apereo/cas","slug":"base-dn-cannot-be-empty-blank-for-authenticated-an","errorCode":null,"errorMessage":"Base dn cannot be empty/blank for authenticated/anonymous authentication","messagePattern":"Base dn cannot be empty/blank for authenticated/anonymous authentication","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java","lineNumber":785,"sourceCode":"                    searchResultHandlers.add(\n                        new RecursiveResultHandler(recursive.getSearchAttribute(),\n                            recursive.getMergeAttributes().toArray(ArrayUtils.EMPTY_STRING_ARRAY)));\n                }\n                default -> searchResultHandlers.add(new MergeResultHandler());\n            }\n        });\n        return searchResultHandlers;\n    }\n\n    /**\n     * Gets authenticated authenticator.\n     *\n     * @param properties the lDAP properties\n     * @return the authenticated or anon search authenticator\n     */\n    public static Authenticator getAuthenticatedOrAnonSearchAuthenticator(final AbstractLdapAuthenticationProperties properties) {\n        if (StringUtils.isBlank(properties.getBaseDn())) {\n            throw new IllegalArgumentException(\"Base dn cannot be empty/blank for authenticated/anonymous authentication\");\n        }\n        if (StringUtils.isBlank(properties.getSearchFilter())) {\n            throw new IllegalArgumentException(\"User filter cannot be empty/blank for authenticated/anonymous authentication\");\n        }\n        val connectionFactory = newLdaptiveConnectionFactory(properties);\n        val resolver = buildAggregateDnResolver(properties, connectionFactory);\n\n        val auth = StringUtils.isBlank(properties.getPrincipalAttributePassword())\n            ? new Authenticator(resolver, getBindAuthenticationHandler(connectionFactory))\n            : new Authenticator(resolver, getCompareAuthenticationHandler(properties, connectionFactory));\n\n        if (properties.isEnhanceWithEntryResolver()) {\n            auth.setEntryResolver(newLdaptiveSearchEntryResolver(properties, connectionFactory));\n        }\n        return auth;\n    }\n\n    private static Authenticator getDnFormatAuthenticator(final AbstractLdapAuthenticationProperties properties) {","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java#L767-L803","documentation":"getAuthenticatedOrAnonSearchAuthenticator builds a search-then-bind Authenticator that must know where to look up users. It rejects a blank baseDn with IllegalArgumentException because neither authenticated nor anonymous search can proceed without a search base.","triggerScenarios":"Configuring an LDAP authentication type that resolves to authenticated/anonymous search (e.g. AUTHENTICATED, ANONYMOUS search types) while cas.authn.ldap[x].base-dn is unset or empty, then newLdaptiveAuthenticator is invoked.","commonSituations":"YAML block created from a template with base-dn left blank; direct-bind-style config reused for search-and-bind; property indentation wrong so base-dn lands in the wrong block; programmatic property construction skipping setBaseDn.","solutions":["Set cas.authn.ldap[x].base-dn to the subtree containing user entries (e.g. ou=people,dc=example,dc=org)","Verify YAML indentation/nesting so base-dn is inside the same ldap[x] block","If you intend direct bind (DN pattern) instead, switch the bind/authentication type so this path is not taken"],"exampleFix":"// before\ncas.authn.ldap[0].base-dn=\n// after\ncas.authn.ldap[0].base-dn=ou=people,dc=example,dc=org","handlingStrategy":"validation","validationCode":"if (props.getBaseDn() == null || props.getBaseDn().isBlank()) {\n    throw new IllegalStateException(\"base-dn is required for authenticated/anonymous LDAP search\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    Authenticator a = LdapUtils.newLdaptiveAuthenticator(props);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Base dn cannot be empty/blank\")) {\n        // abort wiring and report the missing base-dn config\n    }\n}","preventionTips":["Never leave base-dn blank in search-and-bind configurations","Verify YAML nesting places base-dn inside the correct ldap[x] block","For DN-pattern direct bind, use the direct-bind type instead of search types","Validate the base DN with ldapsearch before rollout"],"tags":["ldap","configuration","validation"],"backgroundTag":"missing-required-config-field","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"}