Aracılığıyla paylaş


JavaScript uygulamasını ADAL.js'den MSAL.js geçirme

JavaScript için Microsoft Kimlik Doğrulama Kitaplığı (MSAL.js, olarak da bilinirmsal-browser) 2.x, Microsoft kimlik platformu JavaScript uygulamalarıyla kullanmanızı önerdiğimiz kimlik doğrulama kitaplığıdır. Bu makalede, MSAL.js 2.x kullanmak için ADAL.js kullanan bir uygulamayı geçirmek için yapmanız gereken değişiklikler vurgulanır

Not

MSAL.js 1.x üzerinde MSAL.js 2.x'i kesinlikle öneririz. Kimlik doğrulama kodu verme akışı daha güvenlidir ve Safari gibi tarayıcıların 3. taraf tanımlama bilgilerini engellemek için uyguladığı gizlilik önlemlerine rağmen tek sayfalı uygulamaların iyi bir kullanıcı deneyimini korumasını sağlar.

Önkoşullar

  • Platform / Yanıtı URL Türü'nü Uygulama Kaydı portalında Tek sayfalı uygulama olarak ayarlamanız gerekir (Uygulama kaydınıza Web gibi başka platformlar eklendiyse, yeniden yönlendirme URI'lerinin çakışmadığından emin olmanız gerekir. Bkz. Yeniden yönlendirme URI'leri kısıtlamaları)
  • Uygulamalarınızı Internet Explorer'da çalıştırmak için MSAL.js bağlı olan ES6 özellikleri için çoklu doldurmalar sağlamanız gerekir (örneğin, vaatler).
  • Henüz yapmadıysanız Microsoft Entra uygulamalarınızı v2 uç noktasına geçirme

MSAL'yi yükleme ve içeri aktarma

MSAL.js 2.x kitaplığını yüklemenin iki yolu vardır:

Npm aracılığıyla:

npm install @azure/msal-browser

Ardından modül sisteminize bağlı olarak aşağıda gösterildiği gibi içeri aktarın:

import * as msal from "@azure/msal-browser"; // ESM

const msal = require('@azure/msal-browser'); // CommonJS

CDN aracılığıyla:

Betiği HTML belgenizin üst bilgi bölümüne yükleyin:

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.14.2/js/msal-browser.min.js"></script>
  </head>
</html>

CDN kullanırken alternatif CDN bağlantıları ve en iyi yöntemler için bkz. CDN Kullanımı

MSAL'ı başlatma

ADAL.js'de AuthenticationContext sınıfının örneğini oluşturursunuz. Bu sınıf, kimlik doğrulaması (login, acquireTokenPopup vb.) elde etmek için kullanabileceğiniz yöntemleri kullanıma sunar. Bu nesne, uygulamanızın yetkilendirme sunucusuna veya kimlik sağlayıcısına olan bağlantısını temsil eder. Başlatılırken tek zorunlu parametre clientId değeridir:

window.config = {
  clientId: "YOUR_CLIENT_ID"
};

var authContext = new AuthenticationContext(config);

MSAL.js içinde, bunun yerine PublicClientApplication sınıfını başlatırsınız. ADAL.js gibi oluşturucu da en azından parametresini clientId içeren bir yapılandırma nesnesi bekler. Daha fazla bilgi için bkz: MSAL.js başlatma

const msalConfig = {
  auth: {
      clientId: 'YOUR_CLIENT_ID'
  }
};

const msalInstance = new msal.PublicClientApplication(msalConfig);

Hem ADAL.js hem de MSAL.js, belirtmezseniz yetkili URI'sinin varsayılan değeri https://login.microsoftonline.com/common olur.

Not

v2.0'da yetkiliyi https://login.microsoftonline.com/common kullanırsanız, kullanıcıların herhangi bir Microsoft Entra kuruluşuyla veya kişisel bir Microsoft hesabıyla (MSA) oturum açmasına izin verirsiniz. MSAL.js'da, herhangi bir Microsoft Entra hesabıyla oturum açmayı kısıtlamak istiyorsanız (ADAL.js ile aynı davranış), bunun yerine kullanın https://login.microsoftonline.com/organizations .

