clone repo
This commit is contained in:
commit
f19181c63a
|
@ -0,0 +1,16 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -0,0 +1 @@
|
||||||
|
/vendor/
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Nomad NT
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,355 @@
|
||||||
|
<p align="center"><img src="https://laravel.com/assets/img/components/logo-passport.svg"></p>
|
||||||
|
|
||||||
|
[![Total Downloads](https://poser.pugx.org/nomadnt/lumen-passport/downloads)](https://packagist.org/packages/nomadnt/lumen-passport)
|
||||||
|
[![Latest Stable Version](https://poser.pugx.org/nomadnt/lumen-passport/v/stable)](https://packagist.org/packages/nomadnt/lumen-passport)
|
||||||
|
[![License](https://poser.pugx.org/nomadnt/lumen-passport/license)](https://packagist.org/packages/nomadnt/lumen-passport)
|
||||||
|
|
||||||
|
|
||||||
|
# Lumen Passport
|
||||||
|
|
||||||
|
Lumen porting of Laravel Passport.
|
||||||
|
The idea come from https://github.com/dusterio/lumen-passport but try to make it transparent with original laravel passport
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* PHP >= 7.3.0
|
||||||
|
* Lumen >= 8.0
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
First of all let's install Lumen Framework if you haven't already.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
composer create-project --prefer-dist laravel/lumen lumen-app && cd lumen-app
|
||||||
|
```
|
||||||
|
|
||||||
|
Then install Lumen Passport (it will fetch Laravel Passport along):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
composer require nomadnt/lumen-passport
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Generate your APP_KEY and update .env with single command
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sed -i "s|\(APP_KEY=\)\(.*\)|\1$(openssl rand -base64 24)|" .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure your database connection (ie to use SQLite)
|
||||||
|
This is how your .env file should looking after the changes
|
||||||
|
|
||||||
|
```env
|
||||||
|
APP_NAME=Lumen
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=<my-super-strong-api-key>
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://localhost:8000
|
||||||
|
APP_TIMEZONE=UTC
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_SLACK_WEBHOOK_URL=
|
||||||
|
|
||||||
|
DB_CONNECTION=sqlite
|
||||||
|
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the Lumen configuration folder to your project
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cp -a vendor/laravel/lumen-framework/config config
|
||||||
|
```
|
||||||
|
|
||||||
|
Update `guards` and `provider` section of your config/auth.php to match Passport requirements
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
...
|
||||||
|
|
||||||
|
'guards' => [
|
||||||
|
'api' => ['driver' => 'passport', 'provider' => 'users']
|
||||||
|
],
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
'providers' => [
|
||||||
|
'users' => ['driver' => 'eloquent', 'model' => \App\Models\User::class]
|
||||||
|
]
|
||||||
|
|
||||||
|
...
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
You need to change a little the `bootstrap/app.php` file doing the following:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// enable facades
|
||||||
|
$app->withFacades();
|
||||||
|
|
||||||
|
// enable eloquent
|
||||||
|
$app->withEloquent();
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
$app->configure('app');
|
||||||
|
|
||||||
|
// initialize auth configuration
|
||||||
|
$app->configure('auth');
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// enable auth and throttle middleware
|
||||||
|
$app->routeMiddleware([
|
||||||
|
'auth' => App\Http\Middleware\Authenticate::class,
|
||||||
|
'throttle' => Nomadnt\LumenPassport\Middleware\ThrottleRequests::class
|
||||||
|
]);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// register required service providers
|
||||||
|
|
||||||
|
// $app->register(App\Providers\AppServiceProvider::class);
|
||||||
|
$app->register(App\Providers\AuthServiceProvider::class);
|
||||||
|
$app->register(Laravel\Passport\PassportServiceProvider::class);
|
||||||
|
// $app->register(App\Providers\EventServiceProvider::class);
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Create database.sqlite
|
||||||
|
|
||||||
|
```sh
|
||||||
|
touch database/database.sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
Lauch the migrations
|
||||||
|
|
||||||
|
```sh
|
||||||
|
php artisan migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
Install Laravel passport
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Install encryption keys and other necessary stuff for Passport
|
||||||
|
php artisan passport:install
|
||||||
|
```
|
||||||
|
|
||||||
|
The previous command should give back to you an output similar to this:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
Encryption keys generated successfully.
|
||||||
|
Personal access client created successfully.
|
||||||
|
Client ID: 1
|
||||||
|
Client secret: BxSueZnqimNTE0r98a0Egysq0qnonwkWDUl0KmE5
|
||||||
|
Password grant client created successfully.
|
||||||
|
Client ID: 2
|
||||||
|
Client secret: VFWuiJXTJhjb46Y04llOQqSd3kP3goqDLvVIkcIu
|
||||||
|
```
|
||||||
|
|
||||||
|
## Registering Routes
|
||||||
|
|
||||||
|
Now is time to register the passport routes necessary to issue access tokens and revoke access tokens, clients, and personal access tokens.
|
||||||
|
To do this open you `app/Providers/AuthServiceProvider.php` and change the `boot` function to reflect the example below.
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
// don't forget to include Passport
|
||||||
|
use Nomadnt\LumenPassport\Passport;
|
||||||
|
|
||||||
|
class AuthServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot the authentication services for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
// register passport routes
|
||||||
|
Passport::routes();
|
||||||
|
|
||||||
|
// change the default token expiration
|
||||||
|
Passport::tokensExpireIn(Carbon::now()->addDays(15));
|
||||||
|
|
||||||
|
// change the default refresh token expiration
|
||||||
|
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## User model
|
||||||
|
|
||||||
|
Make sure your user model uses Passport's `HasApiTokens` trait, eg.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Authenticatable;
|
||||||
|
use Laravel\Passport\HasApiTokens;
|
||||||
|
use Laravel\Lumen\Auth\Authorizable;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||||
|
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
|
||||||
|
|
||||||
|
class User extends Model implements AuthenticatableContract, AuthorizableContract
|
||||||
|
{
|
||||||
|
use HasApiTokens, Authenticatable, Authorizable;
|
||||||
|
|
||||||
|
// rest of the model
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Access Token Events
|
||||||
|
|
||||||
|
### Prune and/or Revoke tokens
|
||||||
|
|
||||||
|
If you want to revoke or purge tokens on event based you have to create related Listeners and
|
||||||
|
register on your `app/Http/Providers/EventServiceProvider.php` istead of using deprecated properties
|
||||||
|
`Passport::$revokeOtherTokens = true;` and `Passport::$pruneRevokedTokens = true;`
|
||||||
|
|
||||||
|
First you need to make sure that `EventServiceProvider` is registered on your `bootstrap/app.php`
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// $app->register(App\Providers\AppServiceProvider::class);
|
||||||
|
$app->register(App\Providers\AuthServiceProvider::class);
|
||||||
|
$app->register(Laravel\Passport\PassportServiceProvider::class);
|
||||||
|
$app->register(App\Providers\EventServiceProvider::class);
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you need to listen for `AccessTokenCreated` event and register your required listeners
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class EventServiceProvider extends ServiceProvider{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event listener mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $listen = [
|
||||||
|
'Laravel\Passport\Events\AccessTokenCreated' => [
|
||||||
|
'App\Listeners\RevokeOtherTokens',
|
||||||
|
'App\Listeners\PruneRevokedTokens',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the `app/Listeners/RevokeOtherTokens.php` file and put the following content
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use Laravel\Passport\Events\AccessTokenCreated;
|
||||||
|
use Laravel\Passport\Token;
|
||||||
|
|
||||||
|
class RevokeOtherTokens
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\OrderShipped $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(AccessTokenCreated $event)
|
||||||
|
{
|
||||||
|
Token::where(function($query) use($event){
|
||||||
|
$query->where('user_id', $event->userId);
|
||||||
|
$query->where('id', '<>', $event->tokenId);
|
||||||
|
})->revoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the `app/Listeners/PruneRevokedTokens.php` file and put the following content
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use Laravel\Passport\Events\AccessTokenCreated;
|
||||||
|
use Laravel\Passport\Token;
|
||||||
|
|
||||||
|
class PruneRevokedTokens
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\AccessTokenCreated $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(AccessTokenCreated $event)
|
||||||
|
{
|
||||||
|
Token::where(function($query) use($event){
|
||||||
|
$query->where('user_id', $event->userId);
|
||||||
|
$query->where('id', '<>', $event->tokenId);
|
||||||
|
$query->where('revoked', true);
|
||||||
|
})->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "nomadnt/lumen-passport",
|
||||||
|
"description": "Lumen porting of Laravel Passport",
|
||||||
|
"keywords": ["php","lumen","laravel passport"],
|
||||||
|
"homepage": "https://github.com/nomadnt/lumen-passport",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Filippo Sallemi",
|
||||||
|
"email": "fsallemi@nomadnt.com",
|
||||||
|
"homepage": "https://nomadnt.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"require": {
|
||||||
|
"php": "^7.3.0",
|
||||||
|
"laravel/passport": "^10.1.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Nomadnt\\LumenPassport\\": "src/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/helpers.php"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
<?php namespace Nomadnt\LumenPassport\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use RuntimeException;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Cache\RateLimiter;
|
||||||
|
use Illuminate\Support\InteractsWithTime;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
class ThrottleRequests
|
||||||
|
{
|
||||||
|
use InteractsWithTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rate limiter instance.
|
||||||
|
*
|
||||||
|
* @var \Illuminate\Cache\RateLimiter
|
||||||
|
*/
|
||||||
|
protected $limiter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new request throttler.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Cache\RateLimiter $limiter
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(RateLimiter $limiter)
|
||||||
|
{
|
||||||
|
$this->limiter = $limiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @param int|string $maxAttempts
|
||||||
|
* @param float|int $decayMinutes
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
|
||||||
|
{
|
||||||
|
$key = $this->resolveRequestSignature($request);
|
||||||
|
|
||||||
|
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
|
||||||
|
|
||||||
|
if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
|
||||||
|
throw $this->buildException($key, $maxAttempts);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->limiter->hit($key, $decayMinutes);
|
||||||
|
|
||||||
|
$response = $next($request);
|
||||||
|
|
||||||
|
return $this->addHeaders(
|
||||||
|
$response, $maxAttempts,
|
||||||
|
$this->calculateRemainingAttempts($key, $maxAttempts)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the number of attempts if the user is authenticated or not.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param int|string $maxAttempts
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function resolveMaxAttempts($request, $maxAttempts)
|
||||||
|
{
|
||||||
|
if (Str::contains($maxAttempts, '|')) {
|
||||||
|
$maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $maxAttempts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve request signature.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return string
|
||||||
|
* @throws \RuntimeException
|
||||||
|
*/
|
||||||
|
protected function resolveRequestSignature($request)
|
||||||
|
{
|
||||||
|
if ($user = $request->user()) {
|
||||||
|
return sha1($user->getAuthIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($route = $request->route()) {
|
||||||
|
return sha1($request->getHost().'|'.$request->ip());
|
||||||
|
//return sha1($request->method().'|'.$request->getHost().'|'.$request->ip());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException(
|
||||||
|
'Unable to generate the request signature. Route unavailable.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a 'too many attempts' exception.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param int $maxAttempts
|
||||||
|
* @return \Symfony\Component\HttpKernel\Exception\HttpException
|
||||||
|
*/
|
||||||
|
protected function buildException($key, $maxAttempts)
|
||||||
|
{
|
||||||
|
$retryAfter = $this->getTimeUntilNextRetry($key);
|
||||||
|
|
||||||
|
$headers = $this->getHeaders(
|
||||||
|
$maxAttempts,
|
||||||
|
$this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
|
||||||
|
$retryAfter
|
||||||
|
);
|
||||||
|
|
||||||
|
return new HttpException(
|
||||||
|
429, 'Too Many Attempts.', null, $headers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of seconds until the next retry.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getTimeUntilNextRetry($key)
|
||||||
|
{
|
||||||
|
return $this->limiter->availableIn($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the limit header information to the given response.
|
||||||
|
*
|
||||||
|
* @param \Symfony\Component\HttpFoundation\Response $response
|
||||||
|
* @param int $maxAttempts
|
||||||
|
* @param int $remainingAttempts
|
||||||
|
* @param int|null $retryAfter
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
protected function addHeaders(Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null)
|
||||||
|
{
|
||||||
|
$response->headers->add(
|
||||||
|
$this->getHeaders($maxAttempts, $remainingAttempts, $retryAfter)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the limit headers information.
|
||||||
|
*
|
||||||
|
* @param int $maxAttempts
|
||||||
|
* @param int $remainingAttempts
|
||||||
|
* @param int|null $retryAfter
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getHeaders($maxAttempts, $remainingAttempts, $retryAfter = null)
|
||||||
|
{
|
||||||
|
$headers = [
|
||||||
|
'X-RateLimit-Limit' => $maxAttempts,
|
||||||
|
'X-RateLimit-Remaining' => $remainingAttempts,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (! is_null($retryAfter)) {
|
||||||
|
$headers['Retry-After'] = $retryAfter;
|
||||||
|
$headers['X-RateLimit-Reset'] = $this->availableAt($retryAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the number of remaining attempts.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param int $maxAttempts
|
||||||
|
* @param int|null $retryAfter
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
|
||||||
|
{
|
||||||
|
if (is_null($retryAfter)) {
|
||||||
|
return $this->limiter->retriesLeft($key, $maxAttempts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nomadnt\LumenPassport;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Laravel\Passport\Passport as LaravelPassport;
|
||||||
|
|
||||||
|
class Passport extends LaravelPassport
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Binds the Passport routes into the controller.
|
||||||
|
*
|
||||||
|
* @param callable|null $callback
|
||||||
|
* @param array $options
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function routes($callback = null, array $options = []){
|
||||||
|
$callback = $callback ?: function ($router) {
|
||||||
|
$router->all();
|
||||||
|
};
|
||||||
|
|
||||||
|
$defaultOptions = [
|
||||||
|
'prefix' => 'oauth',
|
||||||
|
'namespace' => '\Laravel\Passport\Http\Controllers',
|
||||||
|
];
|
||||||
|
|
||||||
|
$options = array_merge($defaultOptions, $options);
|
||||||
|
|
||||||
|
Route::group($options, function ($router) use ($callback) {
|
||||||
|
$callback(new RouteRegistrar($router));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nomadnt\LumenPassport;
|
||||||
|
|
||||||
|
use Laravel\Lumen\Routing\Router;
|
||||||
|
use Laravel\Passport\RouteRegistrar as Registrar;
|
||||||
|
|
||||||
|
class RouteRegistrar extends Registrar
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new route registrar instance.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Contracts\Routing\Registrar $router
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Router $router)
|
||||||
|
{
|
||||||
|
$this->router = $router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the routes needed for authorization.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forAuthorization()
|
||||||
|
{
|
||||||
|
$this->router->group(['middleware' => ['auth']], function ($router) {
|
||||||
|
$router->get('/authorize', [
|
||||||
|
'uses' => 'AuthorizationController@authorize',
|
||||||
|
]);
|
||||||
|
$router->post('/authorize', [
|
||||||
|
'uses' => 'ApproveAuthorizationController@approve',
|
||||||
|
]);
|
||||||
|
$router->delete('/authorize', [
|
||||||
|
'uses' => 'DenyAuthorizationController@deny',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the routes for retrieving and issuing access tokens.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forAccessTokens()
|
||||||
|
{
|
||||||
|
$this->router->post('/token', [
|
||||||
|
'uses' => 'AccessTokenController@issueToken',
|
||||||
|
'middleware' => 'throttle',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->router->group(['middleware' => ['auth']], function ($router) {
|
||||||
|
$router->get('/tokens', [
|
||||||
|
'uses' => 'AuthorizedAccessTokenController@forUser',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->delete('/tokens/{token_id}', [
|
||||||
|
'uses' => 'AuthorizedAccessTokenController@destroy',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the routes needed for refreshing transient tokens.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forTransientTokens()
|
||||||
|
{
|
||||||
|
$this->router->post('/token/refresh', [
|
||||||
|
'middleware' => ['auth'],
|
||||||
|
'uses' => 'TransientTokenController@refresh',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the routes needed for managing clients.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forClients()
|
||||||
|
{
|
||||||
|
$this->router->group(['middleware' => ['auth']], function ($router) {
|
||||||
|
$router->get('/clients', [
|
||||||
|
'uses' => 'ClientController@forUser',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->post('/clients', [
|
||||||
|
'uses' => 'ClientController@store',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->put('/clients/{client_id}', [
|
||||||
|
'uses' => 'ClientController@update',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->delete('/clients/{client_id}', [
|
||||||
|
'uses' => 'ClientController@destroy',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the routes needed for managing personal access tokens.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function forPersonalAccessTokens()
|
||||||
|
{
|
||||||
|
$this->router->group(['middleware' => ['auth']], function ($router) {
|
||||||
|
$router->get('/scopes', [
|
||||||
|
'uses' => 'ScopeController@all',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->get('/personal-access-tokens', [
|
||||||
|
'uses' => 'PersonalAccessTokenController@forUser',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->post('/personal-access-tokens', [
|
||||||
|
'uses' => 'PersonalAccessTokenController@store',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$router->delete('/personal-access-tokens/{token_id}', [
|
||||||
|
'uses' => 'PersonalAccessTokenController@destroy',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if (! function_exists('config_path')) {
|
||||||
|
/**
|
||||||
|
* Get the path to the configuration folder.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function config_path($path = '')
|
||||||
|
{
|
||||||
|
return app()->getConfigurationPath().($path ? '/'.$path : $path);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue