Azure AD B2C kullanarak kendi tek sayfalı uygulamanızda kimlik doğrulamasını etkinleştirme

Bu makalede, Azure Active Directory B2C (Azure AD B2C) kimlik doğrulamasını kendi tek sayfalı uygulamanıza (SPA) nasıl ekleyeceğiniz gösterilir. JavaScript için Microsoft Kimlik Doğrulama Kitaplığı'nı (MSAL.js) kullanarak SPA uygulaması oluşturmayı öğrenin.

Örnek SPA uygulamasını kendi SPA uygulamanızla değiştirerek örnek BIR SPA uygulamasında kimlik doğrulamasını yapılandırma ile bu makaleyi kullanın.

Genel Bakış

Bu makalede temel bir Node.js web uygulaması oluşturmak için Node.js ve Express kullanılır. Express, web ve mobil uygulamalar için bir dizi özellik sağlayan minimal ve esnek bir Node.js web uygulaması çerçevesidir.

MSAL.js kimlik doğrulama kitaplığı, SPA uygulamalarına kimlik doğrulaması ve yetkilendirme desteği eklemeyi basitleştiren Microsoft tarafından sağlanan bir kitaplıktır.

İpucu

MSAL.js kodunun tamamı istemci tarafında çalışır. Node.js ve Express sunucu tarafı kodunu .NET Core, Java ve Köprü Metni Ön İşlemcisi (PHP) betik oluşturma dilleri gibi diğer çözümlerle değiştirebilirsiniz.

Önkoşullar

Önkoşulları ve tümleştirme yönergelerini gözden geçirmek için bkz. Örnek spa uygulamasında kimlik doğrulamasını yapılandırma.

1. Adım: SPA uygulaması projesi oluşturma

Mevcut bir SPA uygulaması projesini kullanabilir veya yeni bir proje oluşturabilirsiniz. Yeni proje oluşturmak için aşağıdakileri yapın:

  1. Bir komut kabuğu açın ve yeni bir dizin (örneğin , myApp) oluşturun. Bu dizin uygulama kodunuzu, kullanıcı arabiriminizi ve yapılandırma dosyalarınızı içerir.

  2. Oluşturduğunuz dizini girin.

  3. npm init Uygulamanız için bir package.json dosya oluşturmak için komutunu kullanın. Bu komut, uygulamanız hakkında bilgi ister (örneğin, uygulamanızın adı ve sürümü ve ilk giriş noktasının adı, index.js dosyası). Aşağıdaki komutu çalıştırın ve varsayılan değerleri kabul edin:

npm init

2. Adım: Bağımlılıkları yükleme

Express paketini yüklemek için komut kabuğunuzda aşağıdaki komutu çalıştırın:

npm install express

Uygulamanın statik dosyalarını bulmak için sunucu tarafı kodu Yol paketini kullanır.

Yol paketini yüklemek için komut kabuğunuzda aşağıdaki komutu çalıştırın:

npm install path

3. Adım: Web sunucunuzu yapılandırma

myApp klasörünüzde, aşağıdaki kodu içeren index.jsadlı bir dosya oluşturun:

// Initialize express
const express = require('express');
const app = express();

// The port to listen to incoming HTTP requests
const port = 6420;

// Initialize path
const path = require('path');

// Set the front-end folder to serve public assets.
app.use(express.static('App'));

// Set up a route for the index.html
app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname + '/index.html'));
});

// Start the server, and listen for HTTP requests
app.listen(port, () => {
  console.log(`Listening on http://localhost:${port}`);
});

4. Adım: SPA kullanıcı arabirimini oluşturma

SPA uygulama index.html dosyasını ekleyin. Bu dosya, Bootstrap çerçevesiyle oluşturulmuş bir kullanıcı arabirimi uygular ve yapılandırma, kimlik doğrulaması ve web API çağrıları için betik dosyalarını içeri aktarır.

index.html dosyası tarafından başvuruda bulunılan kaynaklar aşağıdaki tabloda ayrıntılı olarak yer alır:

