mirror of
https://github.com/bitinflow/accounts.git
synced 2026-03-13 13:35:52 +00:00
add CheckClientCredentials middleware
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
vendor
|
||||
.phpunit.result.cache
|
||||
.idea
|
||||
.idea
|
||||
composer.lock
|
||||
@@ -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",
|
||||
|
||||
0
oauth-public.key
Normal file
0
oauth-public.key
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user