-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Ability to add roles in form_login_ldap
by ldap group
#51225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Combining and modifying some solution online: I came with this solution: <?php
namespace App\Security;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Ldap\Security\LdapUser;
use Symfony\Component\Ldap\Security\LdapUserProvider;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* LdapUserProvider is a simple user provider on top of LDAP.
* RolesLdapUserProvider handles the mapping of ldap groups to security roles.
*/
class RolesLdapUserProvider extends LdapUserProvider
{
public function __construct(LdapInterface $ldap,
string $baseDn,
string $searchDn = null,
#[\SensitiveParameter] string $searchPassword = null,
array $defaultRoles = [],
string $uidKey = null,
string $filter = null,
string $passwordAttribute = null,
array $extraFields = [],
// Key is the group name, value is the role name.
array $groupMapping = [],
// Extracts group name from dn string.
// You might want to change it to match your ldap server.
private string $groupNameRegExp = '/^CN=(?P<group>[^,]+),ou.*$/i',
) {
parent::__construct($ldap, $baseDn, $searchDn, $searchPassword, $defaultRoles, $uidKey, $filter, $passwordAttribute, $extraFields);
$this->groupMapping = array_change_key_case($groupMapping, CASE_LOWER);
}
/** Maps ldap groups to roles */
private array $groupMapping;
/**
* Loads a user from an LDAP entry.
*/
protected function loadUser(string $identifier, Entry $entry): UserInterface
{
$ldapUser = parent::loadUser($identifier, $entry);
if (!$ldapUser instanceof LdapUser) {
throw new \Exception(sprintf('Instances of "%s" are not supported.', \get_class($ldapUser)));
}
if (!$entry->hasAttribute('memberOf')) { // Check if the entry has attribute with the group
return new $ldapUser;
}
$roles = $ldapUser->getRoles();
foreach ($entry->getAttribute('memberOf') as $groupLine) { // Iterate through each group entry line
$groupName = strtolower($this->getGroupName($groupLine)); // Extract and normalize the group name from the line
if (array_key_exists($groupName, $this->groupMapping)) { // Check if the group is in the mapping
$roles[] = $this->groupMapping[$groupName]; // Map the group to the role the user will have
}
}
return new LdapUser($entry, $identifier, $ldapUser->getPassword(), $roles, $ldapUser->getExtraFields()); // Create and return the user object
}
/**
* Get the group name from the DN
*/
private function getGroupName(string $dn): string
{
$matches = [];
return preg_match($this->groupNameRegExp, $dn, $matches) ? $matches['group'] : '';
}
} services.yaml override "LdapUserProvider" with "RolesLdapUserProvider" and add the roles mapping services:
...
security.user.provider.ldap:
class: App\Security\RolesLdapUserProvider
arguments:
[
~,
~,
~,
~,
~,
~,
~,
~,
~,
{ 'LDAP-User': 'ROLE_USER', 'LDAP-Admin': 'ROLE_ADMIN' },
]
If needed I can make a PR so all you need to do is add the "roles:" as in @RTUnreal example. |
Hi, What about something we could call a security:
providers:
some_ldap:
ldap:
service: Symfony\Component\Ldap\Ldap
base_dn: cn=Users,dc=example,dc=com
search_dn: "cn=MyService,ou=Services,dc=example,dc=com"
search_password: '%env(resolve:LDAP_PW)%'
role_fetcher: my.custom.ldap.role.fetcher interface RoleFetcherInterface
{
/**
* return string[] A list of roles.
*/
public function fetchRoles(string $dn): array;
}
final class CustomRoleFetcher implements RoleFetcherInterface
{
/**
* return string[] A list of roles.
*/
public function fetchRoles(string $dn): array
{
// Do what you want with de parameter
if (...) {
return ['ROLE_ADMIN'];
}
// Return default role or an empty list depending on the security policy
return ['ROLE_USER'];
}
} |
Description
When a user logs in with a ldap dn, we need the ability to add roles by groups the user is a member of.
Example
Which would result in a user with the a
CN=Administrators,CN=Builtin,DC=example,DC=com
membership to be assigned theROLE_ADMIN
role.The text was updated successfully, but these errors were encountered: