Skip to content
This repository has been archived by the owner on Jul 4, 2018. It is now read-only.

Commit

Permalink
feature #1320 Use BCrypt by default as encoder #1312 (e-moe)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.0.x-dev branch.

Discussion
----------

Use BCrypt by default as encoder #1312

Based on work of @mvanbaak (#1316) with applied comments from @mathroc and fixed tests.

Commits
-------

7f13e76 use bcrypt by default as encoder #1312; add pbkdf2 encoder
  • Loading branch information
fabpot committed Mar 10, 2016
2 parents 800912d + 7f13e76 commit 83ce587
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 24 deletions.
48 changes: 36 additions & 12 deletions doc/providers/security.rst
Expand Up @@ -10,6 +10,8 @@ Parameters
* **security.hide_user_not_found** (optional): Defines whether to hide user not
found exception or not. Defaults to ``true``.

* **security.encoder.bcrypt.cost** (optional): Defines BCrypt password encoder cost. Defaults to 13.

Services
--------

Expand All @@ -36,9 +38,15 @@ Services
Request object.

* **security.encoder_factory**: Defines the encoding strategies for user
passwords (default to use a digest algorithm for all users).
passwords (uses ``security.default_encoder``).

* **security.default_encoder**: The encoder to use by default for all users (BCrypt).

* **security.encoder.digest**: Digest password encoder.

* **security.encoder.bcrypt**: BCrypt password encoder.

* **security.encoder.digest**: The encoder to use by default for all users.
* **security.encoder.pbkdf2**: Pbkdf2 password encoder.

* **user**: Returns the current user

Expand Down Expand Up @@ -552,20 +560,36 @@ sample users::
Defining a custom Encoder
~~~~~~~~~~~~~~~~~~~~~~~~~

By default, Silex uses the ``sha512`` algorithm to encode passwords.
Additionally, the password is encoded multiple times and converted to base64.
You can change these defaults by overriding the ``security.encoder.digest``
service::
By default, Silex uses the ``BCrypt`` algorithm to encode passwords.
Additionally, the password is encoded multiple times.
You can change these defaults by overriding ``security.default_encoder``
service to return one of the predefined encoders:

use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
* **security.encoder.digest**: Digest password encoder.

* **security.encoder.bcrypt**: BCrypt password encoder.

* **security.encoder.pbkdf2**: Pbkdf2 password encoder.

.. code-block:: php
$app['security.encoder.digest'] = function ($app) {
// use the sha1 algorithm
// don't base64 encode the password
// use only 1 iteration
return new MessageDigestPasswordEncoder('sha1', false, 1);
$app['security.default_encoder'] = function ($app) {
return $app['security.encoder.pbkdf2'];
};
Or you can define you own, fully customizable encoder::

use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;

$app['security.default_encoder'] = function ($app) {
// Plain text (e.g. for debugging)
return new PlaintextPasswordEncoder();
};

.. tip::

You can change the default BCrypt encoding cost by overriding ``security.encoder.bcrypt.cost``

Defining a custom Authentication Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
18 changes: 17 additions & 1 deletion src/Silex/Provider/SecurityServiceProvider.php
Expand Up @@ -26,6 +26,8 @@
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
Expand Down Expand Up @@ -78,6 +80,7 @@ public function register(Container $app)
$app['security.role_hierarchy'] = array();
$app['security.access_rules'] = array();
$app['security.hide_user_not_found'] = true;
$app['security.encoder.bcrypt.cost'] = 13;

$app['security.authorization_checker'] = function ($app) {
return new AuthorizationChecker($app['security.token_storage'], $app['security.authentication_manager'], $app['security.access_manager']);
Expand Down Expand Up @@ -109,14 +112,27 @@ public function register(Container $app)
// by default, all users use the digest encoder
$app['security.encoder_factory'] = function ($app) {
return new EncoderFactory(array(
'Symfony\Component\Security\Core\User\UserInterface' => $app['security.encoder.digest'],
'Symfony\Component\Security\Core\User\UserInterface' => $app['security.default_encoder'],
));
};

// by default, all users use the BCrypt encoder
$app['security.default_encoder'] = function ($app) {
return $app['security.encoder.bcrypt'];
};

$app['security.encoder.digest'] = function ($app) {
return new MessageDigestPasswordEncoder();
};

$app['security.encoder.bcrypt'] = function ($app) {
return new BCryptPasswordEncoder($app['security.encoder.bcrypt.cost']);
};

$app['security.encoder.pbkdf2'] = function ($app) {
return new Pbkdf2PasswordEncoder();
};

$app['security.user_checker'] = function ($app) {
return new UserChecker();
};
Expand Down
13 changes: 9 additions & 4 deletions tests/Silex/Tests/Application/SecurityTraitTest.php
Expand Up @@ -25,11 +25,16 @@ class SecurityTraitTest extends \PHPUnit_Framework_TestCase
public function testEncodePassword()
{
$app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
));

$user = new User('foo', 'bar');
$this->assertEquals('5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg==', $app->encodePassword($user, 'foo'));
$password = 'foo';
$encoded = $app->encodePassword($user, $password);

$this->assertTrue(
$app['security.encoder_factory']->getEncoder($user)->isPasswordValid($encoded, $password, $user->getSalt())
);
}

/**
Expand All @@ -48,8 +53,8 @@ public function testIsGranted()
$request = Request::create('/');

$app = $this->createApplication(array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'monique' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'monique' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
));
$app->get('/', function () { return 'foo'; });

Expand Down
Expand Up @@ -77,7 +77,7 @@ public function createApplication($authenticationMethod = 'form')
'remember_me' => array(),
'logout' => true,
'users' => array(
'fabien' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
),
),
);
Expand Down
10 changes: 5 additions & 5 deletions tests/Silex/Tests/Provider/SecurityServiceProviderTest.php
Expand Up @@ -187,7 +187,7 @@ public function testUser()
'default' => array(
'http' => true,
'users' => array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
),
),
),
Expand Down Expand Up @@ -271,8 +271,8 @@ private function addFormAuthentication($app)
'logout' => true,
'users' => array(
// password is foo
'fabien' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'admin' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
),
),
),
Expand Down Expand Up @@ -322,8 +322,8 @@ private function addHttpAuthentication($app)
'http' => true,
'users' => array(
// password is foo
'dennis' => array('ROLE_USER', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'dennis' => array('ROLE_USER', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
'admin' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
),
),
),
Expand Down
2 changes: 1 addition & 1 deletion tests/Silex/Tests/Route/SecurityTraitTest.php
Expand Up @@ -74,7 +74,7 @@ private function createApplication()
'default' => array(
'http' => true,
'users' => array(
'fabien' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
'fabien' => array('ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'),
),
),
),
Expand Down

0 comments on commit 83ce587

Please sign in to comment.