MSAL'yi yapılandırma

AuthenticationContext başlatılırken kullanılan ADAL.js yapılandırma seçeneklerinden bazıları MSAL.js'de kullanım dışı bırakılırken, bazı yeni seçenekler kullanıma sunulmuştur. Kullanılabilir seçeneklerin tam listesine bakın. Daha da önemlisi, clientIdbelirteç alma sırasında bu seçeneklerin çoğu geçersiz kılınabilir ve bunları istek temelinde ayarlamanıza olanak sağlar. Örneğin, belirteçleri alırken başlatma sırasında ayarladığınızdan farklı bir yetkili URI'sini veya yeniden yönlendirme URI'sini kullanabilirsiniz.

Ayrıca, yapılandırma seçenekleri aracılığıyla oturum açma deneyimini (yani açılır pencereleri kullanma veya sayfayı yeniden yönlendirme) belirtmeniz gerekmez. Bunun yerine, MSAL.js örnek aracılığıyla PublicClientApplication ve loginRedirect yöntemlerini kullanıma sunarloginPopup.

Günlü kaydını etkinleştir

ADAL.js'da, günlüğü kodunuzun herhangi bir yerinde ayrı olarak yapılandırabilirsiniz:

window.config = {
  clientId: "YOUR_CLIENT_ID"
};

var authContext = new AuthenticationContext(config);

var Logging = {
  level: 3,
  log: function (message) {
      console.log(message);
  },
  piiLoggingEnabled: false
};


authContext.log(Logging)

MSAL.js günlük, yapılandırma seçeneklerinin bir parçasıdır ve başlatılırken PublicClientApplicationoluşturulur:

const msalConfig = {
  auth: {
      // authentication related parameters
  },
  cache: {
      // cache related parameters
  },
  system: {
      loggerOptions: {
          loggerCallback(loglevel, message, containsPii) {
              console.log(message);
          },
          piiLoggingEnabled: false,
          logLevel: msal.LogLevel.Verbose,
      }
  }
}

const msalInstance = new msal.PublicClientApplication(msalConfig);

MSAL API'sine geçiş yapma

ADAL.js'daki bazı genel yöntemlerin MSAL.js eşdeğerleri vardır:

ADAL MSAL Notlar
acquireToken acquireTokenSilent Yeniden adlandırıldı ve şimdi bir hesap nesnesi bekliyor
acquireTokenPopup acquireTokenPopup Şimdi zaman uyumsuz ve bir söz döndürür
acquireTokenRedirect acquireTokenRedirect Şimdi zaman uyumsuz ve bir söz döndürür
handleWindowCallback handleRedirectPromise Yeniden yönlendirme deneyimi kullanılıyorsa gereklidir
getCachedUser getAllAccounts Yeniden adlandırıldı ve şimdi bir hesap dizisi döndürür.

Diğerleri kullanım dışı bırakılmıştır ancak MSAL.js yeni yöntemler sunar:

ADAL MSAL Notlar
login Yok Kullanımdan kaldırıldı. veya kullanın loginPopuploginRedirect
logOut Yok Kullanımdan kaldırıldı. veya kullanın logoutPopuplogoutRedirect
Yok loginPopup
Yok loginRedirect
Yok logoutPopup
Yok logoutRedirect
Yok getAccountByHomeId Hesapları ev kimliğine (oid + kiracı kimliği) göre filtreler
Yok getAccountLocalId Hesapları yerel kimlikle filtreler (ADFS için kullanışlıdır)
Yok getAccountUsername Hesapları kullanıcı adına göre filtreler (varsa)

Ayrıca, MSAL.js ADAL.js aksine TypeScript'te uygulandığından, projelerinizde kullanabileceğiniz çeşitli türleri ve arabirimleri kullanıma sunar. Daha fazla bilgi için bkz. MSAL.js API başvurusu.

Kaynaklar yerine kapsamları kullanma

