Skip to content

Commit

Permalink
Doctrine (#26)
Browse files Browse the repository at this point in the history
* Better Doctrine support
* Simplified Credential Source
  • Loading branch information
Spomky authored Mar 6, 2019
1 parent 82f3a7c commit 09f3efa
Show file tree
Hide file tree
Showing 29 changed files with 965 additions and 283 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This framework contains PHP libraries and Symfony bundle to allow developpers to
- Extensions
- [x] registration and authentication support without extension
- [x] extension support
- [ ] appid extension support (optional)
- [x] appid extension support (optional)
- Cose Algorithms
- [x] RS1, RS256, RS384, RS512
- [x] PS256, PS384, PS512
Expand Down
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
},
"require-dev": {
"doctrine/dbal": "^2.9",
"doctrine/doctrine-bundle": "^1.10",
"doctrine/orm": "^2.6",
"php-coveralls/php-coveralls": "^2.0",
"php-http/httplug": "^1.0",
"php-http/httplug-bundle": "^1.0",
Expand Down
4 changes: 3 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ parameters:
- %currentWorkingDirectory%/src/*/tests/*
- %currentWorkingDirectory%/src/*/var/*
ignoreErrors:
- '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::addDefaultsIfNotSet\(\)#'
- '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::(.*)\(\)#'
- '#Cannot call method scalarNode() on Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface|null\.#'
- '#Call to function method_exists\(\) with Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder and (.*) will always evaluate to true\.#'
- '#Parameter \#1 \$serialized \(string\) of method (.*)::unserialize\(\) should be contravariant with parameter \$serialized \(mixed\) of method Symfony\\Component\\Security\\Core\\Authentication\\Token\\AbstractToken::unserialize\(\)#'
- '#Offset (.*) does not exist on array\(\)|array\((.*)\)\.#'
- '#Instantiation of deprecated class Jose\\Component\\Core\\Converter\\StandardConverter\.#'
- '#Call to method find\(\) of deprecated class Http\\Discovery\\MessageFactoryDiscovery\.#'
- '#Parameter (.*) of class FG\\ASN1\\Universal\\Integer constructor expects int, string given\.#'
- '#Fetching class constant class of deprecated class Webauthn\\CredentialRepository\.#'
- '#Interface Webauthn\\PublicKeyCredentialSourceRepository extends deprecated interface Webauthn\\CredentialRepository\.#'
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
Expand Down
30 changes: 28 additions & 2 deletions src/symfony-security/tests/config/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
parameters:
env(DATABASE_URL): ''

framework:
test: ~
secret: 'test'
Expand Down Expand Up @@ -34,7 +37,7 @@ services:

httplug.client.default: '@httplug.client.mock'

Webauthn\Bundle\Tests\Functional\CredentialRepository:
Webauthn\SecurityBundle\Tests\Functional\PublicKeyCredentialSourceRepository:
autowire: true

httplug:
Expand All @@ -48,11 +51,34 @@ twig:
paths:
'%kernel.project_dir%/tests/templates': ~

doctrine:
dbal:
# configure these for your database server
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci

url: '%env(resolve:DATABASE_URL)%'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/'
prefix: 'Webauthn\SecurityBundle\Tests\Functional'
alias: App

webauthn_security:
http_message_factory: 'Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory'

webauthn:
credential_repository: 'Webauthn\SecurityBundle\Tests\Functional\CredentialRepository'
credential_repository: 'Webauthn\SecurityBundle\Tests\Functional\PublicKeyCredentialSourceRepository'
android_safetynet:
enabled: true
api_key: 'api_key'
Expand Down
2 changes: 2 additions & 0 deletions src/symfony-security/tests/functional/AppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Webauthn\SecurityBundle\Tests\Functional;

use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Http\HttplugBundle\HttplugBundle;
use SpomkyLabs\CborBundle\SpomkyLabsCborBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
Expand All @@ -38,6 +39,7 @@ public function registerBundles(): array
new SecurityBundle(),
new TwigBundle(),
new HttplugBundle(),
new DoctrineBundle(),

new WebauthnBundle(),
new WebauthnSecurityBundle(),
Expand Down
93 changes: 0 additions & 93 deletions src/symfony-security/tests/functional/CredentialRepository.php

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2018 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Webauthn\SecurityBundle\Tests\Functional;

use Webauthn\AttestationStatement\AttestationStatement;
use Webauthn\AttestedCredentialData;
use Webauthn\PublicKeyCredentialDescriptor;
use Webauthn\PublicKeyCredentialSource;
use Webauthn\PublicKeyCredentialSourceRepository as PublicKeyCredentialSourceRepositoryInterface;
use Webauthn\TrustPath\EmptyTrustPath;

final class PublicKeyCredentialSourceRepository implements PublicKeyCredentialSourceRepositoryInterface
{
/**
* @var PublicKeyCredentialSource[]
*/
private $credentials;

public function __construct()
{
$pkcs1 = new PublicKeyCredentialSource(
\Safe\base64_decode('eHouz/Zi7+BmByHjJ/tx9h4a1WZsK4IzUmgGjkhyOodPGAyUqUp/B9yUkflXY3yHWsNtsrgCXQ3HjAIFUeZB+w==', true),
PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY,
[],
AttestationStatement::TYPE_NONE,
new EmptyTrustPath(),
\Safe\base64_decode('AAAAAAAAAAAAAAAAAAAAAA==', true),
\Safe\base64_decode('pQECAyYgASFYIJV56vRrFusoDf9hm3iDmllcxxXzzKyO9WruKw4kWx7zIlgg/nq63l8IMJcIdKDJcXRh9hoz0L+nVwP1Oxil3/oNQYs=', true),
'foo',
100
);
$this->save($pkcs1);
}

public function find(string $credentialId): ?PublicKeyCredentialSource
{
if (!array_key_exists(base64_encode($credentialId), $this->credentials)) {
return null;
}

return $this->credentials[base64_encode($credentialId)];
}

public function save(PublicKeyCredentialSource $publicKeyCredentialSource): void
{
$this->credentials[base64_encode($publicKeyCredentialSource->getPublicKeyCredentialId())] = $publicKeyCredentialSource;
}

public function has(string $credentialId): bool
{
return null !== $this->find($credentialId);
}

public function get(string $credentialId): AttestedCredentialData
{
$credential = $this->find($credentialId);
if (null === $credential) {
throw new \InvalidArgumentException('Invalid credential ID');
}

return $credential->getAttestedCredentialData();
}

public function getUserHandleFor(string $credentialId): string
{
$credential = $this->find($credentialId);
if (null === $credential) {
throw new \InvalidArgumentException('Invalid credential ID');
}

return $credential->getUserHandle();
}

public function getCounterFor(string $credentialId): int
{
$credential = $this->find($credentialId);
if (null === $credential) {
throw new \InvalidArgumentException('Invalid credential ID');
}

return $credential->getCounter();
}

public function updateCounterFor(string $credentialId, int $newCounter): void
{
$credential = $this->find($credentialId);
if (null === $credential) {
throw new \InvalidArgumentException('Invalid credential ID');
}

$credential->setCounter($newCounter);
$this->save($credential);
}
}
2 changes: 2 additions & 0 deletions src/symfony/src/DependencyInjection/WebauthnExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ public function prepend(ContainerBuilder $container): void
}
$config['dbal']['types'] += [
'attested_credential_data' => DbalType\AttestedCredentialDataType::class,
'base64' => DbalType\Base64BinaryDataType::class,
'public_key_credential_descriptor' => DbalType\PublicKeyCredentialDescriptorType::class,
'public_key_credential_descriptor_collection' => DbalType\PublicKeyCredentialDescriptorCollectionType::class,
'trust_path' => DbalType\TrustPathDataType::class,
];
$container->prependExtensionConfig('doctrine', $config);
}
Expand Down
52 changes: 52 additions & 0 deletions src/symfony/src/Doctrine/Type/Base64BinaryDataType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2018 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

namespace Webauthn\Bundle\Doctrine\Type;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;

final class Base64BinaryDataType extends Type
{
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return base64_encode($value);
}

/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return \Safe\base64_decode($value, true);
}

/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
}

/**
* {@inheritdoc}
*/
public function getName()
{
return 'base64';
}
}
Loading

0 comments on commit 09f3efa

Please sign in to comment.