diff --git a/assets/components/misSession.js b/assets/components/misSession.js
new file mode 100644
index 0000000..45088ef
--- /dev/null
+++ b/assets/components/misSession.js
@@ -0,0 +1,118 @@
+/**
+ * MIS (webSDK / widget.sovamed.ru) session helpers.
+ * Symfony login (ROLE_USER) and MIS session are independent.
+ */
+
+function MisSessionError() {
+    this.name = 'MisSessionError';
+    this.message = 'MIS session is not authenticated';
+}
+
+function isAuthenticated(webSDK) {
+    return Boolean(webSDK?.data?.user?.authenticated);
+}
+
+function ensureAuthenticated(webSDK) {
+    return new Promise(function(resolve, reject) {
+        if (isAuthenticated(webSDK)) {
+            resolve(webSDK);
+            return;
+        }
+
+        if (typeof webSDK?.isLoggedIn === 'function') {
+            webSDK.isLoggedIn(webSDK.sdkOrigin).then(function(result) {
+                if (result?.authenticated) {
+                    resolve(webSDK);
+                    return;
+                }
+                reject(new MisSessionError());
+            }).catch(function() {
+                reject(new MisSessionError());
+            });
+            return;
+        }
+
+        reject(new MisSessionError());
+    });
+}
+
+function removeSdkOverlayModals() {
+    document.querySelectorAll('.wr-sdk-widget-modal').forEach(function(modal) {
+        modal.remove();
+    });
+}
+
+/**
+ * Move #iframeProtocol from SDK overlay into cabinet bootstrap popup.
+ * openConference() must be called without container (SDK applies Guest URL fix).
+ */
+function mountConferenceInPopup(popup) {
+    var iframe = document.getElementById('iframeProtocol');
+    var popupBody = popup?.querySelector('#popup-body');
+
+    if (!iframe || !popupBody) {
+        return false;
+    }
+
+    removeSdkOverlayModals();
+    popupBody.innerHTML = '';
+    popupBody.appendChild(iframe);
+    iframe.style.width = '100%';
+    iframe.style.border = 'none';
+    iframe.style.height = (window.innerHeight - 100) + 'px';
+
+    var fullScreenBtn = popup.querySelector('.full-scren-modal');
+    if (fullScreenBtn) {
+        fullScreenBtn.classList.remove('d-none');
+    }
+
+    popup.querySelector('.modal-dialog').classList = 'modal-dialog';
+    popup.querySelector('.modal-content').classList = 'modal-content';
+    popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
+
+    if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
+        $(popup).modal('show');
+    }
+
+    return true;
+}
+
+function showMisSessionExpired(popup) {
+    if (!popup) {
+        window.location.pathname = '/logout';
+        return;
+    }
+
+    popup.querySelector('.modal-dialog').classList = 'modal-dialog';
+    popup.querySelector('.modal-title').innerHTML = 'Сессия виджета истекла';
+    popup.querySelector('#popup-body').innerHTML =
+        '<p class="mb-3">Личный кабинет открыт, но сессия виджета записи (MIS) истекла. ' +
+        'Для оплаты и онлайн-приёма нужно войти снова — повторная авторизация в iframe не требуется.</p>' +
+        '<button type="button" class="btn btn-outline-secondary w-100" id="mis-session-relogin">Войти снова</button>';
+
+    popup.querySelector('#mis-session-relogin').addEventListener('click', function() {
+        window.location.pathname = '/logout';
+    });
+
+    if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
+        $(popup).modal('show');
+    }
+}
+
+function handleMisSessionFailure(popup, error, logContext) {
+    if (error instanceof MisSessionError || error?.name === 'MisSessionError') {
+        showMisSessionExpired(popup);
+        return true;
+    }
+
+    return false;
+}
+
+module.exports = {
+    MisSessionError: MisSessionError,
+    isAuthenticated: isAuthenticated,
+    ensureAuthenticated: ensureAuthenticated,
+    mountConferenceInPopup: mountConferenceInPopup,
+    showMisSessionExpired: showMisSessionExpired,
+    handleMisSessionFailure: handleMisSessionFailure,
+};
diff --git a/assets/controllers/caseHistory_controller.js b/assets/controllers/caseHistory_controller.js
index 735c13c..aabafb1 100644
--- a/assets/controllers/caseHistory_controller.js
+++ b/assets/controllers/caseHistory_controller.js
@@ -2,6 +2,7 @@ import { Controller } from 'stimulus';
 import Cookies from 'js-cookie';
 const loader = require("./../components/loader.js");
 const helper = require("./../components/helper.js");
