Migrasi dari Browser MSAL v4 ke v5

Jika Anda baru menggunakan MSAL, Anda harus mulai di sini.

Jika Anda berasal dari MSAL v2, Anda harus memeriksa panduan ini terlebih dahulu untuk bermigrasi ke MSAL v3. Jika Anda berasal dari MSAL v3, Anda harus memeriksa panduan ini terlebih dahulu untuk bermigrasi ke MSAL v4 lalu ikuti langkah berikutnya.

Jika Anda berasal dari MSAL v4, Anda dapat mengikuti panduan ini untuk memperbarui kode Anda untuk menggunakan MSAL v5.

Perubahan Pemutusan API

Tipe pengembalian SignedHttpRequest.removeKeys telah berubah

Fungsi removeKeys pada kelas SignedHttpRequest kini mengembalikan Promise<void> alih-alih Promise<boolean>. Resolusi yang berhasil dari janji sekarang setara dengan apa yang sebelumnya merupakan nilai pengembalian dari true. Jika kegagalan terjadi, sekarang dilemparkan sebagai kesalahan alih-alih mengembalikan false.

// BEFORE
const shr = new SignedHttpRequest(shrParameters, shrOptions);
const result = await shr.removeKeys(thumbprint);
if (result) {
    // do something on success
} else {
    // do something on failure
}

// AFTER
const shr = new SignedHttpRequest(shrParameters, shrOptions);
await shr
    .removeKeys(thumbprint)
    .then(() => {
        // do something on success
    })
    .catch((e) => {
        // do something on failure
        console.log(e);
    });

TokenCache dan loadExternalTokens

MSAL JS API untuk loadExternalTokens dimodifikasi. Beberapa perubahan meliputi:

  • TokenCache objek dan getTokenCache() telah dihapus
  • loadExternalTokens() API sekarang menjadi ekspor terpisah dan memerlukan Configuration sebagai parameter
// BEFORE

const pca = new PublicClientApplication(config);
await pca
    .getTokenCache()
    .loadExternalTokens(silentRequest, serverResponse, loadTokenOptions);

//AFTER

await loadExternalTokens(
    config,
    silentRequest,
    serverResponse,
    loadTokenOptions
);

handleRedirectPromise Tanda tangan API telah berubah

Sebelumnya, PublicClientApplication.handleRedirectPromise menerima parameter hash opsional. Jenis opsi baru yang disebut HandleRedirectPromiseOptions telah diperkenalkan. Pada MSAL Browser v5, objek opsional dengan jenis HandleRedirectPromiseOptions adalah satu-satunya parameter handleRedirectPromise() yang diterima.

// BEFORE
const hash = window.location.hash; // Arbitrary example value
pca.handleRedirectPromise(hash);

// AFTER
pca.handleRedirectPromise({
    hash: window.location.hash, // Option nested inside a `HandleRedirectPromiseOptions` object
    navigateToLoginRequestUrl: true, // Additional option
});

Penghapusan beberapa fungsi di PublicClientApplication

Fungsi-fungsi berikut di PublicClientApplication telah dihapus:

  1. enableAccountStorageEvents() dan disableAccountStorageEvents(): peristiwa penyimpanan akun sekarang selalu diaktifkan. Panggilan fungsi ini tidak lagi diperlukan.

  2. getAccountByHomeId(), getAccountByLocalId(), dan getAccountByUsername(): gunakan getAccount() sebagai gantinya.

    // BEFORE
    const account1 = accountManager.getAccountByHomeId(yourHomeAccountId);
    const account2 = accountManager.getAccountByLocalId(yourLocalAccountId);
    const account3 = accountManager.getAccountByUsername(yourUsername);
    
    // AFTER
    const account1 = accountManager.getAccount({
        homeAccountId: yourHomeAccountId,
    });
    const account2 = accountManager.getAccount({
        localAccountId: yourLocalAccountId,
    });
    const account3 = accountManager.getAccount({ username: yourUsername });
    
  3. logout(): gunakan logoutRedirect() atau logoutPopup() sebagai gantinya.

Penghapusan startPerformanceMeasurement()

