extractRouteCallable($handler); if ($callable === null) { // If no callable is available, delegate to the next handler. return $handler->handle($request); } /** @var Controller $class Controller instance resolved from the route. */ [$class, $method] = $callable; // Ensure the controller exists and the method is defined before reflecting. if (class_exists($class::class)) { $reflectionClass = new \ReflectionClass($class); if ($reflectionClass->hasMethod($method)) { $reflectionMethod = $reflectionClass->getMethod($method); // Fetch all Scope attributes declared on the method. $attributes = $reflectionMethod->getAttributes(Scope::class); $requireAllAttributes = $reflectionMethod->getAttributes(RequireAllScopes::class); if (empty($attributes)) { // No scope attributes; delegate to the next handler. return $handler->handle($request); } $requiredScopes = []; $userScopes = []; $requireAll = false; foreach ($attributes as $attribute) { /** @var Scope $scopeInstance Concrete Scope attribute instance. */ $scopeInstance = $attribute->newInstance(); $requiredScopes = array_merge($requiredScopes, $scopeInstance->getScopes()); // If any attribute requires all scopes, set the flag. $requireAll = $requireAll || !empty($requireAllAttributes); $scopes = $request->getAttribute($scopeInstance->getClaim()); if (!is_array($scopes)) { // If user scopes are not an array, treat as no scopes provided. $scopes = explode($scopeInstance->getSeparator(), (string) $scopes); } $userScopes = array_merge( $userScopes, $scopes ); } $userScopes = array_unique($userScopes); // Deny if any required scope is missing from the user's scopes. if ( (!$requireAll && array_intersect($userScopes, $requiredScopes) === []) || ($requireAll && array_diff($requiredScopes, $userScopes) !== []) ) { return JsonResponseFactory::createJsonResponse([ 'error' => 'insufficient_scope', 'error_description' => 'The request requires higher privileges than provided by the access token.' ], CodesEnum::FORBIDDEN); } } } // All checks passed; continue down the middleware pipeline. return $handler->handle($request); } }