Azure Active Directory v1.0 ile 2.0 uç noktaları arasındaki önemli bir fark, kaynaklara nasıl erişildiğinden farklıdır. v1.0 uç noktasıyla ADAL.js kullanırken, önce uygulama kayıt portalına bir izin kaydeder ve ardından aşağıda gösterildiği gibi bir kaynak (Microsoft Graph gibi) için erişim belirteci isteyebilirsiniz:

authContext.acquireTokenRedirect("https://graph.microsoft.com", function (error, token) {
  // do something with the access token
});

MSAL.js yalnızca v2.0 uç noktasını destekler. v2.0 uç noktası, kaynaklara erişmek için kapsam odaklı bir model kullanır. Bu nedenle, bir kaynak için erişim belirteci istediğinizde, bu kaynağın kapsamını da belirtmeniz gerekir:

msalInstance.acquireTokenRedirect({
  scopes: ["https://graph.microsoft.com/User.Read"]
});

Kapsam odaklı modelin avantajlarından biri dinamik kapsamları kullanabilmektir. v1.0 uç noktasını kullanarak uygulama oluştururken, kullanıcının oturum açma sırasında onay verebilmek için uygulamanın gerektirdiği tam izin kümesini (statik kapsamlar olarak adlandırılır) kaydetmeniz gerekiyordu. v2.0'da scope parametresini kullanarak izinleri istediğiniz anda isteyebilirsiniz (dolayısıyla dinamik kapsamlar). Bu, kullanıcının kapsamlara artımlı onay sağlamasına olanak tanır. Bu nedenle, başlangıçta yalnızca kullanıcının uygulamanızda oturum açmasını istiyorsanız ve herhangi bir erişime ihtiyacınız yoksa, bunu yapabilirsiniz. Daha sonra kullanıcının takvimini okuma yeteneğine ihtiyacınız varsa, acquireToken yöntemlerinde takvim kapsamını isteyebilir ve kullanıcının onayını alabilirsiniz. Daha fazla bilgi için bkz. Kaynaklar ve kapsamlar

Geri çağırmalar yerine promises kullanma

ADAL.js kimlik doğrulaması başarılı olduktan ve bir yanıt alındıktan sonra geri çağırmalar herhangi bir işlem için kullanılır:

authContext.acquireTokenPopup(resource, extraQueryParameter, claims, function (error, token) {
  // do something with the access token
});

MSAL.js yerine promises kullanılır:

msalInstance.acquireTokenPopup({
      scopes: ["User.Read"] // shorthand for https://graph.microsoft.com/User.Read
  }).then((response) => {
      // do something with the auth response
  }).catch((error) => {
      // handle errors
  });

ES8 ile birlikte gelen zaman uyumsuz/await söz dizimini de kullanabilirsiniz:

const getAccessToken = async() => {
  try {
      const authResponse = await msalInstance.acquireTokenPopup({
          scopes: ["User.Read"]
      });
  } catch (error) {
      // handle errors
  }
}

Belirteçleri önbelleğe alma ve alma

ADAL.js gibi MSAL.js de Web Depolama API'sini kullanarak tarayıcı depolama alanında belirteçleri ve diğer kimlik doğrulama yapıtlarını önbelleğe alır. Kullanıcılarınız tarafından alınan belirteçleri depolamada daha güvenli olduğundan, ancak localStorage sekmeler ve kullanıcı oturumlarında size Çoklu Oturum Açma sağladığından seçeneği kullanmanız sessionStorage önerilir (bkz. yapılandırma).

Daha da önemlisi, önbelleğe doğrudan erişmeniz gerekmez. Bunun yerine, erişim belirteçleri veya kullanıcı hesapları gibi kimlik doğrulama yapıtlarını almak için uygun bir MSAL.js API'sini kullanmanız gerekir.

Belirteçleri yenileme belirteçleriyle yenileme