startPerformanceMeasurement() telah dihapus. Silakan gunakan startMeasurement() sebagai gantinya.

Penghapusan PublicClientNext

Kelas PublicClientNext dan metode createPublicClientApplication() statisnya telah dihapus di MSAL v5. Anda harus menggunakan salah satu alternatif berikut tergantung pada persyaratan aplikasi Anda:

  • PublicClientApplication: Gunakan ini untuk skenario aplikasi tunggal standar. Ini adalah penggunaan default dan paling umum.
  • createNestablePublicClientApplication: Gunakan ini jika Anda perlu mendukung aplikasi berlapis (NAA). Fungsi ini secara otomatis kembali ke PublicClientApplication standar jika jembatan aplikasi berlapis tidak tersedia atau Hub tidak dikonfigurasi untuk mendukung autentikasi aplikasi berlapis. Lihat Konfigurasi Aplikasi Berlapis untuk detail selengkapnya.
  • createStandardPublicClientApplication: Gunakan ini untuk membuat instance dan menginisialisasi instance PublicClientApplication standar (non-NAA).

Contoh Migrasi

// BEFORE (using PublicClientNext)
import { PublicClientNext } from "@azure/msal-browser";

const pca = PublicClientNext.createPublicClientApplication(config);
// AFTER (standard usage)
import { PublicClientApplication } from "@azure/msal-browser";

const pca = new PublicClientApplication(config);
await pca.initialize();
// AFTER (nested app support)
import { createNestablePublicClientApplication } from "@azure/msal-browser";

const pca = await createNestablePublicClientApplication(config);
// AFTER (standard)
import { createStandardPublicClientApplication } from "@azure/msal-browser";

const pca = await createStandardPublicClientApplication(config);

Untuk sebagian besar aplikasi, mengganti PublicClientNext.createPublicClientApplication(config) dengan new PublicClientApplication(config) sudah cukup. Jika sebelumnya Anda menggunakan supportsNestedAppAuth opsi konfigurasi, migrasikan ke createNestablePublicClientApplication(config) sebagai gantinya.

Penghapusan fungsi statis PublicClientApplication.createPublicClientApplication

Fungsi createPublicClientApplication statis pada PublicClientApplication telah dihapus dan diganti dengan yang diekspor createStandardPublicClientApplicationsecara terpisah .

Contoh Migrasi

// BEFORE
import { PublicClientApplication } from "@azure/msal-browser";

const pca = await PublicClientApplication.createPublicClientApplication(config);
// AFTER
import { createStandardPublicClientApplication } from "@azure/msal-browser";

const pca = await createStandardPublicClientApplication(config);

Perubahan konfigurasi

Perubahan BrowserAuthOptions

  1. Parameter skipAuthorityMetadataCache telah dihapus dari BrowserAuthOptions dalam Konfigurasi.

  2. Parameter protocolMode telah dipindahkan ke SystemOptions alih-alih BrowserAuthOptions dalam Konfigurasi.

  3. Parameter supportsNestedAppAuth telah dihapus. createNestablePublicClientApplication Gunakan API untuk Aplikasi Berlapis sebagai gantinya. Baca selengkapnya tentang Aplikasi Berlapis di sini.

  4. Parameter navigateTologinRequestUrl telah dihapus dari BrowserAuthOptions dalam Konfigurasi dan sekarang dapat disediakan di dalam objek opsi sebagai parameter pada panggilan ke handleRedirectPromise:

    pca.handleRedirectPromise({ navigateToLoginRequestUrl: false });
    
  5. Parameter encodeExtraQueryParams telah dihapus. Semua param kueri tambahan dikodekan.

  6. Parameter supportsNestedAppAuth telah dihapus. Gunakan createNestablePublicClientApplication() sebagai gantinya.

        // BEFORE
        const pca = new PublicClientApplication({
            auth: {
                clientId: "your-client-id",
                authority: "https://login.microsoftonline.com/common"
                supportsNestedAppAuth: true
            },
        });
    
        // AFTER
        const pca = await createNestablePublicClientApplication({
            auth: {
                clientId: "your-client-id",
                authority: "https://login.microsoftonline.com/common"
            }
        });
    
  7. Parameter OIDCOptions sekarang menerima ResponseMode alih-alih ServerResponseType. Silakan gunakan ResponseMode.QUERY sebagai ganti ServerResponseType.QUERY dan ResponseMode.FRAGMENT alih-alih ServerResponseType.FRAGMENT.

