2 Commits
3.0.1 ... 3.1.1

Author SHA1 Message Date
1elf-me
32990da8a0 updated oauth-public.key 2021-03-20 17:02:35 +01:00
1elf-me
7805933b10 add CheckClientCredentials middleware 2021-03-20 16:48:50 +01:00
5 changed files with 141 additions and 2 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
vendor
.phpunit.result.cache
.idea
.idea
composer.lock

View File

@@ -14,7 +14,8 @@
"illuminate/support": "^8.0",
"illuminate/console": "^8.0",
"guzzlehttp/guzzle": "^6.3|^7.0.1",
"socialiteproviders/manager": "^3.4"
"socialiteproviders/manager": "^3.4",
"firebase/php-jwt": "^5.2"
},
"require-dev": {
"phpunit/phpunit": "^8.0",

14
oauth-public.key Normal file
View File

@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3gKvEGl/CdMihkhttsZX
gbnT9Rj+m3d1nI1UG5T2kpzUx5fjnXA70Bfw/wrPyUDucXgTfPro98mZczCvWzY+
8EUF3zOM8BUaMOBEPUJV1Kb7mmGX6JI79KgEj5xBnQMNyEg+D6ZiUT7vu/I4JYik
TfPHzOz2d6w9g5a02aOKC/PXDjs+G16I6YKxKWNC1vMj4K1/1XNlkN4iu7e0AThQ
CcyrAB2qGSgJdEMJTsSB7WmknRZuc69nIpXdWoX1ctdjBiXoEh/C23SmXREX6/oP
KeLoT4qy3TkD2Z2sD+ytTDXuhp2HLL01NtUap3QUkriG/GdtT9Xa/AYYrNLYUDQG
LpYZU3EG+YLe2AmauouPGKiuHwgHix1yZ5x3iHhAsS8r5ZvumdnaJMB05TgE6sXe
Q5dG9TOHsIT9lLduFHpZOg4MjOt0Oj3/IdeP1wXN/JxWbEebkW42vyfXEtD20kbx
J3TcKEEB2YSg9qZzk7vvRkdzJCKA2Dmj0sZcRsSK0rYAP0kL7gLWAH3At3sD57cx
7i+Hi2lFbK4xRu1hcqpAcu5SPBSBB6lbyaW1XY6u8chc/zVyYdsXzyWBHx9P/Dkh
m6kBNv8/HfSz0ZwRPH4Dav57DEnaZPIXaXOE4e4S5BooPL9i7Stz7DkStteZoM09
y8bcxEnkdxqOnHc0cYZvPlsCAwEAAQ==
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,41 @@
<?php
namespace GhostZero\BitinflowAccounts\Exceptions;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Arr;
class MissingScopeException extends AuthorizationException
{
/**
* The scopes that the user did not have.
*
* @var array
*/
protected $scopes;
/**
* Create a new missing scope exception.
*
* @param array|string $scopes
* @param string $message
*
* @return void
*/
public function __construct($scopes = [], $message = 'Invalid scope(s) provided.')
{
parent::__construct($message);
$this->scopes = Arr::wrap($scopes);
}
/**
* Get the scopes that the user did not have.
*
* @return array
*/
public function scopes()
{
return $this->scopes;
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace GhostZero\BitinflowAccounts\Http\Middleware;
use Closure;
use Firebase\JWT\JWT;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Request;
use GhostZero\BitinflowAccounts\Exceptions\MissingScopeException;
use stdClass;
use Throwable;
class CheckClientCredentials
{
public const ALLOWED_ALGORITHMS = ['RS256'];
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @param mixed ...$scopes
*
* @throws AuthenticationException|MissingScopeException
*
* @return mixed
*/
public function handle($request, Closure $next, ...$scopes)
{
JWT::$leeway = 60;
try {
$decoded = JWT::decode(
$request->bearerToken(),
$this->getOauthPublicKey(),
self::ALLOWED_ALGORITHMS
);
} catch (Throwable $exception) {
throw new AuthenticationException();
}
$request->attributes->set('oauth_access_token_id', $decoded->jti);
$request->attributes->set('oauth_client_id', $decoded->aud);
$request->attributes->set('oauth_client_trusted', $decoded->client->trusted);
$request->attributes->set('oauth_user_id', $decoded->sub);
$request->attributes->set('oauth_scopes', $decoded->scopes);
$this->validateScopes($decoded, $scopes);
return $next($request);
}
private function getOauthPublicKey()
{
return file_get_contents(__DIR__ . '/../../../../../oauth-public.key');
}
/**
* Validate token credentials.
*
* @param stdClass $token
* @param array $scopes
*
* @throws MissingScopeException
*
* @return void
*/
protected function validateScopes(stdClass $token, array $scopes)
{
if (empty($scopes) || in_array('*', $token->scopes)) {
return;
}
foreach ($scopes as $scope) {
if (in_array($scope, $token->scopes)) {
return;
}
}
throw new MissingScopeException($scopes);
}
}