Skip to content

Commit

Permalink
use new authenticator manager (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
solverat authored May 24, 2023
1 parent ad59453 commit 21c2fbe
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 40 deletions.
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ bin/console members:install:class

### Security Installation
It is not possible to merge security configurations from multiple locations, including bundles. Instead, you have to move them to
one single config file, e.g. `config/packages/security.yaml`. Please adopt `MembersBundle/Resources/config/packages/security.yaml`
one single config file, e.g. `config/packages/security.yaml`. Please adopt [security_auth_manager.yaml](./src/MembersBundle/Resources/config/packages/security_auth_manager.yaml)
and merge your own firewall configuration into one single file.

#### Legacy Security Configuration
⚠️ If you still want to use the legacy authenticator, adopt [security_legacy.yaml](./src/MembersBundle/Resources/config/packages/security_legacy.yaml)
Keep in mind, that this configuration will be removed in Members 5.0.

### Route Installation
MembersBundle does not include any routes per default. Otherwise, it would be hard for you to change or override included routes.

Expand Down Expand Up @@ -85,15 +89,15 @@ You need two classes: User and Group. So let's create it:
2. Add parent class: `\MembersBundle\Adapter\User\AbstractUser`
3. Add fields:

| Name | Field Type | Comment |
|---------------------|-------------|-------------------------------|
| userName | Input | |
| email | Input | **Note:** Do not add this field if you're using the [CMF](docs/20_ClassCustomization.md). |
| confirmationToken | Input | must set to it read only |
| lastLogin | Date & Time | must set to it read only |
| password | Password | Hide it, if you want. **Note:** Do not add this field if you're using the [CMF](docs/20_ClassCustomization.md). |
| passwordRequestedAt | Date & Time | must set to it read only |
| groups | User Group | This field comes with Members |
| Name | Field Type | Comment |
|---------------------|-------------|-----------------------------------------------------------------------------------------------------------------|
| userName | Input | |
| email | Input | **Note:** Do not add this field if you're using the [CMF](docs/20_ClassCustomization.md). |
| confirmationToken | Input | must set to it read only |
| lastLogin | Date & Time | must set to it read only |
| password | Password | Hide it, if you want. **Note:** Do not add this field if you're using the [CMF](docs/20_ClassCustomization.md). |
| passwordRequestedAt | Date & Time | must set to it read only |
| groups | User Group | This field comes with Members |

> `membersUser` is the default name, you may want to change it. Read [here](docs/20_ClassCustomization.md) how to achieve that.

Expand All @@ -108,9 +112,9 @@ You want to enable the SSO Feature in Members? Read more about it [here](./docs/
2. Add parent class: `\MembersBundle\Adapter\Group\AbstractGroup`
3. Add fields:

| Name | Field Type | Comment |
|---------------------|-------------|-------------------------------|
| name | Input | |
| Name | Field Type | Comment |
|-------|----------------|-------------------------------------------------------------------------------------------------------------|
| name | Input | |
| roles | Multiselection | Set "Options Provider Class or Service Name" to `@MembersBundle\CoreExtension\Provider\RoleOptionsProvider` |

> `membersGroup` is the default name, you may want to change it. Read [here](docs/20_ClassCustomization.md) how to achieve that.
Expand Down
1 change: 1 addition & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- **[ENHANCEMENT]**: Add public asset path protection, read more about it [here](./docs/200_Restrictions.md#public-assets-path-protection)
- **[ENHANCEMENT]**: Respect flysystem stream in asset/zip download, read more about it [here](./docs/240_AssetProtection.md#package) | [#174|@aarongerig](https://github.com/dachcom-digital/pimcore-members/pull/174)
- **[ENHANCEMENT]**: Do not throw any exception if confirmation token couldn't be found. Please check `views/registration/confirmed.html.twig` for changes to adopt [#175](https://github.com/dachcom-digital/pimcore-members/issues/175)
- **[NEW FEATURE]**: Provide new authentication workflow (`security.enable_authenticator_manager = true`). If you want to switch, read more about it [here](./README.md#security-installation) | [#160](https://github.com/dachcom-digital/pimcore-members/issues/160)

### 4.0.4
- **[BUGFIX]**: assert non list array after filtering user roles [@dasraab](https://github.com/dachcom-digital/pimcore-members/pull/169)
Expand Down
2 changes: 1 addition & 1 deletion docs/SSO/20_Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ If you don't want to use it, you need to check several steps which we're going t

## Install Classes
You need an additional Class for the SSO Identity. Every provider (e.g. Google or Facebook) creates an `SsoIdentity` entity, which gets appended to a user object.
If you're using all the default Members Classes, you can simple re-run the command:
If you're using all the default Members Classes, you can simply re-run the command:

````bash
$ bin/console members:install:class -o
Expand Down
102 changes: 85 additions & 17 deletions src/MembersBundle/DependencyInjection/MembersExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace MembersBundle\DependencyInjection;

use MembersBundle\Adapter\User\UserInterface;
use MembersBundle\Security\Authenticator\OAuthIdentityAuthenticator;
use MembersBundle\Security\Encoder\Factory\UserAwareEncoderFactory;
use MembersBundle\Security\OAuth\Dispatcher\ConnectDispatcher;
use MembersBundle\Security\OAuth\Dispatcher\LoginDispatcher;
use MembersBundle\Security\OAuth\Dispatcher\Router\DispatchRouter;
use MembersBundle\Security\OAuthIdentityAuthenticator;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
Expand All @@ -22,25 +24,13 @@ public function prepend(ContainerBuilder $container): void
$configs = $container->getExtensionConfig($this->getAlias());
$config = $this->processConfiguration($this->getConfiguration([], $container), $configs);

if ($container->hasExtension('security') === false) {
return;
$oauthEnabled = false;
if ($container->hasExtension('security') === true && $config['oauth']['enabled'] === true) {
$oauthEnabled = true;
}

if ($config['oauth']['enabled'] === false) {
return;
}
$this->extendPimcoreSecurityConfiguration($container, $oauthEnabled);

$container->loadFromExtension('security', [
'firewalls' => [
'members_fe' => [
'guard' => [
'authenticators' => [
OAuthIdentityAuthenticator::class
]
]
]
]
]);
}

/**
Expand Down Expand Up @@ -101,6 +91,8 @@ public function load(array $configs, ContainerBuilder $container): void
$loader->load('oauth.yml');
$this->enableOauth($container, $config);
}

$this->buildSecurityConfiguration($container, $loader);
}

protected function enableOauth(ContainerBuilder $container, array $config): void
Expand All @@ -121,4 +113,80 @@ protected function enableOauth(ContainerBuilder $container, array $config): void
$container->setParameter('members_user.oauth.sso_identity_complete_profile.form.' . $confName, $confValue);
}
}

protected function extendPimcoreSecurityConfiguration(ContainerBuilder $container, bool $oauthEnabled): void
{
if ($this->authenticatorIsEnabled($container) === false) {

$container->loadFromExtension('pimcore', [
'security' => [
'encoder_factories' => [
UserInterface::class => UserAwareEncoderFactory::class
]
]
]);

if ($oauthEnabled === true) {
$container->loadFromExtension('security', [
'firewalls' => [
'members_fe' => [
'guard' => [
'authenticators' => [
\MembersBundle\Security\OAuthIdentityAuthenticator::class
]
]
]
]
]);
}

return;
}

$container->loadFromExtension('pimcore', [
'security' => [
'password_hasher_factories' => [
UserInterface::class => 'members.security.password_hasher_factory'
]
]
]);

if ($oauthEnabled === true) {
$container->loadFromExtension('security', [
'firewalls' => [
'members_fe' => [
'custom_authenticators' => [
OAuthIdentityAuthenticator::class
]
]
]
]);
}
}

protected function buildSecurityConfiguration(ContainerBuilder $container, YamlFileLoader $loader): void
{
if ($this->authenticatorIsEnabled($container) === false) {
$loader->load('security_legacy.yml');

return;
}

$loader->load('security_authenticator_manager.yml');
}

protected function authenticatorIsEnabled(ContainerBuilder $container): bool
{
/** @phpstan-ignore-next-line */
if (!$container->hasParameter('security.authenticator.manager.enabled')) {
return false;
}

/** @phpstan-ignore-next-line */
if ($container->getParameter('security.authenticator.manager.enabled') !== true) {
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
security:

enable_authenticator_manager: true

# symfony default is set to "true".
# you may want to keep it "true" but keep in mind that this hide meaningful exceptions like "acount is disabled"
# instead the BadCredentialsException will be thrown
hide_user_not_found: false

providers:

# [...] other providers

members:
id: MembersBundle\Security\UserProvider

firewalls:

# [...] other firewalls

members_fe:
pattern: ^/(?!(admin)($|/)).*$
provider: members
entry_point: form_login
form_login:
login_path: members_user_security_login
check_path: members_user_security_check
enable_csrf: true
logout:
path: members_user_security_logout
invalidate_session: false
target: /
user_checker: MembersBundle\Security\UserChecker

access_control:

# [...] other access controls

- { path: ^/_locale/members/login$, role: PUBLIC_ACCESS }
- { path: ^/_locale/members/register, role: PUBLIC_ACCESS }
- { path: ^/_locale/members/resetting, role: PUBLIC_ACCESS }
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ security:
hide_user_not_found: false

providers:

# [...] other providers

members:
id: MembersBundle\Security\UserProvider

firewalls:

# [...] other firewalls

members_fe:
pattern: ^/(?!(admin)($|/)).*$
provider: members
Expand All @@ -21,7 +28,11 @@ security:
target: /
anonymous: true
user_checker: MembersBundle\Security\UserChecker

access_control:

# [...] other access controls

- { path: ^/_locale/members/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/_locale/members/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/_locale/members/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
3 changes: 0 additions & 3 deletions src/MembersBundle/Resources/config/pimcore/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ doctrine_migrations:
'MembersBundle\Migrations': '@MembersBundle/Migrations'

pimcore:
security:
encoder_factories:
MembersBundle\Adapter\User\UserInterface: MembersBundle\Security\Encoder\Factory\UserAwareEncoderFactory
objects:
class_definitions:
data:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
members.security.password_hasher_factory:
class: Pimcore\Security\Hasher\Factory\UserAwarePasswordHasherFactory
arguments:
- Pimcore\Security\Hasher\PasswordFieldHasher
- ['password']
5 changes: 5 additions & 0 deletions src/MembersBundle/Resources/config/security_legacy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
MembersBundle\Security\Encoder\Factory\UserAwareEncoderFactory:
arguments:
$className: 'Pimcore\Security\Encoder\PasswordFieldEncoder'
$arguments: ['password']
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ services:
arguments:
$scopes: '%members.oauth.scopes%'

MembersBundle\Security\OAuthIdentityAuthenticator: ~
MembersBundle\Security\OAuthIdentityAuthenticator:
deprecated:
message: 'The "%service_id%" service is deprecated. Use MembersBundle\Security\Authenticator\OAuthIdentityAuthenticator instead'
package: dachcom-digital/members
version: 4.1

MembersBundle\Security\Authenticator\OAuthIdentityAuthenticator: ~

MembersBundle\Security\OAuth\Dispatcher\ConnectDispatcher: ~
MembersBundle\Security\OAuth\Dispatcher\LoginDispatcher: ~
Expand Down
5 changes: 0 additions & 5 deletions src/MembersBundle/Resources/config/services/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ services:
arguments:
$authIdentifier: '%members.auth.identifier%'

MembersBundle\Security\Encoder\Factory\UserAwareEncoderFactory:
arguments:
$className: 'Pimcore\Security\Encoder\PasswordFieldEncoder'
$arguments: ['password']

MembersBundle\Form\Type\LoginFormType:
tags:
- { name: form.type, alias: members_user_resetting }
Expand Down
Loading

0 comments on commit 21c2fbe

Please sign in to comment.