Perubahan pada CacheOptions

Parameter berikut tidak digunakan lagi di Browser MSAL v4 dan telah dihapus dari CacheOptions dalam v5:

  1. temporaryCacheLocation
  2. claimsBasedCachingEnabled - Token akses tidak lagi disimpan berdasarkan klaim yang diminta.
  3. storeAuthStateInCookie
  4. secureCookies - Semua cookie sekarang hanya pernah dikirim dengan aman melalui HTTPS.
  5. cacheMigrationEnabled

SystemOptions

  1. Parameter protocolMode telah dipindahkan ke SystemOptions dari BrowserAuthOptions dalam Konfigurasi. Tidak ada perubahan pada opsi atau fungsionalitasnya.
  2. Parameter navigateFrameWait telah dihapus. Ini sebelumnya diperlukan oleh browser lama yang tidak lagi didukung oleh MSAL.js.
  3. Parameter iframeHashTimeout dan windowHashTimeout telah diganti dengan iframeBridgeTimeout dan popupBridgeTimeout masing-masing. Batas waktu ini sekarang mengontrol berapa lama menunggu respons dari jembatan pengalihan melalui BROADCASTChannel API.

asyncPopups

Parameter asyncPopups telah diubah namanya menjadi navigatePopups di SystemOptions, dan opsinya dibalik. Ini mengatur apakah popup dibuka dan dinavigasi ke nanti. Ketika diatur ke true, popup kosong akan dibuka dan diarahkan ke domain login. Ketika diatur ke false, popup dibuka langsung ke domain login. Ini dapat diatur ke false untuk skenario di mana about:blank tidak didukung, misalnya aplikasi desktop atau aplikasi web progresif.

Important

Secara default, navigatePopups sekarang diatur ke true. Jika Anda menggunakan asyncPopups sebelumnya, Anda sekarang harus mengubahnya menjadi navigatePopups dan membalikkan konfigurasi Anda.

Lihat dokumen Konfigurasi untuk detail selengkapnya.

Perubahan pada permintaan

Penghapusan onRedirectNavigate parameter

Parameter onRedirectNavigatehanya didukung mulai dari objek Configuration dan seterusnya, serta dihapus dari objek RedirectRequest dan EndSessionRequest. Pastikan menetapkannya di konfigurasi MSAL jika Anda perlu menggunakannya.

Konsolidasi parameter permintaan tambahan

Parameter permintaan berikut telah dihapus:

  • authorizePostBodyParams
  • tokenBodyParameters
  • tokenQueryParameters

Untuk menyederhanakan parameter permintaan tambahan, parameter tambahan generik harus masuk ke opsi permintaan baru extraParameters . Saat extraParameters diatur dalam permintaan, mereka dikirim pada semua panggilan layanan token baik dalam string kueri URL atau isi permintaan, tergantung pada yang httpMethod dikonfigurasi (default adalah GET) dalam permintaan. Untuk mengirimkan parameter tambahan yang HARUS masuk ke string kueri URL, extraQueryParameters masih tersedia.

Note

Jika Anda tidak yakin apakah parameter tambahan harus dimasukkan ke extraQueryStringParameters atau extraParameters, kemungkinan besar parameter tersebut harus dimasukkan ke extraParameters.

Contoh permintaan v4 (sebelumnya):

// Example of a GET request with extra parameters
const authRequest = {
    scopes: ["SAMPLE_SCOPE"],
    extraQueryParamters: {
        "dc": "DC_VALUE" // This was sent on the query string on GET /authorize
    },
    tokenBodyParameters: {
        "extra_parameters_assertion": "ASSERTION_VALUE" // This was sent on the POST body to /token
    },
    tokenQueryParamters: {
        "slice": "SLICE_VALUE" // This was sent on the query string on POST /token
    }
}

