Skip to content

Commit 7403a6d

Browse files
committed
feature #5255 [Cookbook] Use configured user provider instead of injection (mvar)
This PR was submitted for the 2.5 branch but it was merged into the 2.6 branch instead (closes #5255). Discussion ---------- [Cookbook] Use configured user provider instead of injection | Q | A | ------------- | --- | Doc fix? | yes | New docs? | no | Applies to | 2.5, 2.6 | Fixed tickets | #5252 Commits ------- 8556ae2 Improve invalid user provider exception message 77fdbbe Check user provider type f7d7f81 Use configured user provider instead of injection
2 parents 2a949b9 + 8556ae2 commit 7403a6d

File tree

1 file changed

+50
-38
lines changed

1 file changed

+50
-38
lines changed

cookbook/security/api_key_authentication.rst

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@ value and then a User object is created::
3232

3333
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
3434
{
35-
protected $userProvider;
36-
37-
public function __construct(ApiKeyUserProvider $userProvider)
38-
{
39-
$this->userProvider = $userProvider;
40-
}
41-
4235
public function createToken(Request $request, $providerKey)
4336
{
4437
// look for an apikey query parameter
@@ -63,16 +56,25 @@ value and then a User object is created::
6356

6457
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
6558
{
59+
if (!$userProvider instanceof ApiKeyUserProvider) {
60+
throw new \InvalidArgumentException(
61+
sprintf(
62+
'The user provider must be an instance of ApiKeyUserProvider (%s was given).',
63+
get_class($userProvider)
64+
)
65+
);
66+
}
67+
6668
$apiKey = $token->getCredentials();
67-
$username = $this->userProvider->getUsernameForApiKey($apiKey);
69+
$username = $userProvider->getUsernameForApiKey($apiKey);
6870

6971
if (!$username) {
7072
throw new AuthenticationException(
7173
sprintf('API Key "%s" does not exist.', $apiKey)
7274
);
7375
}
7476

75-
$user = $this->userProvider->loadUserByUsername($username);
77+
$user = $userProvider->loadUserByUsername($username);
7678

7779
return new PreAuthenticatedToken(
7880
$user,
@@ -189,7 +191,7 @@ The ``$userProvider`` might look something like this::
189191
}
190192
}
191193

192-
Now register your user provider as service:
194+
Now register your user provider as a service:
193195

194196
.. configuration-block::
195197

@@ -255,7 +257,7 @@ exception in ``refreshUser()``.
255257
Handling Authentication Failure
256258
-------------------------------
257259

258-
In order for your ``ApiKeyAuthentication`` to correctly display a 403
260+
In order for your ``ApiKeyAuthenticator`` to correctly display a 403
259261
http status when either bad credentials or authentication fails you will
260262
need to implement the :class:`Symfony\\Component\\Security\\Http\\Authentication\\AuthenticationFailureHandlerInterface` on your
261263
Authenticator. This will provide a method ``onAuthenticationFailure`` which
@@ -287,11 +289,9 @@ you can use to create an error ``Response``.
287289
Configuration
288290
-------------
289291

290-
Once you have your ``ApiKeyAuthentication`` all setup, you need to register
292+
Once you have your ``ApiKeyAuthenticator`` all setup, you need to register
291293
it as a service and use it in your security configuration (e.g. ``security.yml``).
292-
First, register it as a service. This assumes that you have already setup
293-
your custom user provider as a service called ``your_api_key_user_provider``
294-
(see :doc:`/cookbook/security/custom_provider`).
294+
First, register it as a service.
295295

296296
.. configuration-block::
297297

@@ -302,8 +302,8 @@ your custom user provider as a service called ``your_api_key_user_provider``
302302
# ...
303303
304304
apikey_authenticator:
305-
class: AppBundle\Security\ApiKeyAuthenticator
306-
arguments: ["@api_key_user_provider"]
305+
class: AppBundle\Security\ApiKeyAuthenticator
306+
public: false
307307
308308
.. code-block:: xml
309309
@@ -318,9 +318,7 @@ your custom user provider as a service called ``your_api_key_user_provider``
318318
319319
<service id="apikey_authenticator"
320320
class="AppBundle\Security\ApiKeyAuthenticator"
321-
>
322-
<argument type="service" id="api_key_user_provider" />
323-
</service>
321+
public="false" />
324322
</services>
325323
</container>
326324
@@ -332,13 +330,13 @@ your custom user provider as a service called ``your_api_key_user_provider``
332330
333331
// ...
334332
335-
$container->setDefinition('apikey_authenticator', new Definition(
336-
'AppBundle\Security\ApiKeyAuthenticator',
337-
array(new Reference('api_key_user_provider'))
338-
));
333+
$definition = new Definition('AppBundle\Security\ApiKeyAuthenticator');
334+
$definition->setPublic(false);
335+
$container->setDefinition('apikey_authenticator', $definition);
339336
340-
Now, activate it in the ``firewalls`` section of your security configuration
341-
using the ``simple_preauth`` key:
337+
Now, activate it and your custom user provider (see :doc:`/cookbook/security/custom_provider`)
338+
in the ``firewalls`` section of your security configuration
339+
using the ``simple_preauth`` and ``provider`` keys respectively:
342340

343341
.. configuration-block::
344342

@@ -354,6 +352,7 @@ using the ``simple_preauth`` key:
354352
stateless: true
355353
simple_preauth:
356354
authenticator: apikey_authenticator
355+
provider: api_key_user_provider
357356
358357
providers:
359358
api_key_user_provider:
@@ -374,6 +373,7 @@ using the ``simple_preauth`` key:
374373
<firewall name="secured_area"
375374
pattern="^/admin"
376375
stateless="true"
376+
provider="api_key_user_provider"
377377
>
378378
<simple-preauth authenticator="apikey_authenticator" />
379379
</firewall>
@@ -396,6 +396,7 @@ using the ``simple_preauth`` key:
396396
'simple_preauth' => array(
397397
'authenticator' => 'apikey_authenticator',
398398
),
399+
'provider' => 'api_key_user_provider',
399400
),
400401
),
401402
'providers' => array(
@@ -405,7 +406,7 @@ using the ``simple_preauth`` key:
405406
),
406407
));
407408
408-
That's it! Now, your ``ApiKeyAuthentication`` should be called at the beginning
409+
That's it! Now, your ``ApiKeyAuthenticator`` should be called at the beginning
409410
of each request and your authentication process will take place.
410411

