Skip to content

Commit

Permalink
Adding the ability to use package with service-to-service Passport cl…
Browse files Browse the repository at this point in the history
…ient (#2467)

* Adding the ability to use package with service-to-service Passport clients

Co-authored-by: SuperDJ <[email protected]>
Co-authored-by: erikn69 <[email protected]>
  • Loading branch information
3 people authored Jul 26, 2023
1 parent 2dc2787 commit 04a9592
Show file tree
Hide file tree
Showing 14 changed files with 538 additions and 12 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/run-tests-L8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ jobs:
extensions: curl, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, iconv
coverage: none

- name: Install dependencies (remove passport)
run: composer remove --dev laravel/passport --no-interaction --no-update
if: matrix.laravel == '8.*'

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "symfony/console:>=4.3.4" "mockery/mockery:^1.3.2" "nesbot/carbon:>=2.62.1" --no-interaction --no-update
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"illuminate/database": "^8.0|^9.0|^10.0"
},
"require-dev": {
"laravel/passport": "^11.0",
"orchestra/testbench": "^6.0|^7.0|^8.0",
"phpunit/phpunit": "^9.4"
},
Expand Down
7 changes: 7 additions & 0 deletions config/permission.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@

'teams' => false,

/*
* Passport Client Credentials Grant
* When set to true the package will use Passports Client to check permissions
*/

'use_passport_client_credentials' => false,

/*
* When set to true, the required permission names are added to exception messages.
* This could be considered an information leak in some contexts, so the default
Expand Down
53 changes: 53 additions & 0 deletions docs/basic-usage/passport.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Passport Client Credentials Grant usage
weight: 12
---

**NOTE** currently this only works for Laravel 9 and Passport 11 and newer.

## Install Passport
First of all make sure to have Passport installed as described in the [Laravel documentation](https://laravel.com/docs/master/passport).

## Extend the Client model
After installing the Passport package we need to extend Passports Client model.
The extended Client model should look like something as shown below.

```php
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Laravel\Passport\Client as BaseClient;
use Spatie\Permission\Traits\HasRoles;

class Client extends BaseClient implements AuthorizableContract
{
use HasRoles;
use Authorizable;

public $guard_name = 'api';

// or

public function guardName()
{
return 'api'
}
}
```

You need to extend the Client model to make it possible to add the required traits and properties/ methods.
The extended Client should either provide a `$guard_name` property or a `guardName()` method.
They should return a string that matches the [configured](https://laravel.com/docs/master/passport#installation) guard name for the passport driver.

## Middleware
All middlewares provided by this package work with the Client.

Do make sure that you only wrap your routes in the [`client`](https://laravel.com/docs/master/passport#via-middleware) middleware and not the `auth:api` middleware as well.
Wrapping routes in the `auth:api` middleware currently does not work for the Client Credentials Grant.

## Config
Finally, update the config file as well. Setting `use_passport_client_credentials` to `true` will make sure that the right checks are performed.

```php
// config/permission.php
'use_passport_client_credentials' => true,
```
2 changes: 2 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@
</testsuites>
<php>
<env name="CACHE_DRIVER" value="array"/>
<env name="APP_KEY" value="base64:W99w+5JYz8SVGf5sx17gmPR6uoNCtWiEVc+9qu8iGEg="/> <!-- Required for Passport client -->
<ini name="memory_limit" value="512M" />
</php>
</phpunit>
32 changes: 32 additions & 0 deletions src/Guard.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace Spatie\Permission;

use Illuminate\Contracts\Auth\Access\Authorizable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;

class Guard
{
Expand Down Expand Up @@ -72,4 +74,34 @@ public static function getDefaultName($class): string

return $possible_guards->first() ?: $default;
}

/**
* Lookup a passport guard
*/
public static function getPassportClient($guard): ?Authorizable
{
$guards = collect(config('auth.guards'))->where('driver', 'passport');

if (! $guards->count()) {
return null;
}

$authGuard = Auth::guard($guards->keys()[0]);

if (! \method_exists($authGuard, 'client')) {
return null;
}

$client = $authGuard->client();

if (! $guard || ! $client) {
return $client;
}

if (self::getNames($client)->contains($guard)) {
return $client;
}

return null;
}
}
12 changes: 9 additions & 3 deletions src/Middlewares/PermissionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@
use Closure;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Exceptions\UnauthorizedException;
use Spatie\Permission\Guard;

class PermissionMiddleware
{
public function handle($request, Closure $next, $permission, $guard = null)
{
$authGuard = Auth::guard($guard);

if ($authGuard->guest()) {
throw UnauthorizedException::notLoggedIn();
$user = $authGuard->user();

// For machine-to-machine Passport clients
if (! $user && $request->bearerToken() && config('permission.use_passport_client_credentials')) {
$user = Guard::getPassportClient($guard);
}

$user = $authGuard->user();
if (! $user) {
throw UnauthorizedException::notLoggedIn();
}

if (! method_exists($user, 'hasAnyPermission')) {
throw UnauthorizedException::missingTraitHasRoles($user);
Expand Down
12 changes: 9 additions & 3 deletions src/Middlewares/RoleMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@
use Closure;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Exceptions\UnauthorizedException;
use Spatie\Permission\Guard;

class RoleMiddleware
{
public function handle($request, Closure $next, $role, $guard = null)
{
$authGuard = Auth::guard($guard);

if ($authGuard->guest()) {
throw UnauthorizedException::notLoggedIn();
$user = $authGuard->user();

// For machine-to-machine Passport clients
if (! $user && $request->bearerToken() && config('permission.use_passport_client_credentials')) {
$user = Guard::getPassportClient($guard);
}

$user = $authGuard->user();
if (! $user) {
throw UnauthorizedException::notLoggedIn();
}

if (! method_exists($user, 'hasAnyRole')) {
throw UnauthorizedException::missingTraitHasRoles($user);
Expand Down
13 changes: 10 additions & 3 deletions src/Middlewares/RoleOrPermissionMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
use Closure;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Exceptions\UnauthorizedException;
use Spatie\Permission\Guard;

class RoleOrPermissionMiddleware
{
public function handle($request, Closure $next, $roleOrPermission, $guard = null)
{
$authGuard = Auth::guard($guard);
if ($authGuard->guest()) {
throw UnauthorizedException::notLoggedIn();
}

$user = $authGuard->user();

// For machine-to-machine Passport clients
if (! $user && $request->bearerToken() && config('permission.use_passport_client_credentials')) {
$user = Guard::getPassportClient($guard);
}

if (! $user) {
throw UnauthorizedException::notLoggedIn();
}

if (! method_exists($user, 'hasAnyRole') || ! method_exists($user, 'hasAnyPermission')) {
throw UnauthorizedException::missingTraitHasRoles($user);
}
Expand Down
Loading

0 comments on commit 04a9592

Please sign in to comment.