ADAL.js, güvenlik nedeniyle yenileme belirteçleri döndürmeyen OAuth 2.0 örtük akışını kullanır (yenileme belirteçlerinin ömrü erişim belirteçlerinden daha uzun olur ve bu nedenle kötü amaçlı aktörlerin elinde daha tehlikelidir). Bu nedenle ADAL.js, kullanıcının tekrar tekrar kimlik doğrulamasından istenmesi için gizli bir IFrame kullanarak belirteç yenileme gerçekleştirir.

PKCE desteğine sahip kimlik doğrulama kodu akışıyla, MSAL.js 2.x kullanan uygulamalar kimlik ve erişim belirteçleriyle birlikte yenileme belirteçleri alır ve bunları yenilemek için kullanılabilir. Yenileme belirteçlerinin kullanımı soyutlanır ve geliştiricilerin bunların etrafında mantık oluşturmaması gerekir. Bunun yerine MSAL, yenileme belirteçlerini kullanarak belirteç yenilemeyi tek başına yönetir. Belirteç önbelleği şeması değiştiğinden ve ADAL.js kullanılan şemayla uyumsuz olduğundan ADAL.js içeren önceki belirteç önbelleğiniz MSAL.js aktarılamaz.

Hataları ve özel durumları işleme

MSAL.js kullanırken karşılaşabileceğiniz en yaygın hata türü hatadır interaction_in_progress . Bu hata, başka bir etkileşimli API devam ederken etkileşimli bir API (loginPopup, loginRedirect, acquireTokenPopup, acquireTokenRedirect) çağrıldığında oluşur. ve API'leri login* zaman uyumsuz olduğundan, başka bir söz çağırmadan önce elde edilen vaatlerin çözümlenmiş olduğundan emin olmanız gerekir.acquireToken*

Bir diğer yaygın hata ise şeklindedir interaction_required. Bu hata genellikle etkileşimli bir belirteç alma istemi başlatılarak çözülür. Örneğin, erişmeye çalıştığınız web API'sinde, kullanıcının çok faktörlü kimlik doğrulaması (MFA) gerçekleştirmesini gerektiren bir Koşullu Erişim ilkesi olabilir. Bu durumda, hatanın işlenmesi interaction_required için tetiklenir acquireTokenPopup veya acquireTokenRedirect kullanıcıdan MFA istenir ve tam olarak dosyalanması istenir.

Yine de, korumalı bir kaynak için erişim belirteci almak için gereken izinler kullanıcı tarafından onaylanmadığında oluşan bir diğer yaygın hatayla karşılaşabilirsiniz consent_required. içinde interaction_requiredolduğu gibi hatanın consent_required çözümü genellikle veya acquireTokenRedirectkullanarak acquireTokenPopup etkileşimli bir belirteç alma istemi başlatır.

Daha fazla bilgi için bkz. Yaygın MSAL.js hataları ve bunların nasıl işleneceğini

Olaylar API'sini kullanma

MSAL.js (>=v2.4), uygulamalarınızda kullanabileceğiniz bir olay API'sini tanıtır. Bu olaylar, kimlik doğrulama işlemiyle ve MSAL'nin her an ne yaptığıyla ilgilidir ve kullanıcı arabirimini güncelleştirmek, hata iletilerini göstermek, devam eden bir etkileşim olup olmadığını denetlemek vb. için kullanılabilir. Örneğin, aşağıda herhangi bir nedenle oturum açma işlemi başarısız olduğunda çağrılacak bir olay geri çağırması yer alır:

const callbackId = msalInstance.addEventCallback((message) => {
  // Update UI or interact with EventMessage here
  if (message.eventType === EventType.LOGIN_FAILURE) {
      if (message.error instanceof AuthError) {
          // Do something with the error
      }
    }
});

Performans için, artık gerekli olmadığında olay geri çağırmalarının kaydını kaldırmak önemlidir. Daha fazla bilgi için bkz: MSAL.js Olayları API'si

Birden çok hesabı işleme

