| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- <?php
- namespace Middlewares;
- use Libs\ResponseLib;
- use Psr\Http\Message\ServerRequestInterface;
- class ExternalJwtAuthMiddleware
- {
- private string $verifyUrl;
- private int $timeoutSeconds;
- public function __construct(string $verifyUrl)
- {
- $this->verifyUrl = $verifyUrl;
- $this->timeoutSeconds = (int)($_ENV['EXTERNAL_AUTH_TIMEOUT'] ?? 5);
- }
- public function __invoke(ServerRequestInterface $request, callable $next)
- {
- // Require Authorization: Bearer <token>
- $authHeader = $request->getHeaderLine('Authorization');
- if (empty($authHeader) || !preg_match('/Bearer\s+(.*)/', $authHeader, $matches)) {
- return ResponseLib::sendFail('Unauthorized: Missing or invalid Authorization header', [], 'E_VALIDATE')->withStatus(401);
- }
- // Call external service
- [$ok, $payload, $status, $err] = $this->callExternalVerify($this->verifyUrl, $authHeader);
- if (!$ok) {
- $message = 'Unauthorized';
- if ($status >= 500 || $err) {
- $message = 'Auth service error';
- }
- return ResponseLib::sendFail($message, ['status' => $status, 'error' => $err], 'E_VALIDATE')->withStatus(401);
- }
- // Attach attributes from response if present
- if (is_array($payload)) {
- if (isset($payload['sub'])) {
- $request = $request->withAttribute('api_user_id', $payload['sub']);
- }
- if (isset($payload['username'])) {
- $request = $request->withAttribute('api_user', $payload['username']);
- }
- }
- $request = $request->withAttribute('external_auth', true);
- return $next($request);
- }
- private function callExternalVerify(string $url, string $authorization): array
- {
- $ch = curl_init($url);
- curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_HEADER => true,
- CURLOPT_NOBODY => false,
- CURLOPT_CUSTOMREQUEST => 'GET',
- CURLOPT_HTTPHEADER => [
- 'Authorization: ' . $authorization,
- 'Accept: application/json'
- ],
- CURLOPT_TIMEOUT => $this->timeoutSeconds,
- CURLOPT_CONNECTTIMEOUT => min(2, $this->timeoutSeconds),
- ]);
- $response = curl_exec($ch);
- if ($response === false) {
- $err = curl_error($ch);
- curl_close($ch);
- return [false, null, 0, $err];
- }
- $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
- $body = substr($response, $headerSize);
- curl_close($ch);
- $ok = ($status >= 200 && $status < 300);
- $payload = null;
- if ($body !== '') {
- $decoded = json_decode($body, true);
- if (json_last_error() === JSON_ERROR_NONE) {
- $payload = $decoded;
- } else {
- $payload = $body;
- }
- }
- return [$ok, $payload, $status, null];
- }
- }
|