// Example of a POST request with extra parameters
const authRequest = {
    scopes: ["SAMPLE_SCOPE"],
    httpMethod: "POST", // default is "GET" -> Determines method for "/authorize" call. Calls to "/token" are always POST
    extraQueryParamters: {
        "dc": "DC_VALUE" // This was sent on the query string on POST /authorize
    },
    authorizePostBodyParameters: {
        "extra_parameters_assertion": "ASSERTION_VALUE", // This was sent on the body on POST /authorize
    }
    tokenBodyParameters: {
        "extra_parameters_assertion": "ASSERTION_VALUE" // This was sent on the POST body to /token
    },
    tokenQueryParamters: {
        "slice": "SLICE_VALUE" // This was sent on the query string on POST /token
    }
}

Contoh Permintaan v5

// Example of a GET request with extra parameters
const authRequest = {
    scopes: ["SAMPLE_SCOPE"],
    extraQueryParamters: {
        // Will be sent in query string to /authorize and /token
        "dc": "DC_VALUE",
        "slice": "SLICE_VALUE"
    },
    extraParameters: {
        "extra_parameters_assertion": "ASSERTION_VALUE", // Will be sent in query string to /authorize and in body to /token
    },
};

// Example of a POST request with extra parameters
const authRequest = {
    scopes: ["SAMPLE_SCOPE"],
    httpMethod: "POST", // default is "GET" -> Determines method for "/authorize" call. Calls to "/token" are always POST
    extraQueryParamters: {
        // Will be sent in query string to /authorize and /token
        "dc": "DC_VALUE",
        "slice": "SLICE_VALUE"
    },
    extraParameters: {
        extra_parameter_assertion: "assertion_value", // Will be sent in post body to /authorize and /token
    },
};

Note

Dalam kasus ketika MSAL menentukan bahwa extraParameters harus dienkodekan ke dalam string URL, extraParameters digabungkan dengan extraQueryParams dengan cara yang menyebabkan parameter dengan nama yang sama ditimpa. Dalam kasus ini, nilai parameter dalam extraParameters lebih diutamakan daripada nilai dalam extraQueryParams.

Dukungan Cross-Origin-Opener-Policy (COOP)

MSAL Browser v5 memperkenalkan dukungan bawaan untuk Cross-Origin-Opener-Policy (COOP), yang meningkatkan keamanan dengan mengisolasi konteks penjelajahan. Saat layanan autentikasi (Microsoft Entra ID atau Azure AD B2C) mengembalikan header COOP, alur autentikasi popup tradisional dan iframe senyap dibatasi. MSAL v5 menyediakan mekanisme jembatan pengalihan untuk menangani autentikasi di lingkungan yang mendukung COOP.

Note

Microsoft Entra ID (sebelumnya Azure AD) mengaktifkan COOP secara default. Untuk Azure AD B2C, ketersediaan COOP bergantung pada konfigurasi backend Anda dan titik akhir autentikasi yang digunakan.

Apa yang Berubah

Ketika header COOP ada pada respons layanan autentikasi (misalnya, Cross-Origin-Opener-Policy: same-origin), aliran autentikasi popup dan iframe senyap tradisional gagal karena jendela autentikasi tidak dapat berkomunikasi kembali ke jendela aplikasi utama. MSAL v5 memecahkan masalah ini dengan memperkenalkan pola jembatan pengalihan.

Semua alur autentikasi (acquireTokenSilent(), ssoSilent(), loginPopup(), dan loginRedirect()) sekarang menggunakan jembatan pengalihan. Jembatan pengalihan menangani respons autentikasi secara berbeda berdasarkan alur:

  • Popup dan alur senyap: Jembatan pengalihan menyiarkan respons autentikasi ke jendela aplikasi utama menggunakan BROADCASTChannel API
  • Alur pengalihan: Jembatan pengalihan menavigasi kembali ke halaman aplikasi Anda yang memulai pengalihan dengan respons autentikasi di URL

