Skip to content

Commit

Permalink
Merge pull request #87 from basz/prepare-0.8.0-beta1
Browse files Browse the repository at this point in the history
release prep
  • Loading branch information
basz authored Feb 26, 2017
2 parents 31a10d2 + e418016 commit 470eea7
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 135 deletions.
41 changes: 21 additions & 20 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
# Changelog

## v0.8.0

* ZfrOAuth2Server now integrates with [Zend\Stratigility](https://github.com/zendframework/zend-stratigility), and provide simple
middlewares to cover authorization and authentication. This is entirely optional.

This is achieved through two middlewares that implement `Zend\Stratigility\MiddlewareInterface`:

- `ZfrOAuth2\Server\AuthorizationServerMiddleware`: when piped, it will add three endpoints (`/authorize`, `/token`, `/revoke`) that
handle the creation of token, revocation...
- `ZfrOAuth2\Server\ResourceServerMiddleware`: if you are using `Zend\Expressive`, that's a middleware that you could attach as
a `pre_routing` middleware. What it does is inspecting the request, and extracting the token, and set it as the `oauth_token` attribute

* [BC] `deleteExpiredTokens` has been removed from the TokenService. The reason is that it relied on `Selectable` Doctrine's interface, and
couldn't take advantage of batch optimization deletions in database. You should instead use a more reliable and efficient way to delete
expired tokens (either through a CRON task, or database scheduling manager).

* [BC] The `isTokenValid` method has been removed from the ResourceServer. Use the `isValid` method from the token instead.

* Tokens now have a `isValid` method to check if a given token (either authorization, access or refresh) is valid against
some scopes.
## v0.8.0-beta1

BC! Pre release of a completely rewritten library. It focusses on core OAuth2 functionality and has been decoupled from persistence. If you still need the previous implementation - which is considered EOL - see the [legacy-0.7](https://github.com/zf-fr/zfr-oauth2-server/tree/legacy-0.7) branch

* PHP7+ only
* 100% test coverage
* Uses [Zend\Diactoros](https://github.com/zendframework/zend-diactoros) to generate [PSR-7 (Http Message)](https://github.com/php-fig/http-message) implementation.
* Uses [PSR-11 (Container)](https://github.com/php-fig/container) for dependency injection containers.
* Eventing has been removed
* Persistence has been decoupled, see our doctrine integration [ZfrOAuth2ServerDoctrine](https://github.com/zf-fr/zfr-oauth2-server-doctrine)
* Provides 5 Services
* ZfrOAuth2\Server\Service\AccessTokenService
* ZfrOAuth2\Server\Service\AuthorizationCodeService
* ZfrOAuth2\Server\Service\ClientService
* ZfrOAuth2\Server\Service\RefreshTokenService
* ZfrOAuth2\Server\Service\ScopeService
* Provides 4 PSR7 Middleware's which are really nice but optional
* ZfrOAuth2\Server\AuthorizationServerMiddleware
* ZfrOAuth2\Server\ResourceServerMiddleware
* ZfrOAuth2\Server\RevocationRequestMiddleware
* ZfrOAuth2\Server\TokenRequestMiddleware

## v0.7.1

Expand Down
197 changes: 85 additions & 112 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,27 @@ Here are other OAuth2 library you can use:

## Versioning note

Please note that until I reach 1.0, I **WILL NOT** follow semantic version. This means that BC can occur between
0.1.x and 0.2.x releases. If you are using this in production, please set your dependency using 0.1.*, for instance.
Please note that until we reach 1.0, we **WILL NOT** follow semantic version. This means that BC can occur between
0.1.x and 0.2.x releases.

The current pre release of a completely rewritten version, is it not copatible with the previous implementation - which is considered EOL - see the [legacy-0.7](https://github.com/zf-fr/zfr-oauth2-server/tree/legacy-0.7) branch.

See the [CHANGELOG](CHANGELOG.md)

## Installation

Installation is only officially supported using Composer:
use Composer to install:

```sh
php composer.phar require zfr/zfr-oauth2-server:^1.0
php composer.phar require zfr/zfr-oauth2-server:^0.8-beta
```

## Support

- File issues at [https://github.com/zf-fr/zfr-oauth2-server/issues](https://github.com/zf-fr/zfr-oauth2-server/issues).
- Say hello in our [gitter](https://gitter.im/prolic/zfr-oauth2-server) chat.

### Configuration
## Configuration

Several Apache modules will strip HTTP authorization headers such as `Authorization` to try to enhance security by preventing scripts from seeing sensitive information unless the developer explicitly enables this.

Expand All @@ -62,22 +66,11 @@ CGIPassAuth on
since: [Apache 2.4.13](https://httpd.apache.org/docs/trunk/mod/core.html#cgipassauth)



## Framework integration

Because of its strict dependency injection architecture, ZfrOAuth2Server is hardly usable alone, as it requires
quite a lot of configuration. However, I've made a Zend Framework 2 module that abstract the whole configuration,
and make it very easy to use:

* [Zend Framework 2 module](https://github.com/zf-fr/zfr-oauth2-server-module)

If anyone want to help with a Symfony 2 bundle, I'd be glad to help.

## Documentation

ZfrOAuth2Server is based on the [RFC 6749](http://tools.ietf.org/html/rfc6749) documentation.

### Why using OAuth2?
### Why use OAuth2?

OAuth2 is an authentication/authorization system that allows that can be used to:

Expand All @@ -86,7 +79,7 @@ OAuth2 is an authentication/authorization system that allows that can be used to
* Securing your application through the use of scopes

OAuth2 is a dense, extensible specification that can be used for a wide number of use-cases. As of today,
ZfrOAuth2Server implements three of the four official grants: AuthorizationGrant, ClientCredentialsGrant, PasswordGrant.
ZfrOAuth2Server implements three of the four official grants: AuthorizationGrant, ClientCredentialsGrant, PasswordGrant. Additionally a RefreshTokenGrant is provided to obtain new access tokens. ImplicitGrant and JWTTokens are forthcoming (help wanted).

### How OAuth2 works?

Expand Down Expand Up @@ -148,6 +141,64 @@ $user = new User(); // must implement TokenOwnerInterface
$response = $authorizationServer->handleRequest($request, $user);
```

The AuthorizationServerMiddleware is able to do this for you and retrieve a user instance from a (configurable) request attribute. It is up to you to provide middleware which runs with a higher priority to add a TokenOwnerInterface instance to the request attribute.

Example of such a implementation which uses ZendAuthentication and a TemplateRenderer from ZendExpressive.

```
final class OAuth2AuthorizationFlow
{
/**
* @var AuthenticationService
*/
private $authenticationService;
/**
* @var ClientService
*/
private $clientService;
/**
* @var TemplateRendererInterface
*/
private $template;
public function __construct(
AuthenticationService $authenticationService,
ClientService $clientService,
TemplateRendererInterface $template
) {
$this->authenticationService = $authenticationService;
$this->clientService = $clientService;
$this->template = $template;
}
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out = null)
{
if ($this->authenticationService->hasIdentity()) {
$request = $request->withAttribute('owner', $this->authenticationService->getIdentity());
}
if ($request->getMethod() === 'POST') {
$post = $request->getParsedBody();
$approved = filter_var($post['approved'], FILTER_VALIDATE_BOOLEAN);
if ($approved) {
return $out($request, $response);
}
}
$data = [];
$query = $request->getUri()->getQuery();
parse_str($query, $data['query']);
$data['client'] = $this->clientService->getClient($data['query']['client_id']);
return new HtmlResponse($this->template->render('app::oauth2/authorize-request', $data));
}
}
```

#### Revoking a token

ZfrOAuth2Server supports revoking access and refresh tokens using the [RFC 7009 specification](https://tools.ietf.org/html/rfc7009).
Expand Down Expand Up @@ -179,104 +230,26 @@ if (!$token = $resourceServer->getAccessToken($request, ['write']) {
}
```

### Persistence layer

As of version 1.0 ZfrOAuth2Server has been rewritten to be persistence layer agnostic. Meaning it can by used with any prefered persistence layer.

Currently these packages provide a persistence layer;

- [ZfrOAuth2ServerDoctrine](https://github.com/zf-fr/zfr-oauth2-server-doctrine) for Doctrine 2

The ResourceServerMiddleware is able to do this for you, simply have it run before any other middleware.

### Event manager
Example zend expressive route configuration.

There are a lot of use cases where you would like to execute specific code when a token is created (or when it
could not be created). Such use cases include: log login, modify generic OAuth2 response to include additional fields...

To that extent, ZfrOAuth2 trigger various events in the `AuthorizationServer`. Four events are triggered:

* `ZfrOAuth2\Server\Event\AuthorizationCodeEvent::EVENT_CODE_CREATED`: event that is triggered when the auth code has
been properly created and persisted.
* `ZfrOAuth2\Server\Event\AuthorizationCodeEvent::EVENT_CODE_FAILED`: event that is triggered when an error has occurred (
wrong credentials, missing grant...).
* `ZfrOAuth2\Server\Event\TokenEvent::EVENT_TOKEN_CREATED`: event that is triggered when the access token has
been properly created and persisted.
* `ZfrOAuth2\Server\Event\TokenEvent::EVENT_TOKEN_FAILED`: event that is triggered when an error has occurred (
wrong credentials, missing grant...).

In both cases, the `TokenEvent` or `AuthorizationCodeEvent` event lets you access to the request, the response body
and the access token/authorization code (if available).

Here is an example:

#### Zend Framework 2 users

Zend Framework 2 users can take advantage of the shared event manager, and attach listeners in their Module.php
class as shown below:

```php
use ZfrOAuth2\Server\Event\TokenEvent;

class Module
{
public function onBootstrap(EventInterface $event)
{
/* @var \Zend\Mvc\Application $application */
$application = $event->getTarget();
$eventManager = $application->getEventManager();
$sharedManager = $eventManager->getSharedManager();

$sharedManager->attach(
'ZfrOAuth2\Server\AuthorizationServer',
TokenEvent::EVENT_TOKEN_CREATED,
[$this, 'tokenCreated']
);

$sharedManager->attach(
'ZfrOAuth2\Server\AuthorizationServer',
TokenEvent::EVENT_TOKEN_FAILED,
[$this, 'tokenFailed']
);
}

public function tokenCreated(TokenEvent $event)
{
// Get the response
$response = $event->getResponse();
// ...

// Response is a PSR-7 compliant response, so you modify it
$response = $response->withHeader(...);

// Do not forget to set back the response, as PSR-7 are immutable
$event->setResponse($response);
}

public function tokenFailed(TokenEvent $event)
{
// We can inspect the response to know what happen and log the failure
$body = $event->getResponse()->getBody();
}
}
```
[
'name' => 'command::commerce::create-store',
'path' => '/commerce/create-store',
'middleware' => [
ResourceServerMiddleware::class,
MyActionMiddleware::class,
],
'allowed_methods' => ['OPTIONS', 'POST'],
],
```

#### Other users

For other users, you can manually retrieve the event manager from the authorization server, and attach
your listener there:

```php
use ZfrOAuth2\Server\Event\TokenEvent;

$eventManager = $authorizationServer->getEventManager();
$eventManager->attach(TokenEvent::EVENT_TOKEN_CREATED, function(TokenEvent $event) {
// Do things
}
```
### Persistence layer

You are responsible to wire everything in your application.
As of version 0.8-beta1 ZfrOAuth2Server has been rewritten to be persistence layer agnostic. Meaning it can by used with any prefered persistence layer.

#### Second level cache
Currently these packages provide a persistence layer;

Scope and tokens are marked cacheable to take advantage of Doctrine 2.5 ORM second level cache. However, you
need to configure the regions yourself.
- [ZfrOAuth2ServerDoctrine](https://github.com/zf-fr/zfr-oauth2-server-doctrine) for Doctrine 2
17 changes: 14 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,24 @@
"name": "Michaël Gallego",
"email": "[email protected]",
"homepage": "http://www.michaelgallego.fr"
},
{
"name": "Bas Kamer",
"email": "[email protected]",
"homepage": "https://baskamer.nl"
}
],
"require": {
"php": ">=7.0",
"php": "^7.0",
"zendframework/zend-diactoros": "^1.1",
"psr/container": "^1.0",
"ramsey/uuid": "^3.1"
"ramsey/uuid": "^3.1",
"roave/security-advisories": "dev-master"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.1",
"phpunit/phpunit": "^6.0",
"satooshi/php-coveralls": "~1.0"
"satooshi/php-coveralls": "^1.0"
},
"autoload": {
"psr-4": {
Expand All @@ -36,5 +42,10 @@
"psr-4": {
"ZfrOAuth2Test\\Server\\": "tests/src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "0.9-dev"
}
}
}

0 comments on commit 470eea7

Please sign in to comment.