├── .gitignore ├── example ├── .gitignore ├── .htaccess ├── app │ ├── UnauthorizedException.php │ └── Auth.php ├── composer.json ├── index.php ├── README.md └── composer.lock ├── src ├── TokenAuthentication │ ├── UnauthorizedExceptionInterface.php │ ├── TokenNotFoundException.php │ └── TokenSearch.php └── TokenAuthentication.php ├── composer.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | composer.lock -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | RewriteCond %{REQUEST_FILENAME} !-d 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule . index.php [L] -------------------------------------------------------------------------------- /example/app/UnauthorizedException.php: -------------------------------------------------------------------------------- 1 | 'Dyorg', 23 | 'id' => 1, 24 | 'permisssion' => 'admin' 25 | ]; 26 | 27 | return $user; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dyorg/slim-token-authentication", 3 | "description": "Slim 3.0+ Token Authentication Middleware", 4 | "keywords": [ 5 | "slim", 6 | "middleware", 7 | "token", 8 | "auth", 9 | "authentication", 10 | "authorization" 11 | ], 12 | "homepage": "https://github.com/dyorg/slim-token-authentication", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Dyorg Almeida", 17 | "email": "dyorg@rabbiit.com", 18 | "homepage": "https://rabbiit.com/", 19 | "role": "Developer" 20 | } 21 | ], 22 | "require": { 23 | "php" : ">=5.4.0" 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit" : "~4.6", 27 | "squizlabs/php_codesniffer": "~2.3", 28 | "zendframework/zend-diactoros": "^1.3" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "Slim\\Middleware\\": "src" 33 | } 34 | }, 35 | "autoload-dev": { 36 | "psr-4": { 37 | "Slim\\Middleware\\": "tests" 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2017 Dyorg Almeida 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/index.php: -------------------------------------------------------------------------------- 1 | [ 10 | 'displayErrorDetails' => true 11 | ] 12 | ]; 13 | 14 | $app = new App($config); 15 | 16 | $authenticator = function($request, TokenAuthentication $tokenAuth){ 17 | 18 | /** 19 | * Try find authorization token via header, parameters, cookie or attribute 20 | * If token not found, return response with status 401 (unauthorized) 21 | */ 22 | $token = $tokenAuth->findToken($request); 23 | 24 | /** 25 | * Call authentication logic class 26 | */ 27 | $auth = new \app\Auth(); 28 | 29 | /** 30 | * Verify if token is valid on database 31 | * If token isn't valid, must throw an UnauthorizedExceptionInterface 32 | */ 33 | $auth->getUserByToken($token); 34 | 35 | }; 36 | 37 | /** 38 | * Add token authentication middleware 39 | */ 40 | $app->add(new TokenAuthentication([ 41 | 'path' => '/restrict', 42 | 'authenticator' => $authenticator 43 | ])); 44 | 45 | /** 46 | * Public route example 47 | */ 48 | $app->get('/', function($request, $response){ 49 | $output = ['msg' => 'It is a public area']; 50 | $response->withJson($output, 200, JSON_PRETTY_PRINT); 51 | }); 52 | 53 | /** 54 | * Restrict route example 55 | * Our token is "usertokensecret" 56 | */ 57 | $app->get('/restrict', function($request, $response){ 58 | $output = ['msg' => 'It\'s a restrict area. Token authentication works!']; 59 | $response->withJson($output, 200, JSON_PRETTY_PRINT); 60 | }); 61 | 62 | $app->run(); -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Slim Token Authentication Example 2 | 3 | This is a simple example of how implements token authentication with Slim application. 4 | See complete documentation on [Slim Token Authentication](https://github.com/dyorg/slim-token-authentication). 5 | 6 | ## Installing dependencies 7 | 8 | ```bash 9 | composer update 10 | ``` 11 | 12 | ## Making authentication via header 13 | 14 | On your prompt: 15 | 16 | ```bash 17 | $ curl -i http://localhost/slim-token-authentication/example/restrict -H "Authorization: Bearer usertokensecret" 18 | ``` 19 | 20 | ## Making authentication via query paramater 21 | 22 | On your prompt: 23 | 24 | ```bash 25 | $ curl -i http://localhost/slim-token-authentication/example/restrict?authorization=usertokensecret 26 | ``` 27 | 28 | Instead you can try authentication with parameter via your browser: 29 | 30 | ```bash 31 | http://localhost/slim-token-authentication/example/restrict?authorization=usertokensecret 32 | ``` 33 | 34 | ## Responses 35 | 36 | On success should return something like: 37 | 38 | ```bash 39 | HTTP/1.1 200 OK 40 | Date: Wed, 15 Jun 2016 21:26:09 GMT 41 | Server: Apache/2.4.12 (Win64) OpenSSL/1.0.1m PHP/5.6.9 42 | X-Powered-By: PHP/5.6.9 43 | Content-Length: 59 44 | Content-Type: text/html; charset=UTF-8 45 | 46 | {"msg":"It's a restrict area. Token authentication works!"} 47 | ``` 48 | 49 | With wrong token should return something like: 50 | 51 | ```bash 52 | HTTP/1.1 401 Unauthorized 53 | Date: Wed, 15 Jun 2016 21:28:26 GMT 54 | Server: Apache/2.4.12 (Win64) OpenSSL/1.0.1m PHP/5.6.9 55 | X-Powered-By: PHP/5.6.9 56 | Content-Length: 52 57 | Content-Type: application/json;charset=utf-8 58 | 59 | {"message":"Invalid Token","token":"usertokenwrong"} 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /src/TokenAuthentication/TokenSearch.php: -------------------------------------------------------------------------------- 1 | options = $options; 23 | } 24 | 25 | public function __invoke(Request $request) 26 | { 27 | /** Check for token on header */ 28 | if (isset($this->options['header'])) { 29 | if ($request->hasHeader($this->options['header'])) { 30 | $header = $request->getHeader($this->options['header'])[0]; 31 | if (preg_match($this->options['regex'], $header, $matches)) { 32 | return $matches[1]; 33 | } 34 | } 35 | } 36 | 37 | /** If nothing on header, try query parameters */ 38 | if (isset($this->options['parameter'])) { 39 | if (!empty($request->getQueryParams()[$this->options['parameter']])) 40 | return $request->getQueryParams()[$this->options['parameter']]; 41 | } 42 | 43 | /** If nothing on parameters, try cookies */ 44 | if (isset($this->options['cookie'])) { 45 | $cookie_params = $request->getCookieParams(); 46 | if (!empty($cookie_params[$this->options["cookie"]])) { 47 | return $cookie_params[$this->options["cookie"]]; 48 | }; 49 | } 50 | 51 | /** If nothing until now, check argument as last try */ 52 | if (isset($this->options['argument'])) { 53 | if ($route = $request->getAttribute('route')) { 54 | $argument = $route->getArgument($this->options['argument']); 55 | if (!empty($argument)) { 56 | return $argument; 57 | } 58 | } 59 | } 60 | 61 | throw new TokenNotFoundException('Token not found'); 62 | } 63 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slim Token Authentication 2 | 3 | This is a Token Authentication Middleware for Slim 3.0+. 4 | This middleware was designed to maintain easy to implement token authentication with custom authenticator. 5 | 6 | ## Installing 7 | 8 | Get the latest version with [Composer](http://getcomposer.org "Composer"). 9 | 10 | ```bash 11 | composer require dyorg/slim-token-authentication 12 | ``` 13 | 14 | ## Getting authentication 15 | 16 | Start by creating an `authenticator` function, this function will make the token validation of your application. 17 | When you create a new instance of `TokenAuthentication` you must pass an array with configuration options. 18 | You need setting authenticator and path options for authentication to start working. 19 | 20 | ```php 21 | $authenticator = function($request, TokenAuthentication $tokenAuth){ 22 | 23 | # Search for token on header, parameter, cookie or attribute 24 | $token = $tokenAuth->findToken($request); 25 | 26 | # Your method to make token validation 27 | $user = User::auth_token($token); 28 | 29 | # If occured ok authentication continue to route 30 | # before end you can storage the user informations or whatever 31 | ... 32 | 33 | }; 34 | 35 | $app = new App(); 36 | 37 | $app->add(new TokenAuthentication([ 38 | 'path' => '/api', 39 | 'authenticator' => $authenticator 40 | ])); 41 | ``` 42 | 43 | ### Find Token 44 | 45 | This middleware contains the method `findToken()`, you can access it from your authenticator method through the second param (`TokenAuthentication` instance). 46 | This method is able to search for authentication token on header, parameter, cookie or attribute. 47 | You can configure it through options settings. 48 | 49 | ## Configuration Options 50 | 51 | ### Path 52 | 53 | By default no route requires authentication. 54 | You must set one or more routes to be restricted by authentication, setting it on `path` option. 55 | 56 | ```php 57 | ... 58 | 59 | $app = new App(); 60 | 61 | $app->add(new TokenAuthentication([ 62 | 'path' => '/api', /* or ['/api', '/docs'] */ 63 | 'authenticator' => $authenticator 64 | ])); 65 | ``` 66 | 67 | ### Passthrough 68 | 69 | You can configure which routes do not require authentication, setting it on `passthrough` option. 70 | 71 | ```php 72 | ... 73 | 74 | $app = new App(); 75 | 76 | $app->add(new TokenAuthentication([ 77 | 'path' => '/api', 78 | 'passthrough' => '/api/auth', /* or ['/api/auth', '/api/test'] */ 79 | 'authenticator' => $authenticator 80 | ])); 81 | ``` 82 | 83 | ### Header 84 | 85 | By default middleware tries to find token from `Authorization` header. You can change header name using `header` option. 86 | Is expected in Authorization header the value format as `Bearer `, it is matched using a regular expression. 87 | If you want to work without token type or with other token type, like `Basic `, 88 | you can change the regular expression pattern setting it on `regex` option. 89 | You can disabled authentication via header by setting `header` option as null. 90 | 91 | ```php 92 | ... 93 | 94 | $app->add(new TokenAuthentication([ 95 | 'path' => '/api', 96 | 'authenticator' => $authenticator, 97 | 'header' => 'Token-Authorization-X', 98 | 'regex' => '/Basic\s+(.*)$/i', /* for without token type can use /\s+(.*)$/i */ 99 | ])); 100 | ``` 101 | 102 | ### Parameter 103 | 104 | If token is not found in header, middleware tries to find `authorization` query parameter. 105 | You can change parameter name using `parameter` option. 106 | You can disable authentication via parameter by setting `parameter` option as null. 107 | 108 | ```php 109 | ... 110 | 111 | $app->add(new TokenAuthentication([ 112 | 'path' => '/api', 113 | 'authenticator' => $authenticator, 114 | 'parameter' => 'token' 115 | ])); 116 | ``` 117 | 118 | ### Cookie 119 | 120 | If token is not found yet, middleware tries to find `authorization` cookie. 121 | You can change cookie name using `cookie` option. 122 | You can disabled authentication via cookie by setting `cookie` option as null. 123 | 124 | ```php 125 | ... 126 | 127 | $app->add(new TokenAuthentication([ 128 | 'path' => '/api', 129 | 'authenticator' => $authenticator, 130 | 'cookie' => 'token' 131 | ])); 132 | ``` 133 | 134 | ### Argument 135 | 136 | As a last resort, middleware tries to find `authorization` argument of route. 137 | You can change argument name using `argument` option. 138 | You can disabled authentication via argument by setting `argument` option as null. 139 | 140 | ```php 141 | ... 142 | 143 | $app->add(new TokenAuthentication([ 144 | 'path' => '/api', 145 | 'authenticator' => $authenticator, 146 | 'argument' => 'token' 147 | ])); 148 | ``` 149 | 150 | ### Error 151 | 152 | By default on ocurred a fail on authentication, is sent a response on json format with a message (`Invalid Token` or `Not found Token`) and with the token (if found), with status `401 Unauthorized`. 153 | You can customize it by setting a callable function on `error` option. 154 | 155 | ```php 156 | ... 157 | 158 | $error = function($request, $response, TokenAuthentication $tokenAuth) { 159 | $output = []; 160 | $output['error'] = [ 161 | 'msg' => $tokenAuth->getResponseMessage(), 162 | 'token' => $tokenAuth->getResponseToken(), 163 | 'status' => 401, 164 | 'error' => true 165 | ]; 166 | return $response->withJson($output, 401); 167 | } 168 | 169 | $app = new App(); 170 | 171 | $app->add(new TokenAuthentication([ 172 | 'path' => '/api', 173 | 'authenticator' => $authenticator 174 | 'error' => $error 175 | ])); 176 | ``` 177 | 178 | This error function is called when `TokenAuthentication` catches a throwable class that implements `UnauthorizedExceptionInterface`. 179 | 180 | ### Secure 181 | 182 | Tokens are essentially passwords. You should treat them as such and you should always use HTTPS. 183 | If the middleware detects insecure usage over HTTP it will return unathorized with a message `Required HTTPS for token authentication`. 184 | This rule is relaxed for requests on localhost. To allow insecure usage you must enable it manually by setting `secure` to false. 185 | 186 | ```php 187 | ... 188 | 189 | $app = new App(); 190 | 191 | $app->add(new TokenAuthentication([ 192 | 'path' => '/api', 193 | 'authenticator' => $authenticator, 194 | 'secure' => false 195 | ])); 196 | ``` 197 | 198 | Alternatively you can list your development host to have `relaxed` security. 199 | 200 | ```php 201 | ... 202 | 203 | $app->add(new TokenAuthentication([ 204 | 'path' => '/api', 205 | 'authenticator' => $authenticator, 206 | 'secure' => true, 207 | 'relaxed' => ['localhost', 'your-app.dev'] 208 | ])); 209 | ``` 210 | 211 | ## Example 212 | 213 | See how use it on [/example](example). 214 | 215 | ## License 216 | 217 | The MIT License (MIT). Please see [License](LICENSE) for more information. 218 | -------------------------------------------------------------------------------- /src/TokenAuthentication.php: -------------------------------------------------------------------------------- 1 | true, 23 | 'relaxed' => ['localhost', '127.0.0.1'], 24 | 'path' => null, 25 | 'passthrough' => null, 26 | 'authenticator' => null, 27 | 'error' => null, 28 | 'header' => 'Authorization', 29 | 'regex' => '/Bearer\s+(.*)$/i', 30 | 'parameter' => 'authorization', 31 | 'cookie' => 'authorization', 32 | 'argument' => 'authorization' 33 | ]; 34 | 35 | private $response = []; 36 | 37 | public function __construct(array $options = []) 38 | { 39 | /** Rewrite options */ 40 | $this->fill($options); 41 | } 42 | 43 | public function __invoke(Request $request, Response $response, $next) 44 | { 45 | $scheme = $request->getUri()->getScheme(); 46 | $host = $request->getUri()->getHost(); 47 | 48 | /** If rules say we should not authenticate call next and return. */ 49 | if (false === $this->shouldAuthenticate($request)) { 50 | return $next($request, $response); 51 | } 52 | 53 | /** HTTP allowed only if secure is false or server is in relaxed array. */ 54 | if ("https" !== $scheme && true === $this->options["secure"]) { 55 | if (!in_array($host, $this->options["relaxed"])) { 56 | return $response->withJson(['message' => 'Required HTTPS for token authentication.'], 401); 57 | } 58 | } 59 | 60 | /** Call custom authenticator function */ 61 | if (empty($this->options['authenticator'])) 62 | throw new \RuntimeException('authenticator option has not been set or it is not callable.'); 63 | 64 | try { 65 | 66 | if ($this->options['authenticator']($request, $this) === false) { 67 | return $this->error($request, $response); 68 | } 69 | 70 | return $next($request, $response); 71 | 72 | } catch (UnauthorizedExceptionInterface $e) { 73 | $this->setResponseMessage($e->getMessage()); 74 | return $this->error($request, $response); 75 | } 76 | } 77 | 78 | private function fill($options = array()) 79 | { 80 | foreach ($options as $key => $value) { 81 | $method = "set" . ucfirst($key); 82 | if (method_exists($this, $method)) { 83 | call_user_func(array($this, $method), $value); 84 | } 85 | } 86 | } 87 | 88 | public function shouldAuthenticate(Request $request) 89 | { 90 | $uri = $request->getUri()->getPath(); 91 | $uri = '/' . trim($uri, '/'); 92 | 93 | /** If request path is matches passthrough should not authenticate. */ 94 | foreach ((array)$this->options["passthrough"] as $passthrough) { 95 | $passthrough = rtrim($passthrough, "/"); 96 | if (preg_match("@^{$passthrough}(/.*)?$@", $uri)) { 97 | return false; 98 | } 99 | } 100 | 101 | /** Otherwise check if path matches and we should authenticate. */ 102 | foreach ((array)$this->options["path"] as $path) { 103 | $path = rtrim($path, "/"); 104 | if (preg_match("@^{$path}(/.*)?$@", $uri)) { 105 | return true; 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | public function error(Request $request, Response $response) 113 | { 114 | /** If exists a custom error function callable, ignore remaining code */ 115 | if (!empty($this->options['error'])) { 116 | 117 | $custom_error_response = $this->options['error']($request, $response, $this); 118 | 119 | if ($custom_error_response instanceof Response) { 120 | return $custom_error_response; 121 | } else { 122 | throw new \Exception("The error function must return an object of class Response."); 123 | } 124 | } 125 | 126 | if ($this->getResponseMessage()) 127 | $res['message'] = $this->getResponseMessage(); 128 | else 129 | $res['message'] = 'Invalid authentication token'; 130 | 131 | if ($this->getResponseToken()) { 132 | $res['token'] = $this->getResponseToken(); 133 | } 134 | 135 | return $response->withJson($res, 401, JSON_PRETTY_PRINT); 136 | } 137 | 138 | public function findToken(Request $request) 139 | { 140 | $tokenSearch = new TokenSearch([ 141 | 'header' => $this->options['header'], 142 | 'regex' => $this->options['regex'], 143 | 'parameter' => $this->options['parameter'], 144 | 'cookie' => $this->options['cookie'], 145 | 'argument' => $this->options['argument'] 146 | ]); 147 | 148 | $token = $tokenSearch($request); 149 | $request->withAttribute('authorization', $token); 150 | $this->setResponseToken($token); 151 | 152 | return $token; 153 | } 154 | 155 | public function setResponseMessage($message) 156 | { 157 | $this->response['message'] = $message; 158 | return $this; 159 | } 160 | 161 | public function getResponseMessage() 162 | { 163 | return isset($this->response['message']) ? $this->response['message'] : null; 164 | } 165 | 166 | public function setResponseToken($token) 167 | { 168 | $this->response['token'] = $token; 169 | return $this; 170 | } 171 | 172 | public function getResponseToken() 173 | { 174 | return isset($this->response['token']) ? $this->response['token'] : null; 175 | } 176 | 177 | /** Use to set multiples messages and after get on custom error function */ 178 | public function setResponseArray(array $args = []) 179 | { 180 | foreach ($args as $name => $text) { 181 | return $this->response[$name] = $text; 182 | } 183 | return $this; 184 | } 185 | 186 | public function getResponseByName($name) 187 | { 188 | return isset($this->response[$name]) ? $this->response[$name] : null; 189 | } 190 | 191 | public function setSecure($secure) 192 | { 193 | $this->options['secure'] = (bool) $secure; 194 | return $this; 195 | } 196 | 197 | public function getSecure() 198 | { 199 | return $this->options['secure']; 200 | } 201 | 202 | public function setRelaxed($relaxed) 203 | { 204 | $this->options['relaxed'] = (array) $relaxed; 205 | return $this; 206 | } 207 | 208 | public function getRelaxed() 209 | { 210 | return $this->options['relaxed']; 211 | } 212 | 213 | public function setPath($path) 214 | { 215 | $this->options['path'] = (array) $path; 216 | return $this; 217 | } 218 | 219 | public function getPath() 220 | { 221 | return $this->options['path']; 222 | } 223 | 224 | public function setPassthrough($passthrough) 225 | { 226 | $this->options['passthrough'] = (array) $passthrough; 227 | return $this; 228 | } 229 | 230 | public function getPassthrough() 231 | { 232 | return $this->options['passthrough']; 233 | } 234 | 235 | public function setError(Callable $error) 236 | { 237 | $this->options['error'] = $error; 238 | return $this; 239 | } 240 | 241 | public function getError() 242 | { 243 | return $this->options['error']; 244 | } 245 | 246 | public function setAuthenticator(Callable $authenticator) 247 | { 248 | $this->options['authenticator'] = $authenticator; 249 | return $this; 250 | } 251 | 252 | public function getAuthenticator() 253 | { 254 | return $this->options['authenticator']; 255 | } 256 | 257 | public function setHeader($header) 258 | { 259 | $this->options['header'] = $header; 260 | return $this; 261 | } 262 | 263 | public function getHeader() 264 | { 265 | return $this->options['header']; 266 | } 267 | 268 | public function setRegex($regex) 269 | { 270 | $this->options['regex'] = $regex; 271 | return $this; 272 | } 273 | 274 | public function getRegex() 275 | { 276 | return $this->options['regex']; 277 | } 278 | 279 | public function setParameter($parameter) 280 | { 281 | $this->options['parameter'] = $parameter; 282 | return $this; 283 | } 284 | 285 | public function getParameter() 286 | { 287 | return $this->options['parameter']; 288 | } 289 | 290 | public function setArgument($argument) 291 | { 292 | $this->options['argument'] = $argument; 293 | return $this; 294 | } 295 | 296 | public function getArgument() 297 | { 298 | return $this->options['argument']; 299 | } 300 | 301 | public function setCookie($cookie) 302 | { 303 | $this->options['cookie'] = $cookie; 304 | return $this; 305 | } 306 | 307 | public function getCookie() 308 | { 309 | return $this->options['cookie']; 310 | } 311 | } -------------------------------------------------------------------------------- /example/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "a25e860d002eeb3a1caf698ec5a43e27", 8 | "content-hash": "18b2271661eb4aae8fc39b49d255979a", 9 | "packages": [ 10 | { 11 | "name": "container-interop/container-interop", 12 | "version": "1.1.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/container-interop/container-interop.git", 16 | "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", 21 | "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", 22 | "shasum": "" 23 | }, 24 | "type": "library", 25 | "autoload": { 26 | "psr-4": { 27 | "Interop\\Container\\": "src/Interop/Container/" 28 | } 29 | }, 30 | "notification-url": "https://packagist.org/downloads/", 31 | "license": [ 32 | "MIT" 33 | ], 34 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", 35 | "time": "2014-12-30 15:22:37" 36 | }, 37 | { 38 | "name": "dyorg/slim-token-authentication", 39 | "version": "0.2.1", 40 | "source": { 41 | "type": "git", 42 | "url": "https://github.com/dyorg/slim-token-authentication.git", 43 | "reference": "c9bdfe4478e72d105237e1ec6a93bf985c15c2da" 44 | }, 45 | "dist": { 46 | "type": "zip", 47 | "url": "https://api.github.com/repos/dyorg/slim-token-authentication/zipball/c9bdfe4478e72d105237e1ec6a93bf985c15c2da", 48 | "reference": "c9bdfe4478e72d105237e1ec6a93bf985c15c2da", 49 | "shasum": "" 50 | }, 51 | "require": { 52 | "php": ">=5.4.0" 53 | }, 54 | "require-dev": { 55 | "phpunit/phpunit": "~4.6", 56 | "squizlabs/php_codesniffer": "~2.3", 57 | "zendframework/zend-diactoros": "^1.3" 58 | }, 59 | "type": "library", 60 | "autoload": { 61 | "psr-4": { 62 | "Slim\\Middleware\\": "src" 63 | } 64 | }, 65 | "notification-url": "https://packagist.org/downloads/", 66 | "license": [ 67 | "MIT" 68 | ], 69 | "authors": [ 70 | { 71 | "name": "Dyorg Almeida", 72 | "email": "dyorg@rabbiit.com", 73 | "homepage": "https://rabbiit.com/", 74 | "role": "Developer" 75 | } 76 | ], 77 | "description": "Slim 3.0+ Token Authentication Middleware", 78 | "homepage": "https://github.com/dyorg/slim-token-authentication", 79 | "keywords": [ 80 | "Authentication", 81 | "auth", 82 | "authorization", 83 | "middleware", 84 | "slim", 85 | "token" 86 | ], 87 | "time": "2016-06-15 15:11:02" 88 | }, 89 | { 90 | "name": "nikic/fast-route", 91 | "version": "v1.0.1", 92 | "source": { 93 | "type": "git", 94 | "url": "https://github.com/nikic/FastRoute.git", 95 | "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" 96 | }, 97 | "dist": { 98 | "type": "zip", 99 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", 100 | "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", 101 | "shasum": "" 102 | }, 103 | "require": { 104 | "php": ">=5.4.0" 105 | }, 106 | "type": "library", 107 | "autoload": { 108 | "psr-4": { 109 | "FastRoute\\": "src/" 110 | }, 111 | "files": [ 112 | "src/functions.php" 113 | ] 114 | }, 115 | "notification-url": "https://packagist.org/downloads/", 116 | "license": [ 117 | "BSD-3-Clause" 118 | ], 119 | "authors": [ 120 | { 121 | "name": "Nikita Popov", 122 | "email": "nikic@php.net" 123 | } 124 | ], 125 | "description": "Fast request router for PHP", 126 | "keywords": [ 127 | "router", 128 | "routing" 129 | ], 130 | "time": "2016-06-12 19:08:51" 131 | }, 132 | { 133 | "name": "pimple/pimple", 134 | "version": "v3.0.2", 135 | "source": { 136 | "type": "git", 137 | "url": "https://github.com/silexphp/Pimple.git", 138 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" 139 | }, 140 | "dist": { 141 | "type": "zip", 142 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", 143 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", 144 | "shasum": "" 145 | }, 146 | "require": { 147 | "php": ">=5.3.0" 148 | }, 149 | "type": "library", 150 | "extra": { 151 | "branch-alias": { 152 | "dev-master": "3.0.x-dev" 153 | } 154 | }, 155 | "autoload": { 156 | "psr-0": { 157 | "Pimple": "src/" 158 | } 159 | }, 160 | "notification-url": "https://packagist.org/downloads/", 161 | "license": [ 162 | "MIT" 163 | ], 164 | "authors": [ 165 | { 166 | "name": "Fabien Potencier", 167 | "email": "fabien@symfony.com" 168 | } 169 | ], 170 | "description": "Pimple, a simple Dependency Injection Container", 171 | "homepage": "http://pimple.sensiolabs.org", 172 | "keywords": [ 173 | "container", 174 | "dependency injection" 175 | ], 176 | "time": "2015-09-11 15:10:35" 177 | }, 178 | { 179 | "name": "psr/http-message", 180 | "version": "1.0.1", 181 | "source": { 182 | "type": "git", 183 | "url": "https://github.com/php-fig/http-message.git", 184 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 185 | }, 186 | "dist": { 187 | "type": "zip", 188 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 189 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 190 | "shasum": "" 191 | }, 192 | "require": { 193 | "php": ">=5.3.0" 194 | }, 195 | "type": "library", 196 | "extra": { 197 | "branch-alias": { 198 | "dev-master": "1.0.x-dev" 199 | } 200 | }, 201 | "autoload": { 202 | "psr-4": { 203 | "Psr\\Http\\Message\\": "src/" 204 | } 205 | }, 206 | "notification-url": "https://packagist.org/downloads/", 207 | "license": [ 208 | "MIT" 209 | ], 210 | "authors": [ 211 | { 212 | "name": "PHP-FIG", 213 | "homepage": "http://www.php-fig.org/" 214 | } 215 | ], 216 | "description": "Common interface for HTTP messages", 217 | "homepage": "https://github.com/php-fig/http-message", 218 | "keywords": [ 219 | "http", 220 | "http-message", 221 | "psr", 222 | "psr-7", 223 | "request", 224 | "response" 225 | ], 226 | "time": "2016-08-06 14:39:51" 227 | }, 228 | { 229 | "name": "slim/slim", 230 | "version": "3.5.0", 231 | "source": { 232 | "type": "git", 233 | "url": "https://github.com/slimphp/Slim.git", 234 | "reference": "184352bc1913d7ba552ab4131d62f4730ddb0893" 235 | }, 236 | "dist": { 237 | "type": "zip", 238 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/184352bc1913d7ba552ab4131d62f4730ddb0893", 239 | "reference": "184352bc1913d7ba552ab4131d62f4730ddb0893", 240 | "shasum": "" 241 | }, 242 | "require": { 243 | "container-interop/container-interop": "^1.1", 244 | "nikic/fast-route": "^1.0", 245 | "php": ">=5.5.0", 246 | "pimple/pimple": "^3.0", 247 | "psr/http-message": "^1.0" 248 | }, 249 | "provide": { 250 | "psr/http-message-implementation": "1.0" 251 | }, 252 | "require-dev": { 253 | "phpunit/phpunit": "^4.0", 254 | "squizlabs/php_codesniffer": "^2.5" 255 | }, 256 | "type": "library", 257 | "autoload": { 258 | "psr-4": { 259 | "Slim\\": "Slim" 260 | } 261 | }, 262 | "notification-url": "https://packagist.org/downloads/", 263 | "license": [ 264 | "MIT" 265 | ], 266 | "authors": [ 267 | { 268 | "name": "Rob Allen", 269 | "email": "rob@akrabat.com", 270 | "homepage": "http://akrabat.com" 271 | }, 272 | { 273 | "name": "Josh Lockhart", 274 | "email": "hello@joshlockhart.com", 275 | "homepage": "https://joshlockhart.com" 276 | }, 277 | { 278 | "name": "Gabriel Manricks", 279 | "email": "gmanricks@me.com", 280 | "homepage": "http://gabrielmanricks.com" 281 | }, 282 | { 283 | "name": "Andrew Smith", 284 | "email": "a.smith@silentworks.co.uk", 285 | "homepage": "http://silentworks.co.uk" 286 | } 287 | ], 288 | "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", 289 | "homepage": "http://slimframework.com", 290 | "keywords": [ 291 | "api", 292 | "framework", 293 | "micro", 294 | "router" 295 | ], 296 | "time": "2016-07-26 15:12:13" 297 | } 298 | ], 299 | "packages-dev": [], 300 | "aliases": [], 301 | "minimum-stability": "stable", 302 | "stability-flags": [], 303 | "prefer-stable": false, 304 | "prefer-lowest": false, 305 | "platform": { 306 | "php": "^5.4" 307 | }, 308 | "platform-dev": [] 309 | } 310 | --------------------------------------------------------------------------------