+const misSession = require("./../components/misSession.js");
 
 /*
  * This is an example Stimulus controller!
@@ -248,20 +249,23 @@ export default class extends Controller {
                     btnConfirence.setAttribute('data-filial' , data.filial)
                     btnConfirence.addEventListener('click', function () {
                         popup.querySelector('#popup-body').innerHTML = '';
-                        
-                        webSDK.openConference({
-                            schedid: btnConfirence.dataset.id,
-                            container: popup.querySelector('#popup-body')
-                        }).then(function () {
-                            popup.querySelector('.full-scren-modal').classList.remove('d-none');
-                            document.getElementById('iframeProtocol').style.height =  (window.innerHeight - 100) + 'px';
-                            popup.querySelector('.modal-dialog').classList = 'modal-dialog';
-                            popup.querySelector('.modal-content').classList = 'modal-content';
-                            popup.querySelector('.modal-content').classList = 'modal-content';
-                            popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
 
-                            $(popup).modal('show');
+                        misSession.ensureAuthenticated(webSDK).then(function() {
+                            return webSDK.openConference({
+                                schedid: btnConfirence.dataset.id
+                            });
+                        }).then(function () {
+                            if (!misSession.mountConferenceInPopup(popup)) {
+                                throw { data: { message: 'Не удалось открыть окно онлайн-консультации.' } };
+                            }
                         }).catch(function (e) {
+                            if (misSession.handleMisSessionFailure(popup, e)) {
+                                helper.sendRequest({
+                                    data: {'error': e, method: 'openConference', reason: 'mis_session_expired'}
+                                }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+                                return;
+                            }
+
                             if (typeof e.data?.message !== 'undefined') {
                                 var msg = e.data.message.replace('UTC+3', 'UTC+3 (московское время)');
                                 popup.querySelector('#popup-body').innerHTML = msg;
@@ -272,9 +276,9 @@ export default class extends Controller {
                             }
 
                             helper.sendRequest({
-                                        data: {'error': e, method: 'openConference'}
-                                    }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
-                            });
+                                data: {'error': e, method: 'openConference'}
+                            }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+                        });
                     });
 
                 } else {
@@ -376,7 +380,6 @@ export default class extends Controller {
                     btnPayment.setAttribute('data-amt' , data.payment.amt);
                     btnPayment.setAttribute('data-payprofileid' , data.payment.magazineId);
                     btnPayment.addEventListener('click', function () {
-
                         var params = {
                             'orderid': Number(btnPayment.dataset.id) ,
                             'payprofileid': btnPayment.dataset.payprofileid,
@@ -386,14 +389,26 @@ export default class extends Controller {
                             'pcode': webSDK.data.user.id,
                             'successurl': document.location.origin + '/case-history#pay-success',
                             'errorurl': document.location.origin + '/case-history#error',
-                            'containerId': 'popup-body', 
+                            'containerId': 'popup-body',
                         };
 
-                        webSDK.loadPaymentView(params);
+                        misSession.ensureAuthenticated(webSDK).then(function() {
+                            webSDK.loadPaymentView(params);
+                            popup.querySelector('#popup-body').innerHTML = '';
+                            popup.querySelector('.modal-title').innerHTML = 'Оплата';
+                            $(popup).modal('show');
+                        }).catch(function(e) {
+                            if (misSession.handleMisSessionFailure(popup, e)) {
+                                helper.sendRequest({
+                                    data: {'error': e, method: 'loadPaymentView', reason: 'mis_session_expired'}
+                                }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+                                return;
+                            }
 
-                        popup.querySelector('#popup-body').innerHTML = '';
-                        popup.querySelector('.modal-title').innerHTML = 'Оплата';
-                        $(popup).modal('show');
+                            helper.sendRequest({
+                                data: {'error': e, method: 'loadPaymentView'}
+                            }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
+                        });
                     });
                 } else {
                     btnPayment.classList.add('d-none');
