Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for using UUID client IDs (non-breaking) #168

Closed
wants to merge 11 commits into from
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"league/oauth2-server": "~5.0",
"symfony/psr-http-message-bridge": "^0.3.0",
"zendframework/zend-diactoros": "~1.0",
"phpseclib/phpseclib": "^2.0"
"phpseclib/phpseclib": "^2.0",
"webpatser/laravel-uuid": "2.*"
},
"require-dev": {
"mockery/mockery": "~0.9",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function up()
$table->increments('id');
$table->integer('user_id')->index()->nullable();
$table->string('name');
$table->char('uuid', 36)->unique()->nullable();
$table->string('secret', 100);
$table->text('redirect');
$table->boolean('personal_access_client');
Expand Down
1 change: 1 addition & 0 deletions src/Bridge/ClientRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Passport\Bridge;

use Laravel\Passport\Passport;
use Laravel\Passport\ClientRepository as ClientModelRepository;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;

Expand Down
23 changes: 21 additions & 2 deletions src/ClientRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Laravel\Passport;

use Webpatser\Uuid\Uuid as UUID;

class ClientRepository
{
/**
Expand All @@ -15,6 +17,17 @@ public function find($id)
return Client::find($id);
}

/**
* Get a client by the given UUID.
*
* @param string $uuid
* @return Client|null
*/
public function findUUID($uuid)
{
return Client::where('uuid', $uuid)->firstOrFail();
}

/**
* Get an active client by the given ID.
*
Expand Down Expand Up @@ -79,15 +92,21 @@ public function personalAccessClient()
*/
public function create($userId, $name, $redirect, $personalAccess = false, $password = false)
{
$client = (new Client)->forceFill([
$data = [
'user_id' => $userId,
'name' => $name,
'secret' => str_random(40),
'redirect' => $redirect,
'personal_access_client' => $personalAccess,
'password_client' => $password,
'revoked' => false,
]);
];

if (Passport::$useClientUUIDs) {
$data['uuid'] = UUID::generate(4)->string;
}

$client = (new Client)->forceFill($data);

$client->save();

Expand Down
2 changes: 1 addition & 1 deletion src/Console/ClientCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ClientCommand extends Command
protected $signature = 'passport:client
{--personal : Create a personal access token client}
{--password : Create a password grant client}
{--name : The name of the client}';
{--name= : The name of the client}';

/**
* The console command description.
Expand Down
69 changes: 69 additions & 0 deletions src/Console/UUIDCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Laravel\Passport\Console;

use Laravel\Passport\Client;
use Laravel\Passport\Passport;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;

class UUIDCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'passport:uuid';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate version 4 UUIDs for existing Passport clients';

/**
* Only show this command if Passport::useClientUUIDs is true
*
* @return null
*/
public function __construct()
{
parent::__construct();

if (!Passport::$useClientUUIDs) {
exit;
}
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->comment('Checking for `uuid` column in `oauth_clients`...');
if (!Schema::hasColumn('oauth_clients', 'uuid')) {
Schema::table('oauth_clients', function(Blueprint $table) {
$table->char('uuid', 36)->unique()->after('name')->nullable();
});
$this->line('✓ Created new column `uuid` in `oauth_clients`.');
} else {
$this->line('✓ OK.');
}

$this->comment('Generating version 4 UUIDs for Passport clients...');

$clients = Client::where('uuid', null)->get();

foreach($clients as $client) {
$client->uuid = UUID::generate(4)->string;
$client->save();
}

$this->line('✓ Done.');
}
}
13 changes: 13 additions & 0 deletions src/Http/Controllers/AccessTokenController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Passport\Http\Controllers;

use Laravel\Passport\Client;
use Laravel\Passport\Passport;
use Laravel\Passport\TokenRepository;
use Lcobucci\JWT\Parser as JwtParser;
Expand Down Expand Up @@ -59,6 +60,18 @@ public function __construct(AuthorizationServer $server,
*/
public function issueToken(ServerRequestInterface $request)
{
if (Passport::$useClientUUIDs) {
$rq = request();

$client = Client::where('uuid', $rq->input('client_id'))->firstOrFail();

$formData = $request->getParsedBody();

array_set($formData, 'client_id', $client->id);

$request = $request->withParsedBody($formData);
}

$response = $this->withErrorHandling(function () use ($request) {
return $this->server->respondToAccessTokenRequest($request, new Psr7Response);
});
Expand Down
10 changes: 9 additions & 1 deletion src/Http/Controllers/AuthorizationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,16 @@ public function authorize(ServerRequestInterface $psrRequest,

$scopes = $this->parseScopes($authRequest);

$identifier = $authRequest->getClient()->getIdentifier();

if (!Passport::$useClientUUIDs) {
$client = $clients->find($identifier);
} else {
$client = $clients->findUUID($identifier);
}

return $this->response->view('passport::authorize', [
'client' => $clients->find($authRequest->getClient()->getIdentifier()),
'client' => $client,
'user' => $request->user(),
'scopes' => $scopes,
'request' => $request,
Expand Down
15 changes: 11 additions & 4 deletions src/Http/Controllers/ClientController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Laravel\Passport\Http\Controllers;

use Laravel\Passport\Client;
use Laravel\Passport\Passport;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Laravel\Passport\ClientRepository;
Expand Down Expand Up @@ -36,6 +37,12 @@ public function __construct(ClientRepository $clients,
{
$this->clients = $clients;
$this->validation = $validation;

if (!Passport::$useClientUUIDs) {
$this->lookup = 'find';
} else {
$this->lookup = 'findUUID';
}
}

/**
Expand Down Expand Up @@ -76,7 +83,7 @@ public function store(Request $request)
*/
public function update(Request $request, $clientId)
{
if (! $request->user()->clients->find($clientId)) {
if (! $request->user()->clients->{$this->lookup}($clientId)) {
return new Response('', 404);
}

Expand All @@ -86,7 +93,7 @@ public function update(Request $request, $clientId)
])->validate();

return $this->clients->update(
$request->user()->clients->find($clientId),
$request->user()->clients->{$this->lookup}($clientId),
$request->name, $request->redirect
);
}
Expand All @@ -100,12 +107,12 @@ public function update(Request $request, $clientId)
*/
public function destroy(Request $request, $clientId)
{
if (! $request->user()->clients->find($clientId)) {
if (! $request->user()->clients->{$this->lookup}($clientId)) {
return new Response('', 404);
}

$this->clients->delete(
$request->user()->clients->find($clientId)
$request->user()->clients->{$this->lookup}($clientId)
);
}
}
95 changes: 95 additions & 0 deletions src/Passport.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,34 @@ class Passport
*/
public static $refreshTokensExpireAt;

/**
* The name for API token cookies.
*
* @var string
*/
public static $cookie = 'laravel_token';

/**
* The storage location of the encryption keys.
*
* @var string
*/
public static $keyPath;

/**
* Indicates if Passport migrations will be run.
*
* @var bool
*/
public static $runsMigrations = true;

/**
* Indicates if clients should be identified by UUID
*
* @var bool
*/
public static $useClientUUIDs = false;

/**
* Get a Passport route registrar.
*
Expand Down Expand Up @@ -190,4 +218,71 @@ public static function refreshTokensExpireIn(DateTimeInterface $date = null)

return new static;
}

/**
* Get or set the name for API token cookies.
*
* @param string|null $cookie
* @return string|static
*/
public static function cookie($cookie = null)
{
if (is_null($cookie)) {
return static::$cookie;
} else {
static::$cookie = $cookie;
}

return new static;
}

/**
* Set the storage location of the encryption keys.
*
* @param string $path
* @return void
*/
public static function loadKeysFrom($path)
{
static::$keyPath = $path;
}

/**
* The location of the encryption keys.
*
* @param string $file
* @return string
*/
public static function keyPath($file)
{
$file = ltrim($file, "/\\");

return static::$keyPath
? rtrim(static::$keyPath, "/\\").DIRECTORY_SEPARATOR.$file
: storage_path($file);
}

/**
* Configure Passport to not register its migrations.
*
* @return static
*/
public static function ignoreMigrations()
{
static::$runsMigrations = false;

return new static;
}

/**
* Instruct Passport to use UUIDs for identifying clients.
*
* @return static
*/
public static function useClientUUIDs()
{
static::$useClientUUIDs = true;

return new static;
}
}
10 changes: 8 additions & 2 deletions src/PassportServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,17 @@ public function boot()
__DIR__.'/../resources/assets/js/components' => base_path('resources/assets/js/components/passport'),
], 'passport-components');

$this->commands([
$commands = [
Console\InstallCommand::class,
Console\ClientCommand::class,
Console\KeysCommand::class,
]);
];

if (Passport::$useClientUUIDs) {
array_push($commands, Console\UUIDCommand::class);
}

$this->commands($commands);
}
}

Expand Down