Menggunakan MSAL di aplikasi iframed

Secara default, MSAL mencegah pengalihan bingkai penuh ke titik akhir autentikasi Microsoft Entra ID saat aplikasi dirender di dalam iframe, yang berarti Anda tidak dapat menggunakan API pengalihan untuk interaksi pengguna dengan IdP:

  • Pembatasan ini diberlakukan karena Microsoft Entra ID akan menolak untuk merender permintaan apa pun yang memerlukan interaksi pengguna (misalnya entri kredensial, persetujuan, keluar, dll.) dalam iframe dengan melemparkan X-FRAME OPTIONS SET TO DENYkesalahan, langkah yang diambil untuk mencegah serangan clickjacking.
  • Sebagai gantinya, Anda harus mengandalkan API popup MSAL jika interaksi pengguna diperlukan, dan/atau API senyap (ssoSilent(), acquireTokenSilent()) jika interaksi pengguna dapat dihindari.
  • Demikian pula, Anda harus menggunakan API logoutPopup() untuk keluar (:warning: jika aplikasi Anda menggunakan versi yang lebih lama dari msal-browser v2.13, pastikan untuk meningkatkan dan mengganti logout() API, karena akan mencoba pengalihan bingkai penuh ke Microsoft Entra ID).
  • Saat menggunakan API popup, Anda perlu memperhitungkan batasan kotak pasir apa pun yang diberlakukan oleh aplikasi induk. Secara khusus, aplikasi induk perlu mengatur flag allow-popups saat iframe berada dalam mode sandbox.

Azure AD B2C menawarkan pengalaman masuk yang disematkan, yang memungkinkan penyajian UI masuk kustom dalam iframe. Karena MSAL mencegah pengalihan di iframe secara default, Anda harus mengatur opsi konfigurasi allowRedirectInIframe ke true untuk menggunakan fitur ini. Perhatikan bahwa mengaktifkan opsi ini untuk aplikasi di Microsoft Entra ID tidak disarankan, karena pembatasan di atas.

Pembatasan peramban

Karena cookie sesi Microsoft Entra dalam iframe dianggap sebagai cookie pihak ketiga, browser tertentu (misalnya Safari atau Chrome dalam mode incognito) akan memblokir atau menghapus cookie ini secara default. Ini akan memengaruhi pengalaman single sign-on pada aplikasi yang dimuat dalam iframe karena aplikasi tersebut tidak akan memiliki akses ke cookie sesi IdP (lihat: Single sign-on).

Selain itu, ketika cookie pihak ke-3 dinonaktifkan di Chrome, aplikasi MSAL iframed tidak akan memiliki akses ke penyimpanan lokal atau sesi. MSAL akan beralih ke penyimpanan dalam memori dalam hal ini.

Satu kali masuk

Anda dapat mencapai single sign-on antara aplikasi iframed dan aplikasi induk dengan same-origindan dengan cross-originjika Anda meneruskan hint akun dari aplikasi induk ke aplikasi iframed.

Aplikasi dengan asal yang sama

Aplikasi dalam iframe dan aplikasi induk dengan origin yang sama mungkin dapat mengakses instans cache MSAL.js yang sama dan masuk tanpa diminta lagi, asalkan kedua aplikasi mengonfigurasi MSAL untuk menggunakan penyimpanan lokal untuk cache. Lihat selengkapnya: Akses menyeluruh dengan MSAL.js

Aplikasi lintas asal

Aplikasi yang dimuat dalam iframe dan aplikasi induk dengan origin berbeda dapat memanfaatkan API ssoSilent() untuk mencapai single sign-on. Untuk melakukannya, aplikasi induk harus meneruskan akun, loginHint (nama pengguna) atau id sesi (sid) ke aplikasi iframed.

Aplikasi dapat mencoba menggunakan ssoSilent tanpa parameter di atas. Namun perlu diketahui bahwa ada pertimbangan tambahan saat menggunakan ssoSilent tanpa memberikan informasi apa pun tentang sesi pengguna.