ADAL.js, şu anda kimliği doğrulanmış varlığı temsil eden bir kullanıcı kavramına sahiptir. MSAL.js, bir kullanıcının kendileriyle ilişkili birden fazla hesabı olabileceği göz önünde bulundurulduğunda, kullanıcıları hesaplarla değiştirir. Bu, artık birden çok hesabı denetlemeniz ve çalışmak için uygun hesabı seçmeniz gerektiği anlamına da gelir. Aşağıdaki kod parçacığında bu işlem gösterilmektedir:

let homeAccountId = null; // Initialize global accountId (can also be localAccountId or username) used for account lookup later, ideally stored in app state

// This callback is passed into `acquireTokenPopup` and `acquireTokenRedirect` to handle the interactive auth response
function handleResponse(resp) {
  if (resp !== null) {
      homeAccountId = resp.account.homeAccountId; // alternatively: resp.account.homeAccountId or resp.account.username
  } else {
      const currentAccounts = myMSALObj.getAllAccounts();
      if (currentAccounts.length < 1) { // No cached accounts
          return;
      } else if (currentAccounts.length > 1) { // Multiple account scenario
          // Add account selection logic here
      } else if (currentAccounts.length === 1) {
          homeAccountId = currentAccounts[0].homeAccountId; // Single account scenario
      }
  }
}

Daha fazla bilgi için bkz. MSAL.js'deki hesaplar

Sarmalayıcı kitaplıklarını kullanma

Angular ve React çerçeveleri için geliştiriyorsanız, sırasıyla MSAL Angular v2 ve MSAL React'i kullanabilirsiniz. Bu sarmalayıcılar MSAL.js ile aynı genel API'yi kullanıma sunarken, kimlik doğrulama ve belirteç alma işlemlerini kolaylaştırabilecek çerçeveye özgü yöntemler ve bileşenler sunar.

Uygulamayı çalıştırma

Değişiklikleriniz tamamlandıktan sonra uygulamayı çalıştırın ve kimlik doğrulama senaryonuzu test edin:

npm start

Örnek: spayı ADAL.js ve MSAL.js ile güvenli hale getirme

Aşağıdaki kod parçacıkları, kullanıcıların kimliklerini Microsoft kimlik platformu ve microsoft graph için ilk ADAL.js ve ardından MSAL.js kullanarak erişim belirteci alan tek sayfalı bir uygulama için gereken en düşük kodu gösterir:

ADAL.js kullanma MSAL.js kullanma

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript" src="https://alcdn.msauth.net/lib/1.0.18/js/adal.min.js"></script>
</head>

<body>
    <div>
        <p id="welcomeMessage" style="visibility: hidden;"></p>
        <button id="loginButton">Login</button>
        <button id="logoutButton" style="visibility: hidden;">Logout</button>
        <button id="tokenButton" style="visibility: hidden;">Get Token</button>
    </div>
    <script>
        // DOM elements to work with
        var welcomeMessage = document.getElementById("welcomeMessage");
        var loginButton = document.getElementById("loginButton");
        var logoutButton = document.getElementById("logoutButton");
        var tokenButton = document.getElementById("tokenButton");

        // if user is logged in, update the UI
        function updateUI(user) {
            if (!user) {
                return;
            }

            welcomeMessage.innerHTML = 'Hello ' + user.profile.upn + '!';
            welcomeMessage.style.visibility = "visible";
            logoutButton.style.visibility = "visible";
            tokenButton.style.visibility = "visible";
            loginButton.style.visibility = "hidden";
        };

        // attach logger configuration to window
        window.Logging = {
            piiLoggingEnabled: false,
            level: 3,
            log: function (message) {
                console.log(message);
            }
        };

        // ADAL configuration
        var adalConfig = {
            instance: 'https://login.microsoftonline.com/',
            clientId: "ENTER_CLIENT_ID_HERE",
            tenant: "ENTER_TENANT_ID_HERE",
            redirectUri: "ENTER_REDIRECT_URI_HERE",
            cacheLocation: "sessionStorage",
            popUp: true,
            callback: function (errorDesc, token, error, tokenType) {
                if (error) {
                    console.log(error, errorDesc);
                } else {
                    updateUI(authContext.getCachedUser());
                }
            }
        };

        // instantiate ADAL client object
        var authContext = new AuthenticationContext(adalConfig);

        // handle redirect response or check for cached user
        if (authContext.isCallback(window.location.hash)) {
            authContext.handleWindowCallback();
        } else {
            updateUI(authContext.getCachedUser());
        }

        // attach event handlers to button clicks
        loginButton.addEventListener('click', function () {
            authContext.login();
        });

        logoutButton.addEventListener('click', function () {
            authContext.logOut();
        });

        tokenButton.addEventListener('click', () => {
            authContext.acquireToken(
                "https://graph.microsoft.com",
                function (errorDesc, token, error) {
                    if (error) {
                        console.log(error, errorDesc);

                        authContext.acquireTokenPopup(
                            "https://graph.microsoft.com",
                            null, // extraQueryParameters
                            null, // claims
                            function (errorDesc, token, error) {
                                if (error) {
                                    console.log(error, errorDesc);
                                } else {
                                    console.log(token);
                                }
                            }
                        );
                    } else {
                        console.log(token);
                    }
                }
            );
        });
    </script>
