laravel/framework · warning · OriginMismatchException
Origin mismatch.
Error message
Origin mismatch.
What it means
Within hasValidOrigin(), if the Sec-Fetch-Site header is neither 'same-origin' nor (when allowed) 'same-site', and the static flag PreventRequestForgery::$originOnly is true, an OriginMismatchException is thrown. This is the strict, token-free mode that relies purely on the browser's Fetch Metadata to deny cross-origin requests. Unlike TokenMismatchException it is not auto-converted to 419; it surfaces as a 403.
Source
Thrown at src/Illuminate/Foundation/Http/Middleware/PreventRequestForgery.php:156
* @param \Illuminate\Http\Request $request
* @return bool
*
* @throws \Illuminate\Http\Exceptions\OriginMismatchException
*/
protected function hasValidOrigin($request)
{
$secFetchSite = $request->header('Sec-Fetch-Site');
if ($secFetchSite === 'same-origin') {
return true;
}
if ($secFetchSite === 'same-site' && static::$allowSameSite) {
return true;
}
if (static::$originOnly) {
throw new OriginMismatchException('Origin mismatch.');
}
return false;
}
/**
* Determine if the session and input CSRF tokens match.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function tokensMatch($request)
{
$token = $this->getTokenFromRequest($request);
return is_string($request->session()->token()) &&
is_string($token) &&
hash_equals($request->session()->token(), $token);View on GitHub (pinned to e0f6eb3518)
Solutions
- Move API/webhook routes out of the web middleware stack (use api guard or Sanctum) so PreventRequestForgery does not run on them.
- If same-site subdomain requests must pass, enable PreventRequestForgery::allowSameSite().
- Add the affected URIs to $except and protect them with a different mechanism (signature, bearer token).
- Turn off originOnly if you genuinely need cross-origin browser requests: PreventRequestForgery::originOnly(false).
Example fix
// before PreventRequestForgery::originOnly(); // webhook POST from third party -> OriginMismatchException // after — exclude the webhook, validate signature separately PreventRequestForgery::except(['/webhooks/stripe']); // and in the controller, abort_unless(hash_equals($known, $sig), 403);
Defensive patterns
Strategy: validation
Validate before calling
// On the caller side, only send state-changing requests from a browser same-origin context, // or move API/webhook routes out of the PreventRequestForgery middleware. PreventRequestForgery::except(['/api/*', '/webhooks/*']);
Type guard
// Server-side guard for non-browser callers: rely on bearer tokens instead of Fetch Metadata
if ($request->bearerToken() && $request->user('sanctum')) { /* bypass origin check */ } Try / catch
use Illuminate\Http\Exceptions\OriginMismatchException;
try {
$response = $next($request);
} catch (OriginMismatchException $e) {
// surface 403; do NOT widen trust — fix routing or use bearer auth
} Prevention
- Do not enable originOnly for routes consumed by non-browser clients.
- Allow same-site subdomains with PreventRequestForgery::allowSameSite() when needed.
- Prefer Sanctum bearer tokens for cross-origin API access.
- Document which routes are browser-only so backend consumers know to use the API stack.
When it happens
Trigger: originOnly mode is enabled (e.g. PreventRequestForgery::originOnly()) AND a request arrives with Sec-Fetch-Site: cross-site or no Sec-Fetch-Site header at all. Common with non-browser clients (curl, Postman, server-to-server) that never send Fetch Metadata headers.
Common situations: Mixing originOnly strict mode with API/webhook consumers that are not browsers. Browsers that suppress Sec-Fetch-Site (older versions, some privacy extensions). Webhooks from third parties hitting originOnly-guarded routes.
Related errors
- CSRF token mismatch.
- Callback must be a callable, callback array, or a 'Class@met
- Auth guard [{$name}] is not defined.
- Auth driver [{$config['driver']}] for guard [{$name}] is not
- Unable to bind custom driver callback
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/961879e6b253b95c.
Report an issue: GitHub.