Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flexibilty to the provider and manager #40

Merged
merged 3 commits into from
Oct 29, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public function getConfigTreeBuilder()
->scalarNode('encoder_service')
->defaultValue('lexik_jwt_authentication.jwt_encoder')
->end()
->scalarNode('user_identity_field')
->defaultValue('username')
->cannotBeEmpty()
->end()
->end();

return $treeBuilder;
Expand Down
2 changes: 2 additions & 0 deletions DependencyInjection/LexikJWTAuthenticationExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('lexik_jwt_authentication.public_key_path', $config['public_key_path']);
$container->setParameter('lexik_jwt_authentication.pass_phrase', $config['pass_phrase']);
$container->setParameter('lexik_jwt_authentication.token_ttl', $config['token_ttl']);
$container->setParameter('lexik_jwt_authentication.user_identity_field', $config['user_identity_field']);

$container->setAlias('lexik_jwt_authentication.encoder', $config['encoder_service']);
}

Expand Down
5 changes: 4 additions & 1 deletion DependencyInjection/Security/Factory/JWTFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
{
$providerId = 'security.authentication.provider.jwt.' . $id;
$container
->setDefinition($providerId, new DefinitionDecorator('lexik_jwt_authentication.security.authentication.provider'))
->setDefinition($providerId, new DefinitionDecorator($config['authentication_provider']))
->replaceArgument(0, new Reference($userProvider));

$listenerId = 'security.authentication.listener.jwt.' . $id;
Expand Down Expand Up @@ -116,6 +116,9 @@ public function addConfiguration(NodeDefinition $node)
->booleanNode('create_entry_point')
->defaultTrue()
->end()
->scalarNode('authentication_provider')
->defaultValue('lexik_jwt_authentication.security.authentication.provider')
->end()
->end();
}

Expand Down
6 changes: 3 additions & 3 deletions Encoder/JWTEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ class JWTEncoder implements JWTEncoderInterface
/**
* @var string
*/
private $privateKey;
protected $privateKey;

/**
* @var string
*/
private $publicKey;
protected $publicKey;

/**
* @var string
*/
private $passPhrase;
protected $passPhrase;

/**
* @param string $privateKey
Expand Down
12 changes: 9 additions & 3 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,25 @@
</parameters>

<services>
<!-- JWT Encoder / Decoder -->
<!-- JWT Encoder / Decoder / Default implementation -->
<service id="lexik_jwt_authentication.jwt_encoder" class="%lexik_jwt_authentication.jwt_encoder.class%">
<argument>%lexik_jwt_authentication.private_key_path%</argument>
<argument>%lexik_jwt_authentication.public_key_path%</argument>
<argument>%lexik_jwt_authentication.pass_phrase%</argument>
</service>
<!-- JWT Manager -->
<!-- JWT Manager / Default implementation -->
<service id="lexik_jwt_authentication.jwt_manager" class="%lexik_jwt_authentication.jwt_manager.class%">
<argument type="service" id="lexik_jwt_authentication.encoder"/>
<argument type="service" id="event_dispatcher"/>
<argument>%lexik_jwt_authentication.token_ttl%</argument>
<call method="setRequest">
<argument type="service" id="request" on-invalid="null" strict="false" />
</call>
<call method="setUserIdentityField">
<argument>%lexik_jwt_authentication.user_identity_field%</argument>
</call>
</service>
<!-- JWT Authentication response interceptor -->
<!-- JWT Authentication response interceptor -->
<service id="lexik_jwt_authentication.handler.authentication_success" class="%lexik_jwt_authentication.handler.authentication_success.class%">
<argument type="service" id="lexik_jwt_authentication.jwt_manager"/>
<argument type="service" id="event_dispatcher"/>
Expand All @@ -46,6 +49,9 @@
<service id="lexik_jwt_authentication.security.authentication.provider" class="%lexik_jwt_authentication.security.authentication.provider.class%" public="false">
<argument /> <!-- User Provider -->
<argument type="service" id="lexik_jwt_authentication.jwt_manager" />
<call method="setUserIdentityField">
<argument>%lexik_jwt_authentication.user_identity_field%</argument>
</call>
</service>
<!-- JWT Security Authentication Listener -->
<service id="lexik_jwt_authentication.security.authentication.listener" class="%lexik_jwt_authentication.security.authentication.listener.class%" public="false">
Expand Down
61 changes: 49 additions & 12 deletions Security/Authentication/Provider/JWTProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Provider;

use Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTManager;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTManagerInterface;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
Expand All @@ -19,47 +19,84 @@ class JWTProvider implements AuthenticationProviderInterface
/**
* @var UserProviderInterface
*/
private $userProvider;
protected $userProvider;

/**
* @var JWTManager
* @var JWTManagerInterface
*/
private $jwtManager;
protected $jwtManager;

/**
* @var string
*/
protected $userIdentityField;

/**
* @param UserProviderInterface $userProvider
* @param JWTManager $jwtManager
* @param JWTManagerInterface $jwtManager
*/
public function __construct(UserProviderInterface $userProvider, JWTManager $jwtManager)
public function __construct(UserProviderInterface $userProvider, JWTManagerInterface $jwtManager)
{
$this->userProvider = $userProvider;
$this->jwtManager = $jwtManager;
$this->userProvider = $userProvider;
$this->jwtManager = $jwtManager;
$this->userIdentityField = 'username';
}