Başvuru Tanım
MSAL.js kitaplığı MSAL.js kimlik doğrulaması JavaScript kitaplığı CDN yolu.
Bootstrap stil sayfası Daha hızlı ve daha kolay web geliştirme için ücretsiz bir ön uç çerçevesi. Çerçeve HTML tabanlı ve CSS tabanlı tasarım şablonlarını içerir.
policies.js Azure AD B2C özel ilkelerini ve kullanıcı akışlarını içerir.
authConfig.js Kimlik doğrulama yapılandırma parametrelerini içerir.
authRedirect.js Kimlik doğrulama mantığını içerir.
apiConfig.js Web API kapsamlarını ve API uç noktası konumunu içerir.
api.js API'nizi çağırmak ve yanıtını işlemek için kullanılacak yöntemi tanımlar.
ui.js Kullanıcı arabirimi öğelerini denetler.

SPA dizin dosyasını işlemek için myApp klasöründe aşağıdaki HTML parçacığını içeren index.htmladlı bir dosya oluşturun:

<!DOCTYPE html>
<html>
    <head>
        <title>My Azure AD B2C test app</title>
    </head>
    <body>
        <h2>My Azure AD B2C test app</h2>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />
        <button type="button" id="signIn" class="btn btn-secondary" onclick="signIn()">Sign-in</button>
        <button type="button" id="signOut" class="btn btn-success d-none" onclick="signOut()">Sign-out</button>
        <h5 id="welcome-div" class="card-header text-center d-none"></h5>
        <br />
        <!-- Content -->
        <div class="card">
            <div class="card-body text-center">
                <pre id="response" class="card-text"></pre>
                <button type="button" id="callApiButton" class="btn btn-primary d-none" onclick="passTokenToApi()">Call API</button>
            </div>
        </div>
        <script src="https://alcdn.msauth.net/browser/2.14.2/js/msal-browser.min.js" integrity="sha384-ggh+EF1aSqm+Y4yvv2n17KpurNcZTeYtUZUvhPziElsstmIEubyEB6AIVpKLuZgr" crossorigin="anonymous"></script>

        <!-- Importing app scripts (load order is important) -->
        <script type="text/javascript" src="./apiConfig.js"></script>
        <script type="text/javascript" src="./policies.js"></script>
        <script type="text/javascript" src="./authConfig.js"></script>
        <script type="text/javascript" src="./ui.js"></script>

        <!-- <script type="text/javascript" src="./authRedirect.js"></script>   -->
        <!-- uncomment the above line and comment the line below if you would like to use the redirect flow -->
        <script type="text/javascript" src="./authRedirect.js"></script>
        <script type="text/javascript" src="./api.js"></script>
    </body>
</html>

5. Adım: Kimlik doğrulama kitaplığını yapılandırma

MSAL.js kitaplığının Azure AD B2C ile tümleştirmesini yapılandırın. MSAL.js kitaplığı, Azure AD B2C kiracınızın kimlik doğrulama uç noktalarına bağlanmak için ortak bir yapılandırma nesnesi kullanır.

Kimlik doğrulama kitaplığını yapılandırmak için aşağıdakileri yapın:

  1. myApp klasöründe Uygulama adlı yeni bir klasör oluşturun.

  2. Uygulama klasörünün içinde authConfig.jsadlı yeni bir dosya oluşturun.

  3. authConfig.js dosyasına aşağıdaki JavaScript kodunu ekleyin:

    const msalConfig = {
        auth: {
        clientId: "<Application-ID>", 
        authority: b2cPolicies.authorities.signUpSignIn.authority, 
        knownAuthorities: [b2cPolicies.authorityDomain], 
        redirectUri: "http://localhost:6420",
        },
        cache: {
        cacheLocation: "localStorage", .
        storeAuthStateInCookie: false, 
        }
    };
    
    const loginRequest = {
    scopes: ["openid", ...apiConfig.b2cScopes],
    };
    
    const tokenRequest = {
    scopes: [...apiConfig.b2cScopes],
    forceRefresh: false
    };
    
  4. değerini uygulama kaydı uygulama kimliğiniz ile değiştirin <Application-ID> . Daha fazla bilgi için bkz. Örnek SPA uygulamasında kimlik doğrulamasını yapılandırma.

