Skip to content

Commit 5f6f6c7

Browse files
authored
Merge pull request #10 from RobDWaller/0.3.0
0.3.0
2 parents 3d70bba + edac183 commit 5f6f6c7

32 files changed

+758
-360
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ vendor
33
coverage
44
infection.log
55
coverage.xml
6+
Dockerfile
7+
docker-compose.yml

README.md

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# PSR Compliant JSON Web Token Middleware
22
[![Build Status](https://travis-ci.org/RobDWaller/psr-jwt.svg?branch=master)](https://travis-ci.org/RobDWaller/psr-jwt) [![codecov](https://codecov.io/gh/RobDWaller/psr-jwt/branch/master/graph/badge.svg)](https://codecov.io/gh/RobDWaller/psr-jwt) [![Infection MSI](https://badge.stryker-mutator.io/github.com/RobDWaller/psr-jwt/master)](https://infection.github.io) [![StyleCI](https://github.styleci.io/repos/167511682/shield?branch=master)](https://github.styleci.io/repos/167511682) [![Latest Stable Version](https://poser.pugx.org/rbdwllr/psr-jwt/v/stable)](https://packagist.org/packages/rbdwllr/psr-jwt) ![PHP Version Support](https://img.shields.io/travis/php-v/RobDWaller/psr-jwt/master)
33

4-
A [PSR-7](https://www.php-fig.org/psr/psr-7/) and [PSR-15](https://www.php-fig.org/psr/psr-15/) compliant JSON Web Token middleware library built on top of [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT).
4+
PSR-JWT is a middleware library which allows you to authorise JSON Web Tokens contained in a web request. It is [PSR-7](https://www.php-fig.org/psr/psr-7/) and [PSR-15](https://www.php-fig.org/psr/psr-15/) compliant and built on top of [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT).
55

6-
The library allows you to create JSON Web Tokens and then validate them using PSR-15 compliant middleware which can be added to compatible frameworks such as [Slim PHP](http://www.slimframework.com/) and [Zend Expressive](https://docs.zendframework.com/zend-expressive/).
6+
The library also allows you to generate JSON Web Tokens and the PSR-7 PSR-15 compliant middleware can be added to any compatible framework, such as [Slim PHP](http://www.slimframework.com/).
77

88
For more information on JSON Web Tokens please read [RFC 7519](https://tools.ietf.org/html/rfc7519). Also to learn more about how to pass JSON Web Tokens to web applications please read up on bearer token authorisation in [RFC 6750](https://tools.ietf.org/html/rfc6750).
99

@@ -12,9 +12,9 @@ For more information on JSON Web Tokens please read [RFC 7519](https://tools.iet
1212
- [Setup](#setup)
1313
- [Basic Usage](#basic-usage)
1414
- [Slim PHP Example Implementation](#slim-php-example-implementation)
15-
- [Zend Expressive Example Implementation](#zend-expressive-example-implementation)
16-
- [JSON Response Handler](#json-response-handler)
1715
- [Generate JSON Web Token](#generate-json-web-token)
16+
- [Parse and Validate JSON Web Token](#parse-and-validate-json-web-token)
17+
- [Retrieve Token From the Request](retrieve-token-from-the-request)
1818
- [Advanced Usage](#advanced-usage)
1919
- [Handlers](#handlers)
2020
- [Create Custom Handler](#create-custom-handler)
@@ -23,7 +23,7 @@ For more information on JSON Web Tokens please read [RFC 7519](https://tools.iet
2323

2424
To install this package you will need to install [Composer](https://getcomposer.org/) and then run `composer init`. Once this is done you can install the package via the command line or by editing the composer.json file created by the `composer init` command.
2525

26-
Finally you will need to reference the composer autoloader in your PHP code, `require 'vendor/autoload.php';`. The location of the autoload file will differ dependent on where your code is run. Also you will not need to reference the autoload file if you are using a framework like Zend Expressive.
26+
Finally you will need to reference the Composer autoloader in your PHP code, `require 'vendor/autoload.php';`. The location of the autoload file will differ dependent on where your code is run. Note, some frameworks already have the autoload file referenced for you.
2727

2828
**Install via Composer on the command line:**
2929

@@ -35,31 +35,31 @@ composer require rbdwllr/psr-jwt
3535

3636
```javascript
3737
"require": {
38-
"rbdwllr/psr-jwt": "^0.2"
38+
"rbdwllr/psr-jwt": "^0.3"
3939
}
4040
```
4141

4242
## Basic Usage
4343

44-
PsrJwt can be used with any PSR-7 / PSR-15 compliant framework. Just call one of the middleware factory methods and they will return a middleware instance that exposes two methods, `__invoke()` and `process()`. The latter will work with PSR-15 compliant frameworks like Zend Expressive and the former will work with older PSR-7 compliant frameworks like Slim PHP v3.
44+
PsrJwt can be used with any PSR-7 / PSR-15 compliant framework. Just call one of the middleware factory methods and they will return a middleware instance that exposes two methods, `__invoke()` and `process()`. The latter will work with PSR-15 compliant frameworks and the former will work with older PSR-7 compliant frameworks.
4545

4646
```php
47-
// Will generate a text/html response if JWT authentication fails.
47+
// Will generate a text/html response if JWT authorisation fails.
4848
\PsrJwt\Factory\JwtMiddleware::html('secret', 'tokenKey', 'body');
4949

50-
// Will generate an application/json response if JWT authentication fails.
50+
// Will generate an application/json response if JWT authorisation fails.
5151
\PsrJwt\Factory\JwtMiddleware::json('secret', 'tokenKey', ['body']);
5252
```
5353

54-
The `secret` is the string required to hash the JSON Web Token signature.
54+
**Secret:** is the string required to hash the JSON Web Token signature.
5555

56-
The `tokenKey` is the key required to retrieve the JSON Web Token from a cookie, query parameter or the request body. By default though the library looks for tokens in the bearer field of the authorization header.
56+
**Token Key:** is the key required to retrieve the JSON Web Token from a cookie, query parameter or the request body. By default though the library looks for tokens in the bearer field of the authorization header. If you use the bearer field you can pass an empty string for the token key `''`.
5757

58-
The `body` is the body content you would like to return in the response if authentication fails. For example, `<h1>Authentication Failed!</h1>`.
58+
**Body:** is the body content you would like to return in the response if authorisation fails. For example, `<h1>Authorisation Failed!</h1>`.
5959

6060
### Slim PHP Example Implementation
6161

62-
To implement the middleware in Slim PHP 3.0 you can use the code below.
62+
To add the middleware to a route in Slim PHP you can use the code below.
6363

6464
```php
6565
// Can be added to any routes file in Slim, often index.php.
@@ -69,35 +69,84 @@ $app->get('/jwt', function (Request $request, Response $response) {
6969
$response->getBody()->write("JSON Web Token is Valid!");
7070

7171
return $response;
72-
})->add(\PsrJwt\Factory\JwtMiddleware::html('Secret123!456$', 'jwt', 'Authentication Failed'));
72+
})->add(\PsrJwt\Factory\JwtMiddleware::html('Secret123!456$', 'jwt', 'Authorisation Failed'));
7373
```
7474

75-
### Zend Expressive Example Implementation
75+
### Generate a JSON Web Token
76+
77+
To generate JSON Web Tokens PsrJwt offers a wrapper for the library [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT). You can create an instance of the ReallySimpleJWT builder by calling the built in factory method.
7678

7779
```php
78-
// Add to the config/pipeline.php file.
79-
$app->pipe('/api', \PsrJwt\Factory\JwtMiddleware::html('!Secret#1XYZ$', 'jwt', 'Authentication Failed'));
80+
require 'vendor/autoload.php';
81+
82+
$factory = new \PsrJwt\Factory\Jwt();
83+
84+
$builder = $factory->builder();
85+
86+
$token = $builder->setSecret('!secReT$123*')
87+
->setPayloadClaim('uid', 12)
88+
->build();
8089
```
8190

82-
### Generate JSON Web Token
91+
### Parse and Validate JSON Web Token
8392

84-
To generate JSON Web Tokens PsrJwt offers a wrapper for the library [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT). You can create an instance of the ReallySimpleJWT builder by calling the built in factory method.
93+
If for some reason you need to parse or validate a token outside of the normal middleware authorisation flow the JWT factory class provides a parser method.
94+
95+
This will return an instance of the Really Simple JWT Parse class which provides token parsing and validation functionality.
8596

8697
```php
8798
require 'vendor/autoload.php';
8899

89-
\PsrJwt\Factory\Jwt::builder();
100+
$factory = new \PsrJwt\Factory\Jwt();
101+
102+
$parser = $factory->parse('token', 'secret');
103+
104+
$parser->validate();
105+
106+
$parser->parse();
90107
```
91108

92-
For more information on creating tokens please read the [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT/blob/master/readme.md) documentation.
109+
For more information on creating, parsing and validating tokens please read the [ReallySimpleJWT](https://github.com/RobDWaller/ReallySimpleJWT/blob/master/readme.md) documentation.
110+
111+
### Retrieve Token From the Request
112+
113+
If you would like to retrieve the JSON Web Token from the request outside of the normal middleware authorisation flow you can use the request helper class.
114+
115+
It allows you to retrive the token itself or just access the token's payload or header.
116+
117+
```php
118+
require 'vendor/autoload.php';
119+
120+
use PsrJwt\Helper\Request;
121+
122+
$helper = new Request();
123+
124+
// Will return a ReallySimpleJWT Parsed object.
125+
$helper->getParsedToken($request, $tokenKey);
126+
127+
// Return the token header as an array.
128+
$helper->getTokenHeader($request, $tokenKey);
129+
130+
// Return the token payload as an array.
131+
$helper->getTokenPayload($request, $tokenKey);
132+
```
93133

94134
## Advanced Usage
95135

96-
You don't have to use the factory methods explained above to generate the JWT authentication middleware you can call all the required classes directly. This allows you to configure a more customised setup and use your own handlers.
136+
You don't have to use the factory methods explained above to generate the JWT authorisation middleware you can instantiate all the required classes directly. This allows you to configure a custom setup.
137+
138+
```php
139+
use PsrJwt\Handler\Html;
140+
use PsrJwt\JwtAuthMiddleware;
141+
142+
$htmlHandler = new Html($secret, $tokenKey, $body);
143+
144+
$middleware = new JwtAuthMiddleware($htmlHandler);
145+
```
97146

98147
### Handlers
99148

100-
PsrJwt is built to work with any PSR 15 compliant handler. As standard it comes with two built in handlers, one which returns text/html responses and another which returns application/json responses.
149+
PsrJwt is built to work with any PSR-15 compliant handler. As standard it comes with two built in handlers, one which returns text/html responses and another which returns application/json responses.
101150

102151
You can use these handlers simply by instantiating them and passing them to the PsrJwt middleware.
103152

@@ -106,27 +155,28 @@ You can use these handlers simply by instantiating them and passing them to the
106155
use PsrJwt\Handler\Json;
107156
use PsrJwt\JwtAuthMiddleware;
108157

158+
// The handler.
159+
$jsonHandler = new Json($secret, $tokenKey, $body);
109160

110-
$auth = new Json($secret, $tokenKey, $body);
111-
112-
$middleware = new JwtAuthMiddleware($auth);
161+
// The middleware.
162+
$middleware = new JwtAuthMiddleware($jsonHandler);
113163
```
114164

115165
### Create Custom Handler
116166

117167
To create your own handler you need to do two things. First create a class which implements the `Psr\Http\Server\RequestHandlerInterface` [interface](https://www.php-fig.org/psr/psr-15/). This requires you create a `handle()` method which consumes a `Psr\Http\Message\ServerRequestInterface` object and returns a `Psr\Http\Message\ResponseInterface` object.
118168

119-
Next you will need to extend the `PsrJwt\Auth\Authenticate` class as this will give you access to the JSON Web Token authentication functionality. Once this is done you will be able to pass your handler to the `PsrJwt\JwtAuthMiddleware` class and then integrate it with your desired framework.
169+
Next you will need to extend the `PsrJwt\Auth\Authorise` class as this will give you access to the JSON Web Token authorisation functionality. Once this is done you will be able to pass your handler to the `PsrJwt\JwtAuthMiddleware` class and then integrate it with your desired framework.
120170

121171
```php
122-
// An example JWT Authentication Handler.
123-
use PsrJwt\Auth\Authenticate;
172+
// An example JWT Authorisation Handler.
173+
use PsrJwt\Auth\Authorise;
124174
use Psr\Http\Server\RequestHandlerInterface;
125175
use Psr\Http\Message\ResponseInterface;
126176
use Psr\Http\Message\ServerRequestInterface;
127177
use Nyholm\Psr7\Response;
128178

129-
class MyHandler extends Authenticate implements RequestHandlerInterface
179+
class MyHandler extends Authorise implements RequestHandlerInterface
130180
{
131181
public function __construct(string $secret, string $tokenKey)
132182
{
@@ -135,7 +185,7 @@ class MyHandler extends Authenticate implements RequestHandlerInterface
135185

136186
public function handle(ServerRequestInterface $request): ResponseInterface
137187
{
138-
$auth = $this->authenticate($request);
188+
$auth = $this->authorise($request);
139189

140190
return new Response(
141191
$auth->getCode(),

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rbdwllr/psr-jwt",
33
"description": "A PSR 7 compliant JSON Web Token Middleware Library.",
4-
"keywords": ["jwt", "json", "tokens", "authentication", "json web tokens", "php", "psr-7"],
4+
"keywords": ["jwt", "json", "tokens", "authentication", "authorisation", "json web tokens", "php", "psr-7"],
55
"type": "library",
66
"license": "MIT",
77
"authors": [
@@ -19,8 +19,8 @@
1919
},
2020
"require-dev": {
2121
"phpunit/phpunit": "^7.0",
22-
"phpstan/phpstan": "^0.10",
23-
"phpstan/phpstan-mockery": "^0.10",
22+
"phpstan/phpstan": "^0.11",
23+
"phpstan/phpstan-mockery": "^0.11",
2424
"phpmd/phpmd": "2.6.*",
2525
"squizlabs/php_codesniffer": "^3.0",
2626
"mockery/mockery": "^1.2",

src/Auth/Auth.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
namespace PsrJwt\Auth;
66

77
/**
8-
* Tell the middleware what the status code and reason phrase should be based
9-
* on completing the JWT authentication process.
8+
* Tell the middleware what the status code and reason phrase are when the JWT
9+
* authorisation process is complete.
1010
*/
1111
class Auth
1212
{
@@ -32,7 +32,7 @@ public function __construct(int $code, string $message)
3232
}
3333

3434
/**
35-
* Return the status code based on token authentication
35+
* Return the status code based on token authorisation.
3636
*
3737
* @return int
3838
*/
@@ -42,7 +42,7 @@ public function getCode(): int
4242
}
4343

4444
/**
45-
* Return the reason phrase based on token authentication
45+
* Return the reason phrase based on token authorisation.
4646
*
4747
* @return string
4848
*/
Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
namespace PsrJwt\Auth;
66

77
use Psr\Http\Message\ServerRequestInterface;
8-
use ReallySimpleJWT\Exception\ValidateException;
98
use PsrJwt\Factory\Jwt;
109
use PsrJwt\Auth\Auth;
1110
use PsrJwt\Parser\Parse;
11+
use PsrJwt\Parser\Request;
12+
use PsrJwt\Parser\ParseException;
1213
use PsrJwt\Validation\Validate;
1314

1415
/**
1516
* Retrieve the JSON Web Token from the request and attempt to parse and
1617
* validate it.
1718
*/
18-
class Authenticate
19+
class Authorise
1920
{
2021
/**
2122
* The secret required to parse and validate the JWT.
@@ -25,7 +26,7 @@ class Authenticate
2526
private $secret;
2627

2728
/**
28-
* Define under what key the JWT can be found in the request.
29+
* Define which key the JWT can be found under in the request.
2930
*
3031
* @var string $tokenKey
3132
*/
@@ -48,27 +49,29 @@ public function __construct(string $secret, string $tokenKey)
4849
* @param ServerRequestInterface $request
4950
* @return Auth
5051
*/
51-
public function authenticate(ServerRequestInterface $request): Auth
52+
public function authorise(ServerRequestInterface $request): Auth
5253
{
5354
try {
5455
$token = $this->getToken($request);
55-
} catch (ValidateException $e) {
56+
} catch (ParseException $e) {
5657
return new Auth(400, 'Bad Request: ' . $e->getMessage());
5758
}
5859

5960
return $this->validate($token);
6061
}
6162

6263
/**
63-
* Check the token will parse, the signature is valid, it is ready to use,
64-
* and it has not expired.
64+
* Check the token will parse, the signature is valid, the token is ready
65+
* to use, and it has not expired.
6566
*
6667
* @param string $token
6768
* @return Auth
6869
*/
6970
private function validate(string $token): Auth
7071
{
71-
$parse = Jwt::parser($token, $this->secret);
72+
$jwt = new Jwt();
73+
74+
$parse = $jwt->parser($token, $this->secret);
7275

7376
$validate = new Validate($parse);
7477

@@ -83,7 +86,7 @@ private function validate(string $token): Auth
8386
}
8487

8588
/**
86-
* The authentication can respond as Ok or Unauthorized.
89+
* The authorisation process can respond as 200 Ok or 401 Unauthorized.
8790
*
8891
* @param int $code
8992
* @param string $message
@@ -98,40 +101,18 @@ private function validationResponse(int $code, string $message): Auth
98101
return new Auth(200, 'Ok');
99102
}
100103

101-
/**
102-
* The token found in the request should not be empty.
103-
*
104-
* @param string $token
105-
* @return bool
106-
*/
107-
private function hasJwt(string $token): bool
108-
{
109-
return !empty($token);
110-
}
111-
112104
/**
113105
* Find the token in the request. Ideally the token should be passed as
114106
* a bearer token in the authorization header. Passing the token via
115107
* query parameters is the least advisable option.
116108
*
117109
* @param ServerRequestInterface $request
118110
* @return string
119-
* @throws ValidateException
120111
*/
121112
private function getToken(ServerRequestInterface $request): string
122113
{
123-
$parse = new Parse(['token_key' => $this->tokenKey]);
124-
$parse->addParser(\PsrJwt\Parser\Bearer::class);
125-
$parse->addParser(\PsrJwt\Parser\Cookie::class);
126-
$parse->addParser(\PsrJwt\Parser\Body::class);
127-
$parse->addParser(\PsrJwt\Parser\Query::class);
128-
129-
$token = $parse->findToken($request);
130-
131-
if ($this->hasJwt($token)) {
132-
return $token;
133-
}
114+
$parseRequest = new Request(new Parse());
134115

135-
throw new ValidateException('JSON Web Token not set.', 11);
116+
return $parseRequest->parse($request, $this->tokenKey);
136117
}
137118
}

0 commit comments

Comments
 (0)