Skip to main content
The AuthenticationMiddleware acts as the first gate in your security pipeline. Its primary job is to extract a token (usually from the Authorization header) and verify it.

Overview

Unlike many frameworks, Apivalk does not throw exceptions if authentication fails in this middleware. Instead:
  1. It attempts to authenticate the token using an AuthenticatorInterface.
  2. If successful, it sets a UserAuthIdentity on the Request.
  3. If it fails or no token is provided, the Request remains with its default GuestAuthIdentity.
This “passive” authentication allows you to support both public and private routes on the same endpoint, delegating the final authorization decision to the Security Middleware. For a complete picture of how authentication and authorization work together, see the Security Overview.

Usage

To use it, you must provide an implementation of the AuthenticatorInterface.

JWT / OAuth Example

If you are using JWT with JWKS (e.g., Auth0, Okta, Azure AD), use the JwtAuthenticator.
use apivalk\apivalk\Security\Authenticator\JwtAuthenticator;
use apivalk\apivalk\Middleware\AuthenticationMiddleware;

$authenticator = new JwtAuthenticator(
    'https://your-domain.com/.well-known/jwks.json',
    $cache, // Instance of CacheInterface or null
    'https://your-issuer.com/',
    'your-audience'
);

$middleware = new AuthenticationMiddleware($authenticator);
$configuration->addMiddleware($middleware);

Custom Authentication Logic

If you have custom authentication needs (e.g., API Keys in database), you can implement your own authenticator or middleware.

Implementing a Custom Authenticator

use apivalk\apivalk\Security\Authenticator\AuthenticatorInterface;
use apivalk\apivalk\Security\AuthIdentity\UserAuthIdentity;
use apivalk\apivalk\Security\Scope;

class ApiKeyAuthenticator implements AuthenticatorInterface
{
    public function authenticate(string $token): ?AbstractAuthIdentity
    {
        $user = $this->db->findUserByApiKey($token);
        
        if (!$user) {
            return null;
        }

        return new UserAuthIdentity(
            $user->id,
            [new Scope('read'), new Scope('write')]
        );
    }
}

Implementing a Custom Middleware

If you want full control over the process, you can implement the MiddlewareInterface directly and use setAuthIdentity() on the request.
class CustomAuthMiddleware implements MiddlewareInterface
{
    public function process($request, $controllerClass, $next): AbstractApivalkResponse
    {
        $id = $this->session->get('user_id');
        
        if ($id) {
            $identity = new UserAuthIdentity($id, [new Scope('user')]);
            $request->setAuthIdentity($identity);
        }

        return $next($request);
    }
}

Important: Middleware Ordering

The AuthenticationMiddleware MUST run BEFORE the SecurityMiddleware. The authentication middleware populates the “Who” (Identity), while the security middleware validates the “What” (Scopes). If run out of order, the security middleware will always see a GuestAuthIdentity.
// CORRECT ORDER
$configuration->addMiddleware(new AuthenticationMiddleware($jwtAuth));
$configuration->addMiddleware(new SecurityMiddleware());