</body>

</html>


<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.34.0/js/msal-browser.min.js"></script>
</head>

<body>
    <div>
        <p id="welcomeMessage" style="visibility: hidden;"></p>
        <button id="loginButton">Login</button>
        <button id="logoutButton" style="visibility: hidden;">Logout</button>
        <button id="tokenButton" style="visibility: hidden;">Get Token</button>
    </div>
    <script>
        // DOM elements to work with
        const welcomeMessage = document.getElementById("welcomeMessage");
        const loginButton = document.getElementById("loginButton");
        const logoutButton = document.getElementById("logoutButton");
        const tokenButton = document.getElementById("tokenButton");

        // if user is logged in, update the UI
        const updateUI = (account) => {
            if (!account) {
                return;
            }

            welcomeMessage.innerHTML = `Hello ${account.username}!`;
            welcomeMessage.style.visibility = "visible";
            logoutButton.style.visibility = "visible";
            tokenButton.style.visibility = "visible";
            loginButton.style.visibility = "hidden";
        };

        // MSAL configuration
        const msalConfig = {
            auth: {
                clientId: "ENTER_CLIENT_ID_HERE",
                authority: "https://login.microsoftonline.com/ENTER_TENANT_ID_HERE",
                redirectUri: "ENTER_REDIRECT_URI_HERE",
            },
            cache: {
                cacheLocation: "sessionStorage"
            },
            system: {
                loggerOptions: {
                    loggerCallback(loglevel, message, containsPii) {
                        console.log(message);
                    },
                    piiLoggingEnabled: false,
                    logLevel: msal.LogLevel.Verbose,
                }
            }
        };

        // instantiate MSAL client object
        const pca = new msal.PublicClientApplication(msalConfig);

        // handle redirect response or check for cached user
        pca.handleRedirectPromise().then((response) => {
            if (response) {
                pca.setActiveAccount(response.account);
                updateUI(response.account);
            } else {
                const account = pca.getAllAccounts()[0];
                updateUI(account);
            }
        }).catch((error) => {
            console.log(error);
        });

        // attach event handlers to button clicks
        loginButton.addEventListener('click', () => {
            pca.loginPopup().then((response) => {
                pca.setActiveAccount(response.account);
                updateUI(response.account);
            })
        });

        logoutButton.addEventListener('click', () => {
            pca.logoutPopup().then((response) => {
                window.location.reload();
            });
        });

        tokenButton.addEventListener('click', () => {
            const account = pca.getActiveAccount();

            pca.acquireTokenSilent({
                account: account,
                scopes: ["User.Read"]
            }).then((response) => {
                console.log(response);
            }).catch((error) => {
                if (error instanceof msal.InteractionRequiredAuthError) {
                    pca.acquireTokenPopup({
                        scopes: ["User.Read"]
                    }).then((response) => {
                        console.log(response);
                    });
                }

                console.log(error);
            });
        });
    </script>
</body>

</html>

Sonraki adımlar