Cara Kerjanya

  1. Aplikasi utama: Aplikasi Anda memulai autentikasi menggunakan loginPopup(), , ssoSilent()atau loginRedirect()
  2. Pengalihan: MSAL membuka popup/iframe/jendela untuk menampilkan halaman otoritas
  3. Alur autentikasi: Halaman otoritas menyelesaikan alur OAuth dan menerima respons autentikasi
  4. Penanganan respons: Halaman pengalihan menggunakan fungsi baru broadcastResponseToMainFrame() yang:
    • Untuk alur pop-up/senyap: Mengirimkan respons ke jendela utama melalui BroadcastChannel API
    • Untuk alur pengalihan: Menavigasi ke halaman tempat acquireTokenRedirect dimulai dengan respons autentikasi
  5. Akuisisi token: Aplikasi utama menerima respons dan menyelesaikan akuisisi token

Langkah migrasi

1. Siapkan halaman jembatan pengalihan

Buat halaman yang memanggil broadcastResponseToMainFrame() dari @azure/msal-browser/redirect-bridge. Halaman ini TIDAK boleh dilayani dengan header COOP.

Pengaturan bergantung pada sistem build — lihat panduan Bridge Redirect — Pengaturan Khusus Framework:

Kerangka kerja Approach
Angular Komponen rute + aset opsional angular.json
Vite Beberapa halaman rollupOptions.input
Webpack Entri terpisah + HtmlWebpackPlugin
Next.js Komponen halaman dikecualikan dari MsalProvider
CRA (Buat Aplikasi React) Halaman statis public/redirect.html
Express.js Pengecualian header COOP di sisi server

Lihat juga:Pertimbangan URI pengalihan | Kesalahan interaction_in_progress pada pop-up | MDN: COOP

2. Perbarui konfigurasi MSAL Anda

Arahkan redirectUri ke halaman jembatan pengalihan baru:

const msalConfig = {
    auth: {
        clientId: "{your-client-id}",
        authority: "https://login.microsoftonline.com/common",
        redirectUri: "https://{your-app-home-page}/redirect",
    },
};

Important

Anda juga HARUS memperbarui URI pengalihan di pendaftaran aplikasi Entra ID Anda. URI harus sama persis — termasuk jalur, protokol, dan port. Jika tidak dilakukan, akan menyebabkan kesalahan redirect_uri_mismatch.

Perubahan Melanggar Perilaku

Jenis peristiwa dan perubahan InteractionStatus

Kami telah menggabungkan tipe peristiwa dan InteractionStatus agar mencerminkan apa yang terjadi, bukan API tempat peristiwa tersebut terjadi.

  1. SSO_SILENTdan ACQUIRE_TOKEN_BY_CODE peristiwa telah diganti dengan ACQUIRE_TOKEN peristiwa (START/SUCCESS/FAILURE varian)
  2. ACCOUNT_ADDED dan ACCOUNT_REMOVED telah diganti dengan LOGIN_SUCCESS dan LOGOUT_SUCCESS, masing-masing.
  3. LOGIN_START dan LOGIN_FAILURE telah diganti dengan ACQUIRE_TOKEN_START dan ACQUIRE_TOKEN_FAILURE, masing-masing.
  4. Payload untuk LOGIN_SUCCESS sekarang adalah objek AccountInfo.
  5. Setiap login yang berhasil sekarang menghasilkan peristiwa LOGIN_SUCCESS dan ACQUIRE_TOKEN_SUCCESS.

LOGIN_SUCCESS Migrasi jenis payload

Jika callback event Anda saat ini melakukan cast payload LOGIN_SUCCESS ke AuthenticationResult, perbarui agar menggunakan AccountInfo untuk LOGIN_SUCCESS dan gunakan AuthenticationResult untuk ACQUIRE_TOKEN_SUCCESS.

// BEFORE (v4-style assumption)
import {
    EventType,
    AuthenticationResult,
} from "@azure/msal-browser";

pca.addEventCallback((event) => {
    if (event.eventType === EventType.LOGIN_SUCCESS) {
        const result = event.payload as AuthenticationResult;
        setAccount(result.account); // Will silently fail in v5 where payload is AccountInfo, not AuthenticationResult
    }
});
// AFTER (v5-safe handling)
import {
    EventType,
    AuthenticationResult,
    AccountInfo,
} from "@azure/msal-browser";