İpucu

Diğer MSAL nesne yapılandırma seçenekleri için Kimlik doğrulama seçenekleri makalesine bakın.

6. Adım: Azure AD B2C kullanıcı akışlarınızı belirtin

Azure AD B2C ortamınız hakkında bilgi sağlayanpolicies.jsdosyasını oluşturun. MSAL.js kitaplığı, B2C Azure AD kimlik doğrulama istekleri oluşturmak için bu bilgileri kullanır.

Azure AD B2C kullanıcı akışlarınızı belirtmek için aşağıdakileri yapın:

  1. Uygulama klasörünün içinde policies.jsadlı yeni bir dosya oluşturun.

  2. policies.js dosyasına aşağıdaki kodu ekleyin:

    const b2cPolicies = {
        names: {
            signUpSignIn: "B2C_1_SUSI",
            editProfile: "B2C_1_EditProfile"
        },
        authorities: {
            signUpSignIn: {
                authority: "https://contoso.b2clogin.com/contoso.onmicrosoft.com/Your-B2C-SignInOrSignUp-Policy-Id",
            },
            editProfile: {
                authority: "https://contoso.b2clogin.com/contoso.onmicrosoft.com/Your-B2C-EditProfile-Policy-Id"
            }
        },
        authorityDomain: "contoso.b2clogin.com"
    }
    
  3. değerini oturum açma Azure AD B2C İlkesi adıyla değiştirinB2C_1_SUSI.

  4. değerini B2C ilke adı Azure AD düzenleme profilinizle değiştirinB2C_1_EditProfile.

  5. tüm örneklerini contosoAzure AD B2C kiracı adınız ile değiştirin.

7. Adım: Kullanıcıda oturum açmak için MSAL kullanma

Bu adımda, oturum açma akışını, API erişim belirteci alma işlemini ve oturum kapatma yöntemlerini başlatmak için yöntemleri uygulayın.

Daha fazla bilgi için , kullanıcı makalesinde oturum açmak için Microsoft Kimlik Doğrulama Kitaplığı'nı (MSAL) kullanma konusuna bakın.

