Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BCrwHHnGCB5XH968Nxokqw
40 lines
1.7 KiB
PHP
40 lines
1.7 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Middleware;
|
||
|
||
use App\Ingest\EventUpserter;
|
||
use Closure;
|
||
use Illuminate\Http\Request;
|
||
use Symfony\Component\HttpFoundation\IpUtils;
|
||
use Symfony\Component\HttpFoundation\Response;
|
||
|
||
/**
|
||
* Доверяет X-Remote-User от Caddy forward_auth — и только ему: заголовок принимается,
|
||
* если TCP-сосед (REMOTE_ADDR, не X-Forwarded-For) из HADO_TRUSTED_PROXIES. Порт hado
|
||
* виден и из тейлнета (агент), оттуда подделать SSO-заголовок нельзя.
|
||
* На публичных маршрутах (/api, /a, /hooks, /mcp) этот middleware не стоит.
|
||
*/
|
||
class RemoteUser
|
||
{
|
||
public function __construct(private readonly EventUpserter $users) {}
|
||
|
||
public function handle(Request $request, Closure $next): Response
|
||
{
|
||
$login = trim((string) $request->header('X-Remote-User', ''));
|
||
if ($login !== '' && ! IpUtils::checkIp((string) $request->server('REMOTE_ADDR'), config('hado.trusted_proxies'))) {
|
||
return response()->json(['message' => 'X-Remote-User принимается только от прокси'], 401);
|
||
}
|
||
if ($login === '' && app()->environment('local')) {
|
||
// Dev без хаба: HADO_DEV_USER подставляет пользователя. В проде не работает.
|
||
$login = trim((string) config('hado.dev_user'));
|
||
}
|
||
if ($login === '') {
|
||
return response()->json(['message' => 'Нет X-Remote-User: запрос должен идти через хаб'], 401);
|
||
}
|
||
|
||
$request->attributes->set('user', $this->users->ensureUser($login));
|
||
|
||
return $next($request);
|
||
}
|
||
}
|