This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
Go to file
Fabien Potencier 2248639fb3 feature #37846 [Security] Lazily load the user during the check passport event (wouterj)
This PR was merged into the 5.2-dev branch.

Discussion
----------

[Security] Lazily load the user during the check passport event

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | yes
| Tickets       | Fix #37436
| License       | MIT
| Doc PR        | tbd

**Before**
```php
class ApiKeyAuthenticator extends AbstractAuthenticator
{
    // ...

    public function authenticate(Request $request): PassportInterface
    {
        $email = $request->headers->get('X-USER-EMAIL');
        if (false === strpos($email, '@')) {
            throw new BadCredentialsException('Email is not a valid email address.');
        }

        $user = $this->userRepository->findOneBy(['email' => $email]);
        if (null === $user) {
            throw new UsernameNotFoundException();
        }

        return new SelfValidatingPassport($user);
    }
}
```

**After**
```php
class ApiKeyAuthenticator extends AbstractAuthenticator
{
    // ...

    public function authenticate(Request $request): PassportInterface
    {
        $email = $request->headers->get('X-USER-EMAIL');
        if (false === strpos($email, '@')) {
            throw new BadCredentialsException('Email is not a valid email address.');
        }

        // a global ChainUserProvider (or firewall provider if explicitly configured) will be
        // used to load the User with $email as username
        return new SelfValidatingPassport($email);

        // or a custom closure to load the user
        return new SelfValidatingPassport(new UserBadge($email, function ($username) {
            return $this->userRepository->findOneBy(['email' => $username]);
        });
    }
}
```

Doing it this way has a couple advantages (some of which are already mentioned in the issue):

* Some listeners on `CheckPassportEvent` need to execute *before* loading the user - to reduce resources (e.g. CSRF protection, if CSRF fails, no DB call should be made to load user - and also login throttling);
* Some listeners require knowing the username of the login action (e.g. login throttling on IP and username);
* The `UserProviderListener` allows to remove yet another centralized action in the authentication process from the authenticator class to the Symfony framework.

Automatic User Provider integration
---

Instead of passing the credentials and a closure to `UserBadge`, you can also just pass a (string) username. The user provider will then be used to load the user. This only works for `custom_authenticators` as of this moment.

* By default, a chain user provider with all configured `user_providers` will be used as the user provider;
* However, if you explicitly configure a `provider` for that firewall, that provider will be used (using a listener with higher priority).

Commits
-------

907ef311bf Lazily load the user during the check passport event
2020-08-27 16:29:00 +02:00
.github Merge branch '4.4' into 5.1 2020-07-29 16:51:18 +02:00
src/Symfony Lazily load the user during the check passport event 2020-08-27 16:28:46 +02:00
.appveyor.yml Merge branch '5.0' 2020-04-12 11:49:11 +02:00
.editorconfig Update .editorconfig 2018-09-06 16:22:56 +02:00
.gitignore Run the phpunit-bridge from a PR 2019-08-02 17:46:19 +02:00
.php_cs.dist [Serializer] Add CompiledClassMetadataFactory 2020-08-11 12:10:04 +02:00
.travis.yml clean up HHVM instructions 2020-07-08 16:52:52 +02:00
CHANGELOG-4.0.md Merge branch '3.4' into 4.1 2018-08-01 18:22:14 +02:00
CHANGELOG-4.1.md updated CHANGELOG for 4.1.10 2019-01-06 17:16:07 +01:00
CHANGELOG-4.2.md updated CHANGELOG for 4.2.10 2019-06-26 16:19:37 +02:00
CHANGELOG-4.3.md updated CHANGELOG for 4.3.10 2020-01-21 14:13:32 +01:00
CHANGELOG-4.4.md Update CHANGELOG for 4.4.11 2020-07-24 06:09:57 +02:00
CHANGELOG-5.0.md Merge branch '5.0' into 5.1 2020-06-15 13:50:15 +02:00
CHANGELOG-5.1.md Update CHANGELOG for 5.1.3 2020-07-24 06:22:46 +02:00
CODE_OF_CONDUCT.md Added the Code of Conduct file 2018-10-10 03:13:30 -07:00
composer.json Merge branch '5.1' 2020-08-21 19:20:41 +02:00
CONTRIBUTING.md Mention the community review guide 2016-12-18 22:02:35 +01:00
CONTRIBUTORS.md update CONTRIBUTORS for 3.4.43 2020-07-24 05:48:58 +02:00
LICENSE Update year in license files 2020-01-01 12:03:25 +01:00
link Merge branch '3.4' into 4.4 2020-08-26 10:30:46 +02:00
phpunit Use PHPUnit 9.3 on php 8. 2020-08-10 10:16:22 +02:00
phpunit.xml.dist [Uid] minor improvements 2020-03-20 20:42:05 +01:00
README.md Minor improvement 2020-07-29 07:57:47 +02:00
UPGRADE-5.0.md Typo: somes styles fixed 2020-08-06 09:00:23 +02:00
UPGRADE-5.1.md Added deprecation for RememberMe services without logout() method 2020-05-16 13:05:23 +02:00
UPGRADE-5.2.md Renamed $providerKey to $firewallName 2020-08-26 17:34:05 +02:00
UPGRADE-6.0.md Renamed $providerKey to $firewallName 2020-08-26 17:34:05 +02:00

Symfony is a PHP framework for web and console applications and a set of reusable PHP components. Symfony is used by thousands of web applications (including BlaBlaCar.com and Spotify.com) and most of the popular PHP projects (including Drupal and Magento).

Installation

Documentation

Community

Contributing

Symfony is an Open Source, community-driven project with thousands of contributors. Join them contributing code or contributing documentation.

Security Issues

If you discover a security vulnerability within Symfony, please follow our disclosure procedure.

About Us

Symfony development is sponsored by SensioLabs, led by the Symfony Core Team and supported by Symfony contributors.