Skip to content

Commit

Permalink
[13.x] Deprecate JSON API (#1778)
Browse files Browse the repository at this point in the history
* deprecate json api

* wip

* upgrade guide

* wip

* wip

* wip

* fix tests

* formatting

* wip

* fix bugs

* formatting

* upgrade guide

* Update UPGRADE.md

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
hafezdivandari and taylorotwell authored Oct 8, 2024
1 parent 40c4b91 commit ef122ad
Show file tree
Hide file tree
Showing 16 changed files with 235 additions and 476 deletions.
11 changes: 11 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ Passport's `oauth_personal_access_clients` table has been redundant and unnecess

In addition, the `passport.personal_access_client` configuration value, `Laravel\Passport\PersonalAccessClient` model, `Passport::$personalAccessClientModel` property, `Passport::usePersonalAccessClientModel()`, `Passport::personalAccessClientModel()`, and `Passport::personalAccessClient()` methods have been removed.

### JSON API Deprecation

PR: https://github.com/laravel/passport/pull/1778

The JSON API provided by Passport has been deprecated. If you need to continue using the deprecated JSON API, you can do so by setting `Passport::$registersJsonApiRoutes` to `true` within the `boot` method of your application’s `App\Providers\AppServiceProvider` class. Alternatively, you may also copy the relevant routes and controllers into your application as needed:

public function boot(): void
{
Passport::$registersJsonApiRoutes = true;
}

## Upgrading To 12.0 From 11.x

### Migration Changes
Expand Down
101 changes: 52 additions & 49 deletions routes/web.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Illuminate\Support\Facades\Route;
use Laravel\Passport\Passport;

Route::post('/token', [
'uses' => 'AccessTokenController@issueToken',
Expand Down Expand Up @@ -32,53 +33,55 @@
'as' => 'authorizations.deny',
]);

Route::get('/tokens', [
'uses' => 'AuthorizedAccessTokenController@forUser',
'as' => 'tokens.index',
]);

Route::delete('/tokens/{token_id}', [
'uses' => 'AuthorizedAccessTokenController@destroy',
'as' => 'tokens.destroy',
]);

Route::get('/clients', [
'uses' => 'ClientController@forUser',
'as' => 'clients.index',
]);

Route::post('/clients', [
'uses' => 'ClientController@store',
'as' => 'clients.store',
]);

Route::put('/clients/{client_id}', [
'uses' => 'ClientController@update',
'as' => 'clients.update',
]);

Route::delete('/clients/{client_id}', [
'uses' => 'ClientController@destroy',
'as' => 'clients.destroy',
]);

Route::get('/scopes', [
'uses' => 'ScopeController@all',
'as' => 'scopes.index',
]);

Route::get('/personal-access-tokens', [
'uses' => 'PersonalAccessTokenController@forUser',
'as' => 'personal.tokens.index',
]);

Route::post('/personal-access-tokens', [
'uses' => 'PersonalAccessTokenController@store',
'as' => 'personal.tokens.store',
]);

Route::delete('/personal-access-tokens/{token_id}', [
'uses' => 'PersonalAccessTokenController@destroy',
'as' => 'personal.tokens.destroy',
]);
if (Passport::$registersJsonApiRoutes) {
Route::get('/tokens', [
'uses' => 'AuthorizedAccessTokenController@forUser',
'as' => 'tokens.index',
]);

Route::delete('/tokens/{token_id}', [
'uses' => 'AuthorizedAccessTokenController@destroy',
'as' => 'tokens.destroy',
]);

Route::get('/clients', [
'uses' => 'ClientController@forUser',
'as' => 'clients.index',
]);

Route::post('/clients', [
'uses' => 'ClientController@store',
'as' => 'clients.store',
]);

Route::put('/clients/{client_id}', [
'uses' => 'ClientController@update',
'as' => 'clients.update',
]);

Route::delete('/clients/{client_id}', [
'uses' => 'ClientController@destroy',
'as' => 'clients.destroy',
]);

Route::get('/scopes', [
'uses' => 'ScopeController@all',
'as' => 'scopes.index',
]);

Route::get('/personal-access-tokens', [
'uses' => 'PersonalAccessTokenController@forUser',
'as' => 'personal.tokens.index',
]);

Route::post('/personal-access-tokens', [
'uses' => 'PersonalAccessTokenController@store',
'as' => 'personal.tokens.store',
]);

Route::delete('/personal-access-tokens/{token_id}', [
'uses' => 'PersonalAccessTokenController@destroy',
'as' => 'personal.tokens.destroy',
]);
}
});
66 changes: 20 additions & 46 deletions src/ClientRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use RuntimeException;

