Skip to content

Commit

Permalink
Merge pull request #22 from gepo/extendability
Browse files Browse the repository at this point in the history
Allows user to use custom user provider
  • Loading branch information
cryptiklemur committed Jun 13, 2015
2 parents b7a55bb + e89cfb7 commit e0b8c8a
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 28 deletions.
40 changes: 36 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ ApiKey Bundle

Creates an avenue for using ApiKey authentication for Symfony2. Requires FOSUserBundle.

## Installation
# Installation

Requires composer, install as follows

```sh
composer require uecode/api-key-bundle dev-master
```

#### Enable Bundle
## Enable Bundle

Place in your `AppKernel.php` to enable the bundle

Expand All @@ -36,14 +36,23 @@ uecode_api_key:
parameter_name: some_value # defaults to `api_key`
```
### Update user provider
This bundle provides two ways to work with User model:
1. use model and user provider provided by this bundle
2. use custom user provider
### Use model provided by this bundle
#### Entities
Assuming you already have a `User` class that extends the `FOSUserBundle`'s base user model,
change that extend, so its extending `Uecode\Bundle\ApiKeyBundle\Model\ApiKeyUser`

Then update your schema.

#### Set up security
#### Change used user provider

In your security, change your provider to the service `uecode.api_key.provider.user_provider`

Expand All @@ -64,7 +73,30 @@ security:
id: uecode.api_key.provider.user_provider
```

After adding that, you can now add `api_key: true`, and `stateless: true` to any of your firewalls.

### Use custom user provider

To work with this bundle your user provider should implement ```ApiKeyUserProviderInterface```.
It consist of one method for loading user by their apiKey.
You should implement this interface for user provider which used in your api firewall:

```php
use Uecode\Bundle\ApiKeyBundle\Security\Authentication\Provider\ApiKeyUserProviderInterface;
class MyCustomUserProvider implements ApiKeyUserProviderInterface {
// ...
public function loadUserByApiKey($apiKey)
{
return $this->userManager->findUserBy(array('apiKey' => $apiKey));
}
}
```

## Change security settings

You can now add `api_key: true`, and `stateless: true` to any of your firewalls.

For Example:

Expand Down
21 changes: 4 additions & 17 deletions src/Uecode/Bundle/ApiKeyBundle/Model/ApiKeyUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,31 @@
use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\Security\Core\User\UserInterface as BaseUserInterface;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Uecode\Bundle\ApiKeyBundle\Util\ApiKeyGenerator;

class ApiKeyUser extends BaseUser implements UserInterface, AdvancedUserInterface, BaseUserInterface
{
protected $apiKey;

public function __construct()
{
$this->generateApiKey();
parent::__construct();
$this->setApiKey(ApiKeyGenerator::generate());
}

/**
* @param mixed $apiKey
* @param string $apiKey
*/
public function setApiKey($apiKey)
{
$this->apiKey = $apiKey;
}

/**
* @return mixed
* @return string
*/
public function getApiKey()
{
return $this->apiKey;
}

/**
* Generates an API Key
*/
public function generateApiKey()
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$apikey = '';
for ($i = 0; $i < 64; $i++) {
$apikey .= $characters[rand(0, strlen($characters) - 1)];
}
$apikey = base64_encode(sha1(uniqid('ue' . rand(rand(), rand())) . $apikey));
$this->apiKey = $apikey;
}
}
7 changes: 6 additions & 1 deletion src/Uecode/Bundle/ApiKeyBundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ parameters:

uecode.api_key.extractor.query.class: Uecode\Bundle\ApiKeyBundle\Extractor\QueryExtractor
uecode.api_key.extractor.header.class: Uecode\Bundle\ApiKeyBundle\Extractor\HeaderExtractor


uecode.api_key.generator.class: Uecode\Bundle\ApiKeyBundle\Util\ApiKeyGenerator

services:
uecode.api_key.provider.user_provider:
class: %uecode.api_key.provider.user_provider.class%
Expand All @@ -25,3 +27,6 @@ services:
class: %uecode.api_key.extractor.header.class%
arguments: [%uecode.api_key.parameter_name%]
public: false
uecode.api_key.generator:
class: %uecode.api_key.generator.class%
public: false
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Security\Core\User\UserProviderInterface;
use FOS\UserBundle\Model\UserInterface;
use Uecode\Bundle\ApiKeyBundle\Security\Authentication\Token\ApiKeyUserToken;
use Uecode\Bundle\ApiKeyBundle\Security\Authentication\Provider\ApiKeyUserProviderInterface;

/**
* @author Aaron Scherer <[email protected]>
Expand Down Expand Up @@ -58,9 +59,9 @@ public function authenticate(TokenInterface $token)
* @return bool|ApiKeyUserToken
* @throws AuthenticationException
*/
protected function doAuth(UserProviderInterface $provider, TokenInterface $token)
protected function doAuth($provider, TokenInterface $token)
{
if (!method_exists($provider, 'loadUserByApiKey')) {
if (! $provider instanceof ApiKeyUserProviderInterface) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
namespace Uecode\Bundle\ApiKeyBundle\Security\Authentication\Provider;

/**
* @author Gennady Telegin <[email protected]>
*/
interface ApiKeyUserProviderInterface
{
/**
* @param string $apiKey
*
* @return UserInterface
*/
public function loadUserByApiKey($apiKey);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
/**
* @author Aaron Scherer <[email protected]>
*/
class UserProvider extends FOSUserProvider
class UserProvider extends FOSUserProvider implements ApiKeyUserProviderInterface
{
/**
* @var bool Stateless Authentication?
*/
private $stateless = false;

/**
* @param $apiKey
*
* @return UserInterface
* {@inheritdoc}
*/
public function loadUserByApiKey($apiKey)
{
Expand Down
29 changes: 29 additions & 0 deletions src/Uecode/Bundle/ApiKeyBundle/Util/ApiKeyGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Uecode\Bundle\ApiKeyBundle\Util;

/**
* @author Gennady Telegin <[email protected]>
*/
class ApiKeyGenerator implements ApiKeyGeneratorInterface
{
private $characterSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
private $apiKeyLength = 64;

public function generateApiKey()
{
return self::generate($this->characterSet, $this->apiKeyLength);
}

public static function generate($characterSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $apiKeyLength = 64)
{
$characterSetLength = strlen($characterSet);

$apikey = '';
for ($i = 0; $i < $apiKeyLength; ++$i) {
$apikey .= $characterSet[rand(0, $characterSetLength - 1)];
}

return rtrim(base64_encode(sha1(uniqid('ue' . rand(rand(), rand())) . $apikey)), '=');
}
}
11 changes: 11 additions & 0 deletions src/Uecode/Bundle/ApiKeyBundle/Util/ApiKeyGeneratorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Uecode\Bundle\ApiKeyBundle\Util;

/**
* @author Gennady Telegin <[email protected]>
*/
interface ApiKeyGeneratorInterface
{
public function generateApiKey();
}

0 comments on commit e0b8c8a

Please sign in to comment.