{"record":{"id":"bb29bd3a0129641b","repo":"apolloconfig/apollo","slug":"user-username-not-found-in-directory","errorCode":null,"errorMessage":"User {username} not found in directory.","messagePattern":"User (.+?) not found in directory\\.","errorType":"exception","errorClass":"UsernameNotFoundException","httpStatus":null,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ldap/FilterLdapByGroupUserSearch.java","lineNumber":93,"sourceCode":"  @Override\n  public DirContextOperations searchForUser(String username) {\n    if (logger.isDebugEnabled()) {\n      logger.debug(\"Searching for user '{}', with user search {}\", username, this);\n    }\n    SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(this.contextSource);\n    template.setSearchControls(searchControls);\n    return template.searchForObject(groupBase, groupSearch, ctx -> {\n      if (!MEMBER_UID_ATTR_NAME.equals(groupMembershipAttrName)) {\n        String[] members = ((DirContextAdapter) ctx).getStringAttributes(groupMembershipAttrName);\n        for (String item : members) {\n          LdapName memberDn = LdapUtils.newLdapName(item);\n          LdapName memberRdn = LdapUtils.removeFirst(memberDn, LdapUtils.newLdapName(searchBase));\n          String rdnValue = LdapUtils.getValue(memberRdn, rdnKey).toString();\n          if (rdnValue.equalsIgnoreCase(username)) {\n            return new DirContextAdapter(memberRdn.toString());\n          }\n        }\n        throw new UsernameNotFoundException(\"User \" + username + \" not found in directory.\");\n      }\n      String[] memberUids = ((DirContextAdapter) ctx).getStringAttributes(groupMembershipAttrName);\n      for (String memberUid : memberUids) {\n        if (memberUid.equalsIgnoreCase(username)) {\n          Name name = searchUserById(memberUid);\n          LdapName ldapName = LdapUtils.newLdapName(name);\n          LdapName ldapRdn = LdapUtils.removeFirst(ldapName, LdapUtils.newLdapName(searchBase));\n          return new DirContextAdapter(ldapRdn);\n        }\n      }\n      throw new UsernameNotFoundException(\"User \" + username + \" not found in directory.\");\n    });\n  }\n}\n","sourceCodeStart":75,"sourceCodeEnd":108,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/ldap/FilterLdapByGroupUserSearch.java#L75-L108","documentation":"Thrown by FilterLdapByGroupUserSearch.searchForUser() at line 93 when the LDAP group membership attribute is NOT 'memberUid' (i.e., DN-based membership like 'member'), and after iterating all member DNs from the group, none has an RDN value matching the supplied username. This means the user exists in LDAP but is not a member of the configured group. UsernameNotFoundException propagates up and Spring Security typically wraps it into a BadCredentialsException.","triggerScenarios":"A user authenticates via LDAP group-filtered search where groupMembershipAttrName is DN-based (e.g., 'member'). The LDAP group object is found and its members enumerated, but the username doesn't match any member DN's RDN value (extracted via rdnKey). Common when the user is not in the authorized Apollo access group.","commonSituations":"User was removed from the LDAP/AD group that grants Apollo access but still has an LDAP account. The rdnKey or groupMembershipAttrName configuration doesn't match the actual LDAP schema. The user's DN structure doesn't match the expected searchBase for RDN extraction.","solutions":["Add the user to the LDAP group configured as the Apollo access group.","Verify the LDAP configuration: groupMembershipAttrName, rdnKey, and searchBase match your directory schema.","Check that LdapUtils.removeFirst(memberDn, searchBase) correctly produces a relative DN whose rdnKey value matches the login username."],"exampleFix":"// Not a code fix — add the user to the configured LDAP group in your directory service (e.g., Active Directory or OpenLDAP).","handlingStrategy":"try-catch","validationCode":"// LDAP group membership cannot be validated client-side; verify directory config instead.\n// Ensure groupMembershipAttrName and rdnKey match your LDAP schema before deploying.","typeGuard":null,"tryCatchPattern":"try {\n    authenticationManager.authenticate(\n        new UsernamePasswordAuthenticationToken(username, password));\n} catch (AuthenticationException e) {\n    Throwable cause = e;\n    while (cause != null) {\n        if (cause instanceof UsernameNotFoundException\n                && cause.getMessage().contains(\"not found in directory\")) {\n            return ResponseEntity.status(401).body(\"User is not a member of the authorized LDAP group\");\n        }\n        cause = cause.getCause();\n    }\n    throw e;\n}","preventionTips":["Ensure users are added to the configured LDAP access group before they attempt login.","Verify groupMembershipAttrName, rdnKey, and searchBase match your directory schema.","Log UsernameNotFoundException separately to distinguish 'not in group' from 'bad credentials'."],"tags":["apollo-portal","ldap","authentication","group-membership","username-not-found"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}