I'm upgrading an old Laravel app to Laravel 8. Everything went fine with the upgrade except for being able to connect through the API. When I do try, I get a crash message Class 'Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory' not found. I followed a short guide (https://symfony.com/doc/current/components/psr7.html#usage) to use PSR-7 instead, but after that all API calls came back as simple Unauthenticated, even though I'm using the same credentials as before. I'm able to use curl to get a new access token with a call to /oauth/token, but even using that new token tells me it's unauthenticated when I make any other call.
The thing is, the middleware isn't a file that I coded. It seems to be a generic middleware for API calls and I don't really understand what it's doing. Is there a default API middleware, dealing with access tokens and all that, that I should be using for Laravel 8? Or are there other changes I should be making to the file to make it work again?
The file in question, app/Http/Middleware/MyCheckClientCredentials, which worked fine in Laravel 6 and 7, is
<?php
namespace App\Http\Middleware;
use Closure;
use League\OAuth2\Server\ResourceServer;
use Illuminate\Auth\AuthenticationException;
use Laravel\Passport\Exceptions\MissingScopeException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
class MyCheckClientCredentials
{
/**
* The Resource Server instance.
*
* @var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* Create a new middleware instance.
*
* @param \League\OAuth2\Server\ResourceServer $server
* @return void
*/
public function __construct(ResourceServer $server)
{
$this->server = $server;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return mixed
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$scopes)
{
$psr = (new DiactorosFactory)->createRequest($request);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
$request['oauth_client_id'] = $psr->getAttribute('oauth_client_id');
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$this->validateScopes($psr, $scopes);
return $next($request);
}
/**
* Validate the scopes on the incoming request.
*
* @param \Psr\Http\Message\ResponseInterface $psr
* @param array $scopes
* @return void
* @throws \Laravel\Passport\Exceptions\MissingScopeException
*/
protected function validateScopes($psr, $scopes)
{
if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) {
return;
}
foreach ($scopes as $scope) {
if (! in_array($scope, $tokenScopes)) {
throw new MissingScopeException($scope);
}
}
}
}
The updated middleware that always says Unauthenticated but at least doesn't crash:
<?php
namespace App\Http\Middleware;
use Closure;
use League\OAuth2\Server\ResourceServer;
use Illuminate\Auth\AuthenticationException;
use Laravel\Passport\Exceptions\MissingScopeException;
use League\OAuth2\Server\Exception\OAuthServerException;
//use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Nyholm\Psr7\Factory\Psr17Factory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Component\HttpFoundation\Request;
class MyCheckClientCredentials
{
/**
* The Resource Server instance.
*
* @var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* Create a new middleware instance.
*
* @param \League\OAuth2\Server\ResourceServer $server
* @return void
*/
public function __construct(ResourceServer $server)
{
$this->server = $server;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return mixed
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$scopes)
{
//$psr = (new DiactorosFactory)->createRequest($request);
$symfonyRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'toi.development.lib.utah.edu'], 'Content');
// The HTTP_HOST server key must be set to avoid an unexpected error
$psr17Factory = new Psr17Factory();
$psrHttpFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$psr = $psrHttpFactory->createRequest($symfonyRequest);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
$request['oauth_client_id'] = $psr->getAttribute('oauth_client_id');
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$this->validateScopes($psr, $scopes);
return $next($request);
}
/**
* Validate the scopes on the incoming request.
*
* @param \Psr\Http\Message\ResponseInterface $psr
* @param array $scopes
* @return void
* @throws \Laravel\Passport\Exceptions\MissingScopeException
*/
protected function validateScopes($psr, $scopes)
{
if (in_array('*', $tokenScopes = $psr->getAttribute('oauth_scopes'))) {
return;
}
foreach ($scopes as $scope) {
if (! in_array($scope, $tokenScopes)) {
throw new MissingScopeException($scope);
}
}
}
}
Composer file:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.1",
"doctrine/dbal": "^2.5",
"fideloper/proxy": "~4.0",
"laravel/framework": "^8.0",
"laravel/helpers": "^1.4",
"laravel/passport": "^10.0",
"laravel/tinker": "~2.0",
"lcobucci/jwt": "^4.0",
"subfission/cas": "dev-master",
"symfony/psr-http-message-bridge": "^2.0",
"nyholm/psr7": "^1.5",
"zendframework/zend-diactoros": "2.2.1",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/ui": "^3.0"
},
"require-dev": {
"facade/ignition": "^2.3.6",
"filp/whoops": "~2.0",
"fzaninotto/faker": "~1.4",
"mockery/mockery": "0.9.*",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.0"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/Functions/helper_functions.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"dont-discover": [
]
}
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
}
}