411412
The ``stateless`` configuration parameter prevents Symfony from trying to
@@ -441,6 +442,7 @@ configuration or set it to ``false``:
441442
stateless: false
442443
simple_preauth:
443444
authenticator: apikey_authenticator
445+
provider: api_key_user_provider
444446
445447
providers:
446448
api_key_user_provider:
@@ -461,6 +463,7 @@ configuration or set it to ``false``:
461463
<firewall name="secured_area"
462464
pattern="^/admin"
463465
stateless="false"
466+
provider="api_key_user_provider"
464467
>
465468
<simple-preauth authenticator="apikey_authenticator" />
466469
</firewall>
@@ -482,6 +485,7 @@ configuration or set it to ``false``:
482485
'simple_preauth' => array(
483486
'authenticator' => 'apikey_authenticator',
484487
),
488+
'provider' => 'api_key_user_provider',
485489
),
486490
),
487491
'providers' => array(
@@ -504,8 +508,17 @@ to see if the stored token has a valid User object that can be used::
504508
// ...
505509
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
506510
{
511+
if (!$userProvider instanceof ApiKeyUserProvider) {
512+
throw new \InvalidArgumentException(
513+
sprintf(
514+
'The user provider must be an instance of ApiKeyUserProvider (%s was given).',
515+
get_class($userProvider)
516+
)
517+
);
518+
}
519+
507520
$apiKey = $token->getCredentials();
508-
$username = $this->userProvider->getUsernameForApiKey($apiKey);
521+
$username = $userProvider->getUsernameForApiKey($apiKey);
509522

510523
// User is the Entity which represents your user
511524
$user = $token->getUser();
@@ -524,7 +537,7 @@ to see if the stored token has a valid User object that can be used::
524537
);
525538
}
526539

527-
$user = $this->userProvider->loadUserByUsername($username);
540+
$user = $userProvider->loadUserByUsername($username);
528541

529542
return new PreAuthenticatedToken(
530543
$user,
@@ -598,13 +611,10 @@ current URL is before creating the token in ``createToken()``::
598611

599612
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
600613
{
601-
protected $userProvider;
602-
603614
protected $httpUtils;
604615

605-
public function __construct(UserProviderInterface $userProvider, HttpUtils $httpUtils)
616+
public function __construct(HttpUtils $httpUtils)
606617
{
607-
$this->userProvider = $userProvider;
608618
$this->httpUtils = $httpUtils;
609619
}
610620

@@ -639,7 +649,8 @@ service:
639649
640650
apikey_authenticator:
641651
class: AppBundle\Security\ApiKeyAuthenticator
642-
arguments: ["@api_key_user_provider", "@security.http_utils"]
652+
arguments: ["@security.http_utils"]
653+
public: false
643654
644655
.. code-block:: xml
645656
@@ -654,8 +665,8 @@ service:
654665
655666
<service id="apikey_authenticator"
656667
class="AppBundle\Security\ApiKeyAuthenticator"
668+
public="false"
657669
>
658-
<argument type="service" id="api_key_user_provider" />
659670
<argument type="service" id="security.http_utils" />
660671
</service>
661672
</services>
@@ -669,12 +680,13 @@ service:
669680
670681
// ...
671682
672-
$container->setDefinition('apikey_authenticator', new Definition(
683+
$definition = new Definition(
673684
'AppBundle\Security\ApiKeyAuthenticator',
674685
array(
675-
new Reference('api_key_user_provider'),
676686
new Reference('security.http_utils')
677687
)
678-
));
688+
);
689+
$definition->setPublic(false);
690+
$container->setDefinition('apikey_authenticator', $definition);
679691
680692
That's it! Have fun!

0 commit comments

Comments
 (0)