Expand All @@ -30,44 +31,26 @@ public function findActive(string|int $id): ?Client
/**
* Get a client instance for the given ID and user ID.
*
* @param int|string $clientId
* @param mixed $userId
* @return \Laravel\Passport\Client|null
* @deprecated Use $user->clients()->find()
*
* @param \Laravel\Passport\HasApiTokens $user
*/
public function findForUser($clientId, $userId)
public function findForUser(string|int $clientId, Authenticatable $user): ?Client
{
$client = Passport::client();

return $client
->where($client->getKeyName(), $clientId)
->where('user_id', $userId)
->first();
return $user->clients()->where('revoked', false)->find($clientId);
}

/**
* Get the client instances for the given user ID.
*
* @param mixed $userId
* @return \Illuminate\Database\Eloquent\Collection
*/
public function forUser($userId)
{
return Passport::client()
->where('user_id', $userId)
->orderBy('name', 'asc')->get();
}

/**
* Get the active client instances for the given user ID.
* @deprecated Use $user->clients()
*
* @param mixed $userId
* @return \Illuminate\Database\Eloquent\Collection
* @param \Laravel\Passport\HasApiTokens $user
* @return \Illuminate\Database\Eloquent\Collection<int, \Laravel\Passport\Client>
*/
public function activeForUser($userId)
public function forUser(Authenticatable $user): Collection
{
return $this->forUser($userId)->reject(function ($client) {
return $client->revoked;
})->values();
return $user->clients()->where('revoked', false)->orderBy('name')->get();
}

/*
Expand Down Expand Up @@ -188,6 +171,8 @@ public function createAuthorizationCodeGrantClient(
/**
* Update the given client.
*
* @deprecated Will be removed in a future Laravel version.
*
* @param string[] $redirectUris
*/
public function update(Client $client, string $name, array $redirectUris): bool
Expand Down Expand Up @@ -215,27 +200,16 @@ public function regenerateSecret(Client $client): bool
}

/**
* Determine if the given client is revoked.
*
* @param int|string $id
* @return bool
*/
public function revoked($id)
{
$client = $this->find($id);

return is_null($client) || $client->revoked;
}

/**
* Delete the given client.
* Revoke the given client and its tokens.
*
* @param \Laravel\Passport\Client $client
* @return void
* @deprecated Will be removed in a future Laravel version.
*/
public function delete(Client $client)
public function delete(Client $client): void
{
$client->tokens()->update(['revoked' => true]);
$client->tokens()->with('refreshToken')->each(function (Token $token): void {
$token->refreshToken?->revoke();
$token->revoke();
});

$client->forceFill(['revoked' => true])->save();
}
Expand Down
55 changes: 16 additions & 39 deletions src/Http/Controllers/AuthorizedAccessTokenController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,52 @@

namespace Laravel\Passport\Http\Controllers;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Laravel\Passport\RefreshTokenRepository;
use Laravel\Passport\Token;
use Laravel\Passport\TokenRepository;

/**
* @deprecated Will be removed in a future Laravel version.
*/
class AuthorizedAccessTokenController
{
/**
* The token repository implementation.
*
* @var \Laravel\Passport\TokenRepository
*/
protected $tokenRepository;

/**
* The refresh token repository implementation.
*
* @var \Laravel\Passport\RefreshTokenRepository
*/
protected $refreshTokenRepository;

/**
* Create a new controller instance.
*
* @param \Laravel\Passport\TokenRepository $tokenRepository
* @param \Laravel\Passport\RefreshTokenRepository $refreshTokenRepository
* @return void
*/
public function __construct(TokenRepository $tokenRepository, RefreshTokenRepository $refreshTokenRepository)
{
$this->tokenRepository = $tokenRepository;
$this->refreshTokenRepository = $refreshTokenRepository;
public function __construct(
protected TokenRepository $tokenRepository
) {
}

/**
* Get all of the authorized tokens for the authenticated user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Database\Eloquent\Collection<int, \Laravel\Passport\Token>
*/
public function forUser(Request $request)
public function forUser(Request $request): Collection
{
$tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier());

return $tokens->load('client')->filter(function ($token) {
return ! $token->client->firstParty() && ! $token->revoked;
})->values();
return $this->tokenRepository->forUser($request->user())
->reject(fn (Token $token): bool => $token->client->revoked || $token->client->firstParty())
->values();
}

/**
* Delete the given token.
*
* @param \Illuminate\Http\Request $request
* @param string $tokenId
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request, $tokenId)
public function destroy(Request $request, string $tokenId): Response
{
$token = $this->tokenRepository->findForUser(
$tokenId, $request->user()->getAuthIdentifier()
$tokenId, $request->user()
);

if (is_null($token)) {
return new Response('', 404);
}

$token->revoke();

$this->refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId);
$token->refreshToken?->revoke();

return new Response('', Response::HTTP_NO_CONTENT);
}
Expand Down
Loading

0 comments on commit ef122ad

Please sign in to comment.