Skip to content

Commit 4b84f87

Browse files
chalasrnicolas-grekas
authored andcommitted
[Security] Deprecate UserInterface & TokenInterface's eraseCredentials()
1 parent 8e83a64 commit 4b84f87

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Deprecate `LdapUser::eraseCredentials()`, use `LdapUser::setPassword(null)` instead
8+
* Add `EraseLdapUserCredentialsListener`
9+
410
7.2
511
---
612

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Security;
13+
14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16+
use Symfony\Component\Ldap\Exception\InvalidCredentialsException;
17+
use Symfony\Component\Ldap\Exception\InvalidSearchCredentialsException;
18+
use Symfony\Component\Ldap\LdapInterface;
19+
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
20+
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
21+
use Symfony\Component\Security\Core\Exception\LogicException;
22+
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
23+
use Symfony\Component\Security\Http\Event\AuthenticationTokenCreatedEvent;
24+
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
25+
26+
/**
27+
* Erases credentials from LdapUser instances upon successful authentication.
28+
*
29+
* @author Robin Chalas <robin.chalas@gmail.com>
30+
*/
31+
class EraseLdapUserCredentialsListener implements EventSubscriberInterface
32+
{
33+
public function onAuthenticationSuccess(AuthenticationSuccessEvent $event): void
34+
{
35+
$user = $event->getAuthenticationToken()->getUser();
36+
37+
if (!$user instanceof LdapUser) {
38+
return;
39+
}
40+
41+
$user->setPassword(null);
42+
}
43+
44+
public static function getSubscribedEvents(): array
45+
{
46+
return [AuthenticationSuccessEvent::class => ['onAuthenticationSuccess', 256]];
47+
}
48+
}

Security/LdapUser.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public function getUserIdentifier(): string
6262

6363
public function eraseCredentials(): void
6464
{
65+
trigger_deprecation('symfony/security-core', '7.3', sprintf('The "%s()" method is deprecated and will be removed in 8.0, call "setPassword(null)" instead.', __METHOD__));
66+
6567
$this->password = null;
6668
}
6769

@@ -70,7 +72,7 @@ public function getExtraFields(): array
7072
return $this->extraFields;
7173
}
7274

73-
public function setPassword(#[\SensitiveParameter] string $password): void
75+
public function setPassword(#[\SensitiveParameter] ?string $password): void
7476
{
7577
$this->password = $password;
7678
}
@@ -95,4 +97,14 @@ public function isEqualTo(UserInterface $user): bool
9597

9698
return true;
9799
}
100+
101+
public function __serialize(): array
102+
{
103+
return [$this->entry, $this->identifier, null, $this->roles, $this->extraFields];
104+
}
105+
106+
public function __unserialize(array $data): void
107+
{
108+
[$this->entry, $this->identifier, $this->password, $this->roles, $this->extraFields] = $data;
109+
}
98110
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Ldap\Tests\Security;
13+
14+
use PHPUnit\Framework\MockObject\MockObject;
15+
use PHPUnit\Framework\TestCase;
16+
use Psr\Container\ContainerInterface;
17+
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpFoundation\Response;
19+
use Symfony\Component\Ldap\Adapter\CollectionInterface;
20+
use Symfony\Component\Ldap\Adapter\QueryInterface;
21+
use Symfony\Component\Ldap\Entry;
22+
use Symfony\Component\Ldap\Exception\InvalidCredentialsException;
23+
use Symfony\Component\Ldap\LdapInterface;
24+
use Symfony\Component\Ldap\Security\CheckLdapCredentialsListener;
25+
use Symfony\Component\Ldap\Security\EraseLdapUserCredentialsListener;
26+
use Symfony\Component\Ldap\Security\LdapBadge;
27+
use Symfony\Component\Ldap\Security\LdapUser;
28+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
29+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
30+
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
31+
use Symfony\Component\Security\Core\Exception\AuthenticationException;
32+
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
33+
use Symfony\Component\Security\Core\User\InMemoryUser;
34+
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
35+
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
36+
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
37+
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
38+
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
39+
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
40+
use Symfony\Contracts\Service\ServiceLocatorTrait;
41+
42+
class EraseLdapUserCredentialsListenerTest extends TestCase
43+
{
44+
public function testPasswordIsErasedOnAuthenticationSuccess()
45+
{
46+
$user = new LdapUser(new Entry(''), 'chalasr', 'password');
47+
$listener = new EraseLdapUserCredentialsListener();
48+
49+
$listener->onAuthenticationSuccess(new AuthenticationSuccessEvent(new UsernamePasswordToken($user, 'main')));
50+
51+
$this->assertSame(null, $user->getPassword());
52+
}
53+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"require": {
1919
"php": ">=8.2",
2020
"ext-ldap": "*",
21+
"symfony/deprecation-contracts": "^2.5|^3",
2122
"symfony/options-resolver": "^6.4|^7.0"
2223
},
2324
"require-dev": {

0 commit comments

Comments
 (0)