Initial php8 work
- switch to GD for image work - fix issues around jwt
This commit is contained in:
parent
303b0e66ca
commit
6942fc1d32
9 changed files with 370 additions and 337 deletions
|
@ -10,6 +10,8 @@ use App\Models\Place;
|
||||||
use App\Services\Micropub\{HCardService, HEntryService, UpdateService};
|
use App\Services\Micropub\{HCardService, HEntryService, UpdateService};
|
||||||
use App\Services\TokenService;
|
use App\Services\TokenService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Lcobucci\JWT\Token\InvalidTokenStructure;
|
||||||
|
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
use Monolog\Logger;
|
use Monolog\Logger;
|
||||||
|
|
||||||
|
@ -43,13 +45,13 @@ class MicropubController extends Controller
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
||||||
} catch (InvalidTokenException $e) {
|
} catch (RequiredConstraintsViolated | InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->hasClaim('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
|
@ -58,7 +60,7 @@ class MicropubController extends Controller
|
||||||
$this->logMicropubRequest(request()->all());
|
$this->logMicropubRequest(request()->all());
|
||||||
|
|
||||||
if ((request()->input('h') == 'entry') || (request()->input('type.0') == 'h-entry')) {
|
if ((request()->input('h') == 'entry') || (request()->input('type.0') == 'h-entry')) {
|
||||||
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
|
if (stristr($tokenData->claims()->get('scope'), 'create') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
|
@ -72,7 +74,7 @@ class MicropubController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request()->input('h') == 'card' || request()->input('type.0') == 'h-card') {
|
if (request()->input('h') == 'card' || request()->input('type.0') == 'h-card') {
|
||||||
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
|
if (stristr($tokenData->claims()->get('scope'), 'create') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
|
@ -86,7 +88,7 @@ class MicropubController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request()->input('action') == 'update') {
|
if (request()->input('action') == 'update') {
|
||||||
if (stristr($tokenData->getClaim('scope'), 'update') === false) {
|
if (stristr($tokenData->claims()->get('scope'), 'update') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
|
@ -115,7 +117,7 @@ class MicropubController extends Controller
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
||||||
} catch (InvalidTokenException $e) {
|
} catch (RequiredConstraintsViolated | InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
|
@ -156,9 +158,9 @@ class MicropubController extends Controller
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'response' => 'token',
|
'response' => 'token',
|
||||||
'token' => [
|
'token' => [
|
||||||
'me' => $tokenData->getClaim('me'),
|
'me' => $tokenData->claims()->get('me'),
|
||||||
'scope' => $tokenData->getClaim('scope'),
|
'scope' => $tokenData->claims()->get('scope'),
|
||||||
'client_id' => $tokenData->getClaim('client_id'),
|
'client_id' => $tokenData->claims()->get('client_id'),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -167,13 +169,13 @@ class MicropubController extends Controller
|
||||||
* Determine the client id from the access token sent with the request.
|
* Determine the client id from the access token sent with the request.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws InvalidTokenException
|
* @throws RequiredConstraintsViolated
|
||||||
*/
|
*/
|
||||||
private function getClientId(): string
|
private function getClientId(): string
|
||||||
{
|
{
|
||||||
return resolve(TokenService::class)
|
return resolve(TokenService::class)
|
||||||
->validateToken(request()->input('access_token'))
|
->validateToken(request()->input('access_token'))
|
||||||
->getClaim('client_id');
|
->claims()->get('client_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Intervention\Image\Exception\NotReadableException;
|
use Intervention\Image\Exception\NotReadableException;
|
||||||
use Intervention\Image\ImageManager;
|
use Intervention\Image\ImageManager;
|
||||||
|
use Lcobucci\JWT\Token\InvalidTokenStructure;
|
||||||
|
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
|
|
||||||
class MicropubMediaController extends Controller
|
class MicropubMediaController extends Controller
|
||||||
|
@ -36,19 +38,19 @@ class MicropubMediaController extends Controller
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
||||||
} catch (InvalidTokenException $e) {
|
} catch (RequiredConstraintsViolated | InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->hasClaim('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Str::contains($tokenData->getClaim('scope'), 'create') === false) {
|
if (Str::contains($tokenData->claims()->get('scope'), 'create') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
|
@ -103,19 +105,19 @@ class MicropubMediaController extends Controller
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
$tokenData = $this->tokenService->validateToken(request()->input('access_token'));
|
||||||
} catch (InvalidTokenException $e) {
|
} catch (RequiredConstraintsViolated | InvalidTokenStructure) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->invalidTokenResponse();
|
return $micropubResponses->invalidTokenResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tokenData->hasClaim('scope') === false) {
|
if ($tokenData->claims()->has('scope') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->tokenHasNoScopeResponse();
|
return $micropubResponses->tokenHasNoScopeResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Str::contains($tokenData->getClaim('scope'), 'create') === false) {
|
if (Str::contains($tokenData->claims()->get('scope'), 'create') === false) {
|
||||||
$micropubResponses = new MicropubResponses();
|
$micropubResponses = new MicropubResponses();
|
||||||
|
|
||||||
return $micropubResponses->insufficientScopeResponse();
|
return $micropubResponses->insufficientScopeResponse();
|
||||||
|
|
|
@ -11,6 +11,10 @@ use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Laravel\Dusk\DuskServiceProvider;
|
use Laravel\Dusk\DuskServiceProvider;
|
||||||
|
use Lcobucci\JWT\Configuration;
|
||||||
|
use Lcobucci\JWT\Signer\Hmac\Sha256;
|
||||||
|
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||||
|
use Lcobucci\JWT\Validation\Constraint\SignedWith;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
@ -73,6 +77,17 @@ class AppServiceProvider extends ServiceProvider
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Configure JWT builder
|
||||||
|
$this->app->bind('Lcobucci\JWT\Configuration', function () {
|
||||||
|
$key = InMemory::plainText('testing');
|
||||||
|
|
||||||
|
$config = Configuration::forSymmetricSigner(new Sha256(), $key);
|
||||||
|
|
||||||
|
$config->setValidationConstraints(new SignedWith(new Sha256(), $key));
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,8 +6,8 @@ namespace App\Services;
|
||||||
|
|
||||||
use App\Exceptions\InvalidTokenException;
|
use App\Exceptions\InvalidTokenException;
|
||||||
use App\Jobs\AddClientToDatabase;
|
use App\Jobs\AddClientToDatabase;
|
||||||
use Lcobucci\JWT\Signer\Hmac\Sha256;
|
use DateTimeImmutable;
|
||||||
use Lcobucci\JWT\{Builder, Parser, Token};
|
use Lcobucci\JWT\{Configuration, Token};
|
||||||
|
|
||||||
class TokenService
|
class TokenService
|
||||||
{
|
{
|
||||||
|
@ -19,17 +19,19 @@ class TokenService
|
||||||
*/
|
*/
|
||||||
public function getNewToken(array $data): string
|
public function getNewToken(array $data): string
|
||||||
{
|
{
|
||||||
$signer = new Sha256();
|
$config = resolve(Configuration::class);
|
||||||
$token = (new Builder())->set('me', $data['me'])
|
|
||||||
->set('client_id', $data['client_id'])
|
$token = $config->builder()
|
||||||
->set('scope', $data['scope'])
|
->issuedAt(new DateTimeImmutable())
|
||||||
->set('date_issued', time())
|
->withClaim('client_id', $data['client_id'])
|
||||||
->set('nonce', bin2hex(random_bytes(8)))
|
->withClaim('me', $data['me'])
|
||||||
->sign($signer, config('app.key'))
|
->withClaim('scope', $data['scope'])
|
||||||
->getToken();
|
->withClaim('nonce', bin2hex(random_bytes(8)))
|
||||||
|
->getToken($config->signer(), $config->signingKey());
|
||||||
|
|
||||||
dispatch(new AddClientToDatabase($data['client_id']));
|
dispatch(new AddClientToDatabase($data['client_id']));
|
||||||
|
|
||||||
return (string) $token;
|
return $token->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,15 +42,13 @@ class TokenService
|
||||||
*/
|
*/
|
||||||
public function validateToken(string $bearerToken): Token
|
public function validateToken(string $bearerToken): Token
|
||||||
{
|
{
|
||||||
$signer = new Sha256();
|
$config = resolve('Lcobucci\JWT\Configuration');
|
||||||
try {
|
|
||||||
$token = (new Parser())->parse((string) $bearerToken);
|
$token = $config->parser()->parse($bearerToken);
|
||||||
} catch (\InvalidArgumentException $e) {
|
|
||||||
throw new InvalidTokenException('Token could not be parsed');
|
$constraints = $config->validationConstraints();
|
||||||
}
|
|
||||||
if (! $token->verify($signer, config('app.key'))) {
|
$config->validator()->assert($token, ...$constraints);
|
||||||
throw new InvalidTokenException('Token failed validation');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
],
|
],
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4",
|
"php": "^8.0",
|
||||||
"ext-intl": "*",
|
"ext-intl": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
|
|
550
composer.lock
generated
550
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -15,6 +15,6 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'driver' => 'imagick',
|
'driver' => 'gd',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -5,19 +5,16 @@ namespace Tests\Feature;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\TestToken;
|
use Tests\TestToken;
|
||||||
use App\Jobs\ProcessMedia;
|
|
||||||
use App\Jobs\SendWebMentions;
|
use App\Jobs\SendWebMentions;
|
||||||
use App\Models\{Media, Place};
|
use App\Models\{Media, Place};
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use App\Jobs\SyndicateNoteToTwitter;
|
use App\Jobs\SyndicateNoteToTwitter;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use MStaack\LaravelPostgis\Geometries\Point;
|
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
|
||||||
class MicropubControllerTest extends TestCase
|
class MicropubControllerTest extends TestCase
|
||||||
{
|
{
|
||||||
use DatabaseTransactions, TestToken;
|
use DatabaseTransactions;
|
||||||
|
use TestToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test a GET request for the micropub endpoint without a token gives a
|
* Test a GET request for the micropub endpoint without a token gives a
|
||||||
|
|
|
@ -2,50 +2,47 @@
|
||||||
|
|
||||||
namespace Tests;
|
namespace Tests;
|
||||||
|
|
||||||
use Lcobucci\JWT\Builder;
|
use DateTimeImmutable;
|
||||||
use Lcobucci\JWT\Signer\Hmac\Sha256;
|
use Lcobucci\JWT\Configuration;
|
||||||
|
|
||||||
trait TestToken
|
trait TestToken
|
||||||
{
|
{
|
||||||
public function getToken()
|
public function getToken()
|
||||||
{
|
{
|
||||||
$signer = new Sha256();
|
$config = $this->app->make(Configuration::class);
|
||||||
$token = (new Builder())
|
|
||||||
->set('client_id', 'https://quill.p3k.io')
|
|
||||||
->set('me', 'https://jonnybarnes.localhost')
|
|
||||||
->set('scope', 'create update')
|
|
||||||
->set('issued_at', time())
|
|
||||||
->sign($signer, env('APP_KEY'))
|
|
||||||
->getToken();
|
|
||||||
|
|
||||||
return $token;
|
return $config->builder()
|
||||||
|
->issuedAt(new DateTimeImmutable())
|
||||||
|
->withClaim('client_id', 'https://quill.p3k.io')
|
||||||
|
->withClaim('me', 'https://jonnybarnes.localhost')
|
||||||
|
->withClaim('scope', 'create update')
|
||||||
|
->getToken($config->signer(), $config->signingKey())
|
||||||
|
->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTokenWithIncorrectScope()
|
public function getTokenWithIncorrectScope()
|
||||||
{
|
{
|
||||||
$signer = new Sha256();
|
$config = $this->app->make(Configuration::class);
|
||||||
$token = (new Builder())
|
|
||||||
->set('client_id', 'https://quill.p3k.io')
|
|
||||||
->set('me', 'https://jonnybarnes.localhost')
|
|
||||||
->set('scope', 'view') //error here
|
|
||||||
->set('issued_at', time())
|
|
||||||
->sign($signer, env('APP_KEY'))
|
|
||||||
->getToken();
|
|
||||||
|
|
||||||
return $token;
|
return $config->builder()
|
||||||
|
->issuedAt(new DateTimeImmutable())
|
||||||
|
->withClaim('client_id', 'https://quill.p3k.io')
|
||||||
|
->withClaim('me', 'https://jonnybarnes.localhost')
|
||||||
|
->withClaim('scope', 'view')
|
||||||
|
->getToken($config->signer(), $config->signingKey())
|
||||||
|
->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTokenWithNoScope()
|
public function getTokenWithNoScope()
|
||||||
{
|
{
|
||||||
$signer = new Sha256();
|
$config = $this->app->make(Configuration::class);
|
||||||
$token = (new Builder())
|
|
||||||
->set('client_id', 'https://quill.p3k.io')
|
|
||||||
->set('me', 'https://jonnybarnes.localhost')
|
|
||||||
->set('issued_at', time())
|
|
||||||
->sign($signer, env('APP_KEY'))
|
|
||||||
->getToken();
|
|
||||||
|
|
||||||
return $token;
|
return $config->builder()
|
||||||
|
->issuedAt(new DateTimeImmutable())
|
||||||
|
->withClaim('client_id', 'https://quill.p3k.io')
|
||||||
|
->withClaim('me', 'https://jonnybarnes.localhost')
|
||||||
|
->getToken($config->signer(), $config->signingKey())
|
||||||
|
->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInvalidToken()
|
public function getInvalidToken()
|
||||||
|
|
Loading…
Add table
Reference in a new issue