header('Authorization'); if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) { return response()->json([ 'status' => 'failure', 'message' => 'Missing or invalid Authorization header' ], 401); } $token = substr($authHeader, 7); try { $decoded = JWT::decode($token, new Key(config('intaleq.jwt_secret'), 'HS256')); // Verify issuer (defense in depth) $iss = $decoded->iss ?? ''; if (!in_array($iss, ['Tripz', 'Tripz-Wallet'])) { return response()->json([ 'status' => 'failure', 'message' => 'Invalid token issuer' ], 401); } // Attach JWT claims to request attributes (internal, not spoofable via POST/GET) $request->attributes->set('_jwt_user_id', $decoded->user_id ?? null); $request->attributes->set('_jwt_user_type', $decoded->user_type ?? null); $request->attributes->set('_jwt_fingerprint', $decoded->fingerprint ?? null); return $next($request); } catch (ExpiredException $e) { return response()->json([ 'status' => 'failure', 'message' => 'Token expired' ], 401); } catch (\Exception $e) { return response()->json([ 'status' => 'failure', 'message' => 'Invalid token' ], 401); } } }