Untuk komunikasi lintas asal antara aplikasi iframed dan induk, ada beberapa alternatif yang dapat Anda pertimbangkan:

  • Anda dapat menambahkan parameter kueri ke URL sumber iframe di aplikasi induk dan mengambilnya nanti di aplikasi anak:
// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication({
    auth: {
        clientId: "ENTER_CLIENT_ID",
        authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
        redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
    },
    cache: {
        cacheLocation: "localStorage", // set your cache location to local storage
    },
});

window.onload = () => {
    
    const urlParams = new URLSearchParams(window.location.search);
    const sid = urlParams.get("sid");

    // attempt SSO
    myMSALObj.ssoSilent({
        sid: sid
    }).then((response) => {
        // do something with response
    }).catch(error => {
        // handle errors
    });
}
  • Anda dapat menggunakan API postMessage() di aplikasi induk dan mendengarkan peristiwa pesan di anak:
// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication({
    auth: {
        clientId: "ENTER_CLIENT_ID",
        authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
        redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
    },
    cache: {
        cacheLocation: "localStorage", // set your cache location to local storage
    },
});

const parentDomain = "http://localhost:3001";

window.addEventListener("message", (event) => {
    // check the origin of the data
    if (event.origin === parentDomain) {
        const sid = event.data;

        // attempt SSO
        myMSALObj.ssoSilent({
            sid: sid
        }).then((response) => {
            // do something with response
        }).catch(error => {
            // handle errors
        });
    }
});

Penanganan kesalahan

Anda harus menangkap dan menangani kesalahan apa pun jika ssoSilent() gagal. Secara khusus:

  • InteractionRequiredError: akan dilemparkan jika persetujuan diperlukan, pengguna perlu melakukan MFA dan dll. Kesalahan ini sering dapat ditangani hanya dengan memulai API interaktif.
  • BrowserAuthError: akan ditampilkan jika tidak ada petunjuk akun yang diberikan atau jika petunjuk akun yang diberikan tidak valid, pop-up diblokir, dan sebagainya. Anda harus memeriksa errorCode dan menanganinya sebagaimana mestinya.
    myMSALObj.ssoSilent({
        sid: sid
    }).then((response) => {
            // do something with response
        }).catch(error => {
            if (error instanceof msal.InteractionRequiredAuthError) {
                myMSALObj.loginPopup()
                    .then((response) => {
                        // do something with response
                    });
            } else if (error instanceof msal.BrowserAuthError) {
                if (error.errorCode === "silent_sso_error") {
                    // e.g. username is null
                }
                if (error.errorCode === "popup_window_error") {
                    // e.g. popups are blocked
                }
            } else {
                console.log(error);
            }
        });

Interaksi pengguna

Jika Anda ingin meminimalkan komunikasi dengan IdP yang memerlukan interaksi pengguna, atau jika Anda mengalami masalah dengan popup karena alasan apa pun, ada beberapa opsi yang dapat Anda pertimbangkan:

  • Memberikan persetujuan admin. Ini memastikan bahwa tidak ada permintaan persetujuan untuk izin yang diperlukan oleh aplikasi Anda saat pengguna masuk untuk pertama kalinya.

  • Pra-otorisasi aplikasi klien. Ini memastikan bahwa tidak ada permintaan persetujuan untuk izin yang diperlukan oleh API web Anda saat dipanggil oleh aplikasi klien Anda.

Keluar sekali

Anda dapat menggunakan MSAL.js dengan URI logout front-channel untuk menghasilkan efek logout tunggal antara aplikasi dalam iframe dan aplikasi induk. Misalnya, jika Anda ingin pengguna keluar secara otomatis dari aplikasi iframed saat mereka keluar dari aplikasi induk, Anda harus mengaktifkan keluar saluran depan untuk aplikasi iframed. Untuk melakukannya, silakan merujuk ke: Cara mengonfigurasi URI keluar saluran depan.