pca.addEventCallback((event) => {
    if (event.eventType === EventType.LOGIN_SUCCESS) {
        const account = event.payload as AccountInfo;
        setAccount(account);
    }

    if (event.eventType === EventType.ACQUIRE_TOKEN_SUCCESS) {
        const result = event.payload as AuthenticationResult;
        setAccessToken(result.accessToken);
    }
});

Perubahan format pesan kesalahan

Untuk mengurangi ukuran bundel, pesan kesalahan telah dipindahkan dari bundel. Saat kesalahan dilemparkan, message properti sekarang mengembalikan tautan generik ke dokumentasi kesalahan alih-alih pesan kesalahan deskriptif:

// BEFORE (v4)
error.message = "Token request cannot be made without authorization code or refresh token.";

// AFTER (v5)
error.message = "See https://aka.ms/msal.js.errors#request_cannot_be_made for details";

Properti errorCode tetap tidak berubah dan masih dapat digunakan untuk mengidentifikasi kesalahan tertentu. Untuk deskripsi kesalahan terperinci, lihat dokumentasi kesalahan.

Important

Jika aplikasi Anda mengandalkan penguraian atau penampilan properti error.message, Anda mungkin perlu memperbarui kode penanganan kesalahan untuk menggunakan errorCode sebagai gantinya atau mengarahkan pengguna ke tautan dokumentasi.

Memperbarui Kode Penanganan Kesalahan

Jika Anda menampilkan kesalahan kepada pengguna, petakan errorCode ke pesan yang mudah digunakan alih-alih menampilkan error.message secara langsung:

// BEFORE (v4)
showError(error.message);

// AFTER (v5) — use errorCode for user-facing messages
const userMessages = {
    request_cannot_be_made: "Please sign in again to continue.",
    interaction_required: "Additional verification is needed.",
    consent_required: "Administrator approval is required for this action.",
    login_required: "Your session has expired. Please sign in again.",
    // Add mappings for error codes your application encounters
};
showError(userMessages[error.errorCode] || "An authentication error occurred.");

Jika Anda mengurai error untuk logika bersyarat, beralihlah dari pencocokan string pada message ke perbandingan errorCode (ini sudah merupakan pendekatan yang disarankan di v4):

// BEFORE (v4) — fragile, relied on message text
if (error.message.includes("interaction_required")) {
    await msalInstance.acquireTokenPopup(request);
}

// AFTER (v5) — use errorCode (stable across versions)
if (error.errorCode === "interaction_required") {
    await msalInstance.acquireTokenPopup(request);
}

Jika Anda mencatat kesalahan untuk diagnosis, sertakan errorCode dan message (pesan tersebut kini berisi tautan langsung ke dokumentasi yang relevan):

// AFTER (v5) — log errorCode for programmatic use, message for the docs link
logger.error(`MSAL Error [${error.errorCode}]: ${error.message}`);
// Output: MSAL Error [request_cannot_be_made]: See https://aka.ms/msal.js.errors#request_cannot_be_made for details

Tip

Nilainya errorCode sama antara v4 dan v5 — hanya format yang message telah berubah. Jika kode Anda yang ada sudah bercabang pada errorCode, tidak ada perubahan yang diperlukan.

Perubahan pengelogan konsol

Untuk mengurangi ukuran bundel, pesan log konsol sekarang di-hash. Alih-alih melihat pesan log lengkap di konsol browser, Anda akan melihat nilai hash:

// BEFORE (v4)
[Wed, 15 Jan 2025 10:30:45 GMT] : abc-123 : @azure/msal-browser@4.27.0 : Info - Returning token from cache

// AFTER (v5)
[Wed, 15 Jan 2025 10:30:45 GMT] : abc-123 : @azure/msal-browser@5.0.0 : Info - 7f3a9b2c

Proses debug di konsol peramban memerlukan satu langkah tambahan untuk mendekode log. Untuk mendekode log hash kembali ke pesan yang dapat dibaca, gunakan skrip dekode. Untuk informasi selengkapnya tentang menggunakan skrip dekode, lihat dokumentasi skrip.