AxiamMiddleware
in package
Laravel authentication middleware (D-02, CONTRACT.md §10): extracts the bearer/cookie token, verifies it via {@see AxiamClient::verifyLocallyOrFallback()} — local JWKS verification first, falling back to the shared single-flight refresh (§9, D-06) — and populates the `axiam_user` request attribute with `user_id`/`tenant_id`/`roles` on success. Returns a standardized 401 JSON error body on any failure (missing token, invalid signature, expired-and-unrefreshable token). Never duplicates JWKS-verify or refresh logic itself (D-02 prohibition) — every security-critical decision is made by {@see AxiamClient}.
Type-hinted against Symfony\Component\HttpFoundation\Request rather than
Illuminate\Http\Request: a real Illuminate\Http\Request instance IS a
Symfony\Component\HttpFoundation\Request (it directly extends it, adding only
Laravel-specific convenience methods this class does not need), so Laravel's own HTTP
kernel/pipeline can call handle($request, $next) with its real request object
unchanged. This keeps the class's own dependency footprint to a package every Laravel
installation already ships transitively (via illuminate/http), without requiring a
new illuminate/http dev/runtime dependency just to type-hint the parameter (D-01:
illuminate/* stays dev-only, and only the packages actually needed are declared).
CSRF (cookie double-submit, CONTRACT.md §3): when the credential was sourced from the
axiam_access COOKIE (not the Authorization header) and the request method is
state-changing (anything other than GET/HEAD/OPTIONS), this middleware additionally
requires the X-CSRF-Token request header to be present and equal (constant-time) to
the axiam_csrf cookie value, rejecting with 403 on mismatch/absence. Bearer-header
requests are CSRF-immune by construction — a cross-site attacker cannot set arbitrary
request headers — but a cookie automatically attached by the browser is not, and in
any same-site deployment where axiam_access reaches this app, the non-httpOnly
axiam_csrf cookie does too. This mirrors, locally, the same double-submit check the
AXIAM server performs on its own endpoints (§3).
Table of Contents
Methods
- __construct() : mixed
- handle() : mixed
- Authenticates the inbound request and, for cookie-authenticated writes, enforces CSRF.
Methods
__construct()
public
__construct(AxiamClient $client, string $tenant) : mixed
Parameters
- $client : AxiamClient
-
Client used to verify the presented token against the cached JWKS.
- $tenant : string
-
Tenant slug the verified token's claim must match (cross-tenant control: a JWKS is organization-wide, so a valid signature alone never implies tenant authorization).
handle()
Authenticates the inbound request and, for cookie-authenticated writes, enforces CSRF.
public
handle(Request $request, Closure $next) : mixed
Sequence: extract the credential (Authorization: Bearer first, then the axiam_access
cookie) → verify the JWT locally → enforce the cross-tenant claim check → inject the
identity → call the next middleware.
CSRF (CONTRACT.md §3a): when the credential came from the COOKIE and the method is
state-changing (not GET/HEAD/OPTIONS), the X-CSRF-Token header must be present and equal
(constant-time) to the axiam_csrf cookie, else the request is rejected with 403.
Bearer-authenticated requests are exempt — a cross-site attacker cannot set custom headers.
Parameters
- $request : Request
-
Inbound request.
- $next : Closure
-
Next middleware in the pipeline.
Return values
mixed —The next middleware's response, or a 401/403 JSON error response.