Kullanıcıda oturum açmak için aşağıdakileri yapın:

  1. Uygulama klasörünün içinde authRedirect.jsadlı yeni bir dosya oluşturun.

  2. authRedirect.jsaşağıdaki kodu kopyalayıp yapıştırın:

    // Create the main myMSALObj instance
    // configuration parameters are located at authConfig.js
    const myMSALObj = new msal.PublicClientApplication(msalConfig);
    
    let accountId = "";
    let idTokenObject = "";
    let accessToken = null;
    
    myMSALObj.handleRedirectPromise()
        .then(response => {
            if (response) {
                /**
                 * For the purpose of setting an active account for UI update, we want to consider only the auth response resulting
                 * from SUSI flow. "tfp" claim in the id token tells us the policy (NOTE: legacy policies may use "acr" instead of "tfp").
                 * To learn more about B2C tokens, visit https://learn.microsoft.com/azure/active-directory-b2c/tokens-overview
                 */
                if (response.idTokenClaims['tfp'].toUpperCase() === b2cPolicies.names.signUpSignIn.toUpperCase()) {
                    handleResponse(response);
                }
            }
        })
        .catch(error => {
            console.log(error);
        });
    
    
    function setAccount(account) {
        accountId = account.homeAccountId;
        idTokenObject = account.idTokenClaims;
        myClaims= JSON.stringify(idTokenObject);
        welcomeUser(myClaims);
    }
    
    function selectAccount() {
    
        /**
         * See here for more information on account retrieval: 
         * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
         */
    
        const currentAccounts = myMSALObj.getAllAccounts();
    
        if (currentAccounts.length < 1) {
            return;
        } else if (currentAccounts.length > 1) {
    
            /**
             * Due to the way MSAL caches account objects, the auth response from initiating a user-flow
             * is cached as a new account, which results in more than one account in the cache. Here we make
             * sure we are selecting the account with homeAccountId that contains the sign-up/sign-in user-flow, 
             * as this is the default flow the user initially signed-in with.
             */
            const accounts = currentAccounts.filter(account =>
                account.homeAccountId.toUpperCase().includes(b2cPolicies.names.signUpSignIn.toUpperCase())
                &&
                account.idTokenClaims.iss.toUpperCase().includes(b2cPolicies.authorityDomain.toUpperCase())
                &&
                account.idTokenClaims.aud === msalConfig.auth.clientId 
                );
    
            if (accounts.length > 1) {
                // localAccountId identifies the entity for which the token asserts information.
                if (accounts.every(account => account.localAccountId === accounts[0].localAccountId)) {
                    // All accounts belong to the same user
                    setAccount(accounts[0]);
                } else {
                    // Multiple users detected. Logout all to be safe.
                    signOut();
                };
            } else if (accounts.length === 1) {
                setAccount(accounts[0]);
            }
    
        } else if (currentAccounts.length === 1) {
            setAccount(currentAccounts[0]);
        }
    }
    
    // in case of page refresh
    selectAccount();
    
    async function handleResponse(response) {
    
        if (response !== null) {
            setAccount(response.account);
        } else {
            selectAccount();
        }
    }
    
    function signIn() {
        myMSALObj.loginRedirect(loginRequest);
    }
    
    function signOut() {
        const logoutRequest = {
            postLogoutRedirectUri: msalConfig.auth.redirectUri,
        };
    
        myMSALObj.logoutRedirect(logoutRequest);
    }
    
    function getTokenRedirect(request) {
        request.account = myMSALObj.getAccountByHomeId(accountId); 
    
        return myMSALObj.acquireTokenSilent(request)
            .then((response) => {
                // In case the response from B2C server has an empty accessToken field
                // throw an error to initiate token acquisition
                if (!response.accessToken || response.accessToken === "") {
                    throw new msal.InteractionRequiredAuthError;
                } else {
                    console.log("access_token acquired at: " + new Date().toString());
                    accessToken = response.accessToken;
                    passTokenToApi();
                }
            }).catch(error => {
                console.log("Silent token acquisition fails. Acquiring token using popup. \n", error);
                if (error instanceof msal.InteractionRequiredAuthError) {
                    // fallback to interaction when silent call fails
                    return myMSALObj.acquireTokenRedirect(request);
                } else {
                    console.log(error);   
                }
        });
    }
    
    // Acquires and access token and then passes it to the API call
    function passTokenToApi() {
        if (!accessToken) {
            getTokenRedirect(tokenRequest);
        } else {
            try {
                callApi(apiConfig.webApi, accessToken);
            } catch(error) {
                console.log(error); 
            }
        }
    }
    
    function editProfile() {
    
    
        const editProfileRequest = b2cPolicies.authorities.editProfile;
        editProfileRequest.loginHint = myMSALObj.getAccountByHomeId(accountId).username;
    
        myMSALObj.loginRedirect(editProfileRequest);
    }
    

8. Adım: Web API'sinin konumunu ve kapsamını yapılandırma

SPA uygulamanızın web API'sini çağırmasına izin vermek için web API'si uç noktası konumunu ve web API'sine erişimi yetkilendirmek için kullanılacak kapsamları sağlayın.