/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
$payload = $this->jwtManager->decode($token);

if (!$payload || !isset($payload['username'])) {
if (!($payload = $this->jwtManager->decode($token))) {
throw new AuthenticationException('Invalid JWT Token');
}

$user = $this->userProvider->loadUserByUsername($payload['username']);
$user = $this->getUserFromPayload($payload);

$authToken = new JWTUserToken($user->getRoles());
$authToken->setUser($user);

return $authToken;
}

/**
* Load user from payload, using username by default.
* Override this to load by another property.
*
* @param array $payload
*
* @return \Symfony\Component\Security\Core\User\UserInterface
*/
protected function getUserFromPayload(array $payload)
{
if (!isset($payload[$this->userIdentityField])) {
throw new AuthenticationException('Invalid JWT Token');
}

return $this->userProvider->loadUserByUsername($payload[$this->userIdentityField]);
}

/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof JWTUserToken;
}

/**
* @return string
*/
public function getUserIdentityField()
{
return $this->userIdentityField;
}

/**
* @param string $userIdentityField
*/
public function setUserIdentityField($userIdentityField)
{
$this->userIdentityField = $userIdentityField;
}
}
13 changes: 6 additions & 7 deletions Security/Http/Authentication/AuthenticationFailureHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/
class AuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
{
const RESPONSE_CODE = 401;
const RESPONSE_MESSAGE = 'Bad credentials';

/**
* @var EventDispatcherInterface
*/
Expand All @@ -35,17 +38,13 @@ public function __construct(EventDispatcherInterface $dispatcher)
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$statusCode = 401;

$data = array(
'code' => $statusCode,
'message' => 'Bad credentials',
'code' => self::RESPONSE_CODE,
'message' => self::RESPONSE_MESSAGE,
);

$response = new JsonResponse($data, $statusCode);

$event = new AuthenticationFailureEvent($request);
$event->setResponse($response);
$event->setResponse(new JsonResponse($data, self::RESPONSE_CODE));

$this->dispatcher->dispatch(Events::AUTHENTICATION_FAILURE, $event);

Expand Down
91 changes: 69 additions & 22 deletions Services/JWTManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @author Nicolas Cabot <[email protected]>
*/
class JWTManager
class JWTManager implements JWTManagerInterface
{
/**
* @var JWTEncoderInterface
Expand All @@ -28,10 +28,20 @@ class JWTManager
*/
protected $dispatcher;

/**
* @var integer
*/
protected $ttl;

/**
* @var string
*/
protected $userIdentityField;

/**
* @var Request
*/
private $request;
protected $request;

/**
* @param JWTEncoderInterface $encoder
Expand All @@ -40,29 +50,22 @@ class JWTManager
*/
public function __construct(JWTEncoderInterface $encoder, EventDispatcherInterface $dispatcher, $ttl)
{
$this->jwtEncoder = $encoder;
$this->dispatcher = $dispatcher;
$this->ttl = $ttl;
}

/**
* @param Request $request
*/
public function setRequest(Request $request = null)
{
$this->request = $request;
$this->jwtEncoder = $encoder;
$this->dispatcher = $dispatcher;
$this->ttl = $ttl;
$this->userIdentityField = 'username';
}

/**
* @param UserInterface $user
*
* @return string
* {@inheritdoc}
*/
public function create(UserInterface $user)
{
$payload = array();
$payload['exp'] = time() + $this->ttl;
$payload['username'] = $user->getUsername();
$payload = array(
'exp' => time() + $this->ttl
);

$this->addUserIdentityToPayload($user, $payload);

$event = new JWTCreatedEvent($payload, $user, $this->request);
$this->dispatcher->dispatch(Events::JWT_CREATED, $event);
Expand All @@ -71,9 +74,7 @@ public function create(UserInterface $user)
}

/**
* @param TokenInterface $token
*
* @return bool|string
* {@inheritdoc}
*/
public function decode(TokenInterface $token)
{
Expand All @@ -90,4 +91,50 @@ public function decode(TokenInterface $token)

return $payload;
}

/**
* Add user identity to payload, username by default.
* Override this if you need to identify it by another property.
*
* @param UserInterface $user
* @param array $payload
*/
protected function addUserIdentityToPayload(UserInterface $user, array &$payload)
{
$payload[$this->userIdentityField] = $user->getUsername();
}

/**
* @return string
*/
public function getUserIdentityField()
{
return $this->userIdentityField;
}

/**
* @param string $userIdentityField
*/
public function setUserIdentityField($userIdentityField)
{
$this->userIdentityField = $userIdentityField;
}

/**
* @param Request $request
*/
public function setRequest(Request $request = null)
{
$this->request = $request;
}

/**
* Get request
*
* @return Request
*/
public function getRequest()
{
return $this->request;
}
}
28 changes: 28 additions & 0 deletions Services/JWTManagerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Lexik\Bundle\JWTAuthenticationBundle\Services;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
* JWTManagerInterface
*
* @author Nicolas Cabot <[email protected]>
*/
interface JWTManagerInterface
{
/**
* @param UserInterface $user
*
* @return string
*/
public function create(UserInterface $user);

/**
* @param TokenInterface $token
*
* @return bool|string
*/
public function decode(TokenInterface $token);
}
Loading