Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 80eb8a3

Browse filesBrowse files
committed
Add a normalization step for the user-identifier in firewalls
1 parent cad21a9 commit 80eb8a3
Copy full SHA for 80eb8a3

File tree

Expand file treeCollapse file tree

14 files changed

+297
-2
lines changed
Filter options
Expand file treeCollapse file tree

14 files changed

+297
-2
lines changed

‎src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Add `Security::isGrantedForUser()` to test user authorization without relying on the session. For example, users not currently logged in, or while processing a message from a message queue
88
* Add encryption support to `OidcTokenHandler` (JWE)
9+
* Add ability to fetch Ldap roles
910

1011
7.2
1112
---

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function create(ContainerBuilder $container, string $id, array $config):
3737
->replaceArgument(6, $config['filter'])
3838
->replaceArgument(7, $config['password_attribute'])
3939
->replaceArgument(8, $config['extra_fields'])
40+
->replaceArgument(9, $config['role_fetcher'] ? new Reference($config['role_fetcher']) : null)
4041
;
4142
}
4243

@@ -63,6 +64,7 @@ public function addConfiguration(NodeDefinition $node): void
6364
->requiresAtLeastOneElement()
6465
->prototype('scalar')->end()
6566
->end()
67+
->scalarNode('role_fetcher')->defaultNull()->end()
6668
->scalarNode('uid_key')->defaultValue('sAMAccountName')->end()
6769
->scalarNode('filter')->defaultValue('({uid_key}={user_identifier})')->end()
6870
->scalarNode('password_attribute')->defaultNull()->end()

‎src/Symfony/Bundle/SecurityBundle/Resources/config/security.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/security.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
abstract_arg('filter'),
269269
abstract_arg('password_attribute'),
270270
abstract_arg('extra_fields (email etc)'),
271+
abstract_arg('role fetcher'),
271272
])
272273

273274
->set('security.user.provider.chain', ChainUserProvider::class)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLdapLoginBundle\Controller;
13+
14+
use Symfony\Component\HttpFoundation\JsonResponse;
15+
use Symfony\Component\Security\Core\User\UserInterface;
16+
17+
class TestController
18+
{
19+
public function loginCheckAction(UserInterface $user)
20+
{
21+
return new JsonResponse([
22+
'message' => \sprintf('Welcome @%s!', $user->getUserIdentifier()),
23+
'roles' => $user->getRoles(),
24+
]);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLdapLoginBundle\Security\Ldap;
13+
14+
use Symfony\Component\Ldap\Entry;
15+
use Symfony\Component\Ldap\Security\RoleFetcherInterface;
16+
17+
class DummyRoleFetcher implements RoleFetcherInterface
18+
{
19+
public function fetchRoles(Entry $entry): array
20+
{
21+
if ($entry->getAttribute('uid') === ['spomky']) {
22+
return ['ROLE_SUPER_ADMIN', 'ROLE_USER'];
23+
}
24+
25+
return ['ROLE_LDAP_USER_42', 'ROLE_USER'];
26+
}
27+
}

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/JsonLoginLdapTest.php
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@
1111

1212
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
1313

14+
use Symfony\Component\HttpFoundation\JsonResponse;
1415
use Symfony\Component\HttpKernel\Kernel;
16+
use Symfony\Component\Ldap\Adapter\AdapterInterface;
17+
use Symfony\Component\Ldap\Adapter\CollectionInterface;
18+
use Symfony\Component\Ldap\Adapter\ConnectionInterface;
19+
use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
20+
use Symfony\Component\Ldap\Adapter\QueryInterface;
21+
use Symfony\Component\Ldap\Entry;
1522

1623
class JsonLoginLdapTest extends AbstractWebTestCase
1724
{
@@ -22,4 +29,45 @@ public function testKernelBoot()
2229

2330
$this->assertInstanceOf(Kernel::class, $kernel);
2431
}
32+
33+
public function testDefaultJsonLdapLoginSuccess()
34+
{
35+
if (!class_exists(\Symfony\Component\Ldap\Security\RoleFetcherInterface::class)) {
36+
$this->markTestSkipped('The "Ldap" component does not support Ldap roles.');
37+
}
38+
// Given
39+
$client = $this->createClient(['test_case' => 'JsonLoginLdap', 'root_config' => 'config.yml', 'debug' => true]);
40+
$container = $client->getContainer();
41+
$connectionMock = $this->createMock(ConnectionInterface::class);
42+
$collection = new class([new Entry('', ['uid' => ['spomky']])]) extends \ArrayObject implements CollectionInterface {
43+
public function toArray(): array
44+
{
45+
return $this->getArrayCopy();
46+
}
47+
};
48+
$queryMock = $this->createMock(QueryInterface::class);
49+
$queryMock
50+
->method('execute')
51+
->willReturn($collection)
52+
;
53+
$ldapAdapterMock = $this->createMock(AdapterInterface::class);
54+
$ldapAdapterMock
55+
->method('getConnection')
56+
->willReturn($connectionMock)
57+
;
58+
$ldapAdapterMock
59+
->method('createQuery')
60+
->willReturn($queryMock)
61+
;
62+
$container->set(Adapter::class, $ldapAdapterMock);
63+
64+
// When
65+
$client->request('POST', '/login', [], [], ['CONTENT_TYPE' => 'application/json'], '{"user": {"login": "spomky", "password": "foo"}}');
66+
$response = $client->getResponse();
67+
68+
// Then
69+
$this->assertInstanceOf(JsonResponse::class, $response);
70+
$this->assertSame(200, $response->getStatusCode());
71+
$this->assertSame(['message' => 'Welcome @spomky!', 'roles' => ['ROLE_SUPER_ADMIN', 'ROLE_USER']], json_decode($response->getContent(), true));
72+
}
2573
}

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/config.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLoginLdap/config.yml
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ imports:
33
services:
44
Symfony\Component\Ldap\Ldap:
55
arguments: ['@Symfony\Component\Ldap\Adapter\ExtLdap\Adapter']
6+
tags: [ 'ldap' ]
67

78
Symfony\Component\Ldap\Adapter\ExtLdap\Adapter:
89
arguments:
@@ -21,7 +22,7 @@ security:
2122
search_password: ''
2223
default_roles: ROLE_USER
2324
uid_key: uid
24-
extra_fields: ['email']
25+
#extra_fields: ['email']
2526

2627
firewalls:
2728
main:
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
login_check:
2+
path: /login
3+
defaults: { _controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\JsonLdapLoginBundle\Controller\TestController::loginCheckAction }

‎src/Symfony/Component/Ldap/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Ldap/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add ability to fetch roles
8+
49
7.2
510
---
611

+33Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 Symfony\Component\Ldap\Entry;
15+
16+
final readonly class AssignDefaultRoles implements RoleFetcherInterface
17+
{
18+
/**
19+
* @param string[] $roles
20+
*/
21+
public function __construct(
22+
private array $roles,
23+
) {
24+
}
25+
26+
/**
27+
* @return string[]
28+
*/
29+
public function fetchRoles(Entry $entry): array
30+
{
31+
return $this->roles;
32+
}
33+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.