Web API'sinin konumunu ve kapsamlarını yapılandırmak için aşağıdakileri yapın:

  1. Uygulama klasörünün içinde apiConfig.jsadlı yeni bir dosya oluşturun.

  2. apiConfig.jsaşağıdaki kodu kopyalayıp yapıştırın:

    // The current application coordinates were pre-registered in a B2C tenant.
    const apiConfig = {
        b2cScopes: ["https://contoso.onmicrosoft.com/tasks/tasks.read"],
        webApi: "https://mydomain.azurewebsites.net/tasks"
    };
    
  3. değerini kiracı adınızla değiştirin contoso . Gerekli kapsam adı Kapsamları yapılandırma makalesinde açıklandığı gibi bulunabilir.

  4. değerini webApi web API uç noktası konumunuzla değiştirin.

9. Adım: Web API'nizi çağırma

API uç noktanıza HTTP isteğini tanımlayın. HTTP isteği, MSAL.js ile alınan erişim belirtecini istekteki Authorization HTTP üst bilgisine geçirecek şekilde yapılandırılır.

Aşağıdaki kod, ERIŞIM belirtecini Authorization HTTP GET üst bilgisinde geçirerek API uç noktasına HTTP isteğini tanımlar. API konumu ,apiConfig.jsiçindeki anahtar tarafından webApi tanımlanır.

Aldığınız belirteci kullanarak web API'nizi çağırmak için aşağıdakileri yapın:

  1. Uygulama klasörünün içinde api.jsadlı yeni bir dosya oluşturun.

  2. api.js dosyasına aşağıdaki kodu ekleyin:

    function callApi(endpoint, token) {
    
        const headers = new Headers();
        const bearer = `Bearer ${token}`;
    
        headers.append("Authorization", bearer);
    
        const options = {
            method: "GET",
            headers: headers
        };
    
        logMessage('Calling web API...');
    
        fetch(endpoint, options)
        .then(response => response.json())
        .then(response => {
    
            if (response) {
            logMessage('Web API responded: ' + response.name);
            }
    
            return response;
        }).catch(error => {
            console.error(error);
        });
    }
    

10. Adım: Kullanıcı arabirimi öğeleri başvurusu ekleme

SPA uygulaması, kullanıcı arabirimi öğelerini denetlemek için JavaScript kullanır. Örneğin, oturum açma ve oturum kapatma düğmelerini görüntüler ve kullanıcıların kimlik belirteci taleplerini ekranda işler.

Kullanıcı arabirimi öğeleri başvurusu eklemek için aşağıdakileri yapın:

  1. Uygulama klasörünün içinde ui.jsadlı bir dosya oluşturun.

  2. ui.js dosyasına aşağıdaki kodu ekleyin:

    // Select DOM elements to work with
    const signInButton = document.getElementById('signIn');
    const signOutButton = document.getElementById('signOut')
    const titleDiv = document.getElementById('title-div');
    const welcomeDiv = document.getElementById('welcome-div');
    const tableDiv = document.getElementById('table-div');
    const tableBody = document.getElementById('table-body-div');
    const editProfileButton = document.getElementById('editProfileButton');
    const callApiButton = document.getElementById('callApiButton');
    const response = document.getElementById("response");
    const label = document.getElementById('label');
    
    function welcomeUser(claims) {
        welcomeDiv.innerHTML = `Token claims: </br></br> ${claims}!`
    
        signInButton.classList.add('d-none');
        signOutButton.classList.remove('d-none');
        welcomeDiv.classList.remove('d-none');
        callApiButton.classList.remove('d-none');
    }
    
    function logMessage(s) {
        response.appendChild(document.createTextNode('\n' + s + '\n'));
    }
    

11. Adım: SPA uygulamanızı çalıştırma

Komut kabuğunuzda aşağıdaki komutları çalıştırın:

npm install  
npm ./index.js
  1. Şuraya gidin: https://localhost:6420.
  2. Oturum aç'ı seçin.
  3. Kaydolma veya oturum açma işlemini tamamlayın.

Kimlik doğrulaması başarıyla tamamlandıktan sonra, ayrıştırılan kimlik belirteci ekranda görüntülenir. API uç noktanızı çağırmak için seçin Call API .

Sonraki adımlar