Skip to main content
The SecurityMiddleware is the core authorization engine of Apivalk. It ensures that the current requester has the necessary scopes and permissions to access a specific route. For a deep dive into the underlying architecture, check the Security Overview.

How it Works

The middleware retrieves the Route object from the controller being called and examines its RouteAuthorization.

Authorization Logic

A route can have a RouteAuthorization object that defines:
  1. Security Scheme: The name of the security scheme required (e.g., BearerAuth). This name must match a SecuritySchemeObject defined in your ComponentsObject so the generated OpenAPI spec correctly links the route to its authentication method. See Security Schemes and Components for full setup examples.
  2. Scopes: A list of required scopes.
  3. Permissions: A list of required permissions.
The current Identity must possess all the required scopes and permissions to be granted access.

Route Examples

Public Route (No Authorization)

A route that is accessible by anyone. When no RouteAuthorization is defined, the middleware passes the request through without any checks.
$route = Route::get('/about')->description('About page');

Authenticated Route (Any Valid Token)

A route that requires the user to be authenticated but does not enforce any specific scopes or permissions. Pass only the security scheme name to RouteAuthorization. The middleware will return 401 Unauthorized for anonymous users but allow any authenticated identity through.
use apivalk\apivalk\Router\Route\Route;
use apivalk\apivalk\Security\RouteAuthorization;

$route = Route::get('/me/profile')
    ->description('Get my profile')
    ->routeAuthorization(new RouteAuthorization('BearerAuth'));

Scoped Route (Specific Scopes and Permissions)

A route that requires a logged-in user with specific scopes and permissions.
use apivalk\apivalk\Router\Route\Route;
use apivalk\apivalk\Security\RouteAuthorization;

$route = Route::get('/admin/dashboard')
    ->description('Admin Dashboard')
    ->routeAuthorization(
        new RouteAuthorization('BearerAuth', ['admin'], ['admin:dashboard:read'])
    );

Optional Security (Public with Identity)

If you want a route to be public but also optionally use identity information when a token is provided, leave RouteAuthorization as null. The AuthenticationMiddleware will still populate the identity if a valid token is present — you can check $request->getAuthIdentity()->isAuthenticated() in your controller to adapt behavior.

Status Codes

When authorization fails, the middleware returns an error response directly — it does not throw. The status code depends on whether the request was authenticated:
  1. 401 Unauthorized: Returned when a GuestAuthIdentity (anonymous user) attempts to access a route that requires security.
  2. 403 Forbidden: Returned when an authenticated identity (e.g. JwtAuthIdentity) does not have the required scopes or permissions for the route.

Scopes and Permissions

While many frameworks use roles (e.g., ROLE_ADMIN), Apivalk follows the OpenAPI standard of using Scopes and Permissions. Scopes and permissions are more granular and describe what an identity is allowed to do (e.g., read:users) rather than who they are.

Integration

The SecurityMiddleware should always be placed after your authentication middleware in the stack.
$configuration->getMiddlewareStack()->add(new AuthenticationMiddleware($authenticator));
$configuration->getMiddlewareStack()->add(new SecurityMiddleware());