> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apivalk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Middleware

> The Security Middleware enforces scope-based authorization as defined in your OpenAPI route specifications.

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](/security/index).

## 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](/documentation/openapi-generator#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](/security/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.

```php theme={null}
$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.

```php theme={null}
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.

```php theme={null}
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](/security/identity) (anonymous user) attempts to access a route that requires security.
2. **403 Forbidden**: Returned when an authenticated identity (e.g. [JwtAuthIdentity](/security/identity)) 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.

```php theme={null}
$configuration->getMiddlewareStack()->add(new AuthenticationMiddleware($authenticator));
$configuration->getMiddlewareStack()->add(new SecurityMiddleware());
```
