Tutorial: Memasukkan pengguna dan memanggil Microsoft Graph API dari aplikasi satu halaman (SPA) JavaScript menggunakan alur kode autentikasi

Dalam tutorial ini, Anda membuat aplikasi satu halaman JavaScript (SPA) yang memasukkan pengguna dan memanggil Microsoft Graph menggunakan alur kode otorisasi dengan PKCE. SPA yang Anda buat menggunakan Microsoft Authentication Library (MSAL) untuk JavaScript v2.0.

Dalam tutorial ini:

  • Jalankan alur kode otorisasi OAuth 2.0 dengan PKCE
  • Masukkan akun Microsoft pribadi serta akun kerja dan sekolah
  • Memperoleh token akses
  • Panggil Microsoft Graph atau API Anda sendiri yang memerlukan token akses yang diperoleh dari platform identitas Microsoft

MSAL.js 2.0 meningkatkan MSAL.js 1.0 dengan mendukung alur kode otorisasi di browser dan bukan alur peruntukan implisit. MSAL.js 2.0 TIDAK mendukung aliran implisit.

Prasyarat

Cara kerja aplikasi tutorial

Diagram showing the authorization code flow in a single-page application

Aplikasi yang Anda buat dalam tutorial ini memungkinkan JavaScript SPA untuk mengkueri Microsoft Graph API dengan memperoleh token keamanan dari platform identitas Microsoft. Dalam skenario ini, setelah pengguna masuk, token akses diminta dan ditambahkan ke permintaan HTTP di header otorisasi. Akuisisi dan perpanjangan token ditangani oleh Microsoft Authentication Library untuk JavaScript (MSAL.js).

Tutorial ini menggunakan MSAL.js, Microsoft Authentication Library untuk paket browser JavaScript v2.0.

Dapatkan sampel kode yang telah selesai

Anda dapat mengunduh proyek sampel tutorial yang telah selesai ini sebagai gantinya dengan mengkloning repositori ms-identity-javascript-v2 .

git clone https://github.com/Azure-Samples/ms-identity-javascript-v2.git

Untuk menjalankan proyek yang diunduh di lingkungan pengembangan lokal Anda, mulailah dengan membuat server localhost untuk aplikasi Anda seperti yang dijelaskan pada langkah 1 dari membuat proyek Anda. Setelah selesai, Anda dapat mengonfigurasi sampel kode dengan melompat ke langkah konfigurasi.

Untuk melanjutkan tutorial dan membuat aplikasi sendiri, lanjutkan ke bagian berikutnya, yaitu Membuat proyek Anda.

Membuat proyek

Setelah Anda menginstal Node.js , buat folder untuk menghosting aplikasi Anda, seperti msal-spa-tutorial.

Selanjutnya, terapkan server web Ekspres kecil untuk melayani file index.html Anda.

  1. Pertama, ubah ke direktori proyek di terminal Anda, lalu jalankan perintah npm berikut:

    npm init -y
    npm install @azure/msal-browser
    npm install express
    npm install morgan
    npm install yargs
    
  2. Selanjutnya, buat file bernama server.js dan tambahkan kode berikut:

    const express = require('express');
    const morgan = require('morgan');
    const path = require('path');
    
    const DEFAULT_PORT = process.env.PORT || 3000;
    
    // initialize express.
    const app = express();
    
    // Initialize variables.
    let port = DEFAULT_PORT;
    
    // Configure morgan module to log all requests.
    app.use(morgan('dev'));
    
    // Setup app folders.
    app.use(express.static('app'));
    
    // Set up a route for index.html
    app.get('*', (req, res) => {
        res.sendFile(path.join(__dirname + '/index.html'));
    });
    
    // Start the server.
    app.listen(port);
    console.log(`Listening on port ${port}...`);
    

Membuat UI SPA

  1. Buat folder aplikasi di direktori proyek Anda, dan di dalamnya buat file index.html untuk JavaScript SPA Anda. File ini mengimplementasikan UI yang dibuat dengan Bootstrap 4 Framework dan mengimpor file skrip untuk konfigurasi, autentikasi, dan panggilan API.

    Dalam file index.html, tambahkan kode berikut:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
      <title>Microsoft identity platform</title>
      <link rel="SHORTCUT ICON" href="./favicon.svg" type="image/x-icon">
    
       <!-- msal.min.js can be used in the place of msal.js; included msal.js to make debug easy -->
      <script src="https://alcdn.msauth.net/browser/2.30.0/js/msal-browser.js"
        integrity="sha384-o4ufwq3oKqc7IoCcR08YtZXmgOljhTggRwxP2CLbSqeXGtitAxwYaUln/05nJjit"
        crossorigin="anonymous"></script>
      
      <!-- adding Bootstrap 4 for UI components  -->
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
      <link rel="SHORTCUT ICON" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon">
    </head>
    
    <body>
      <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <a class="navbar-brand" href="/">Microsoft identity platform</a>
        <div class="btn-group ml-auto dropleft">
          <button type="button" id="SignIn" class="btn btn-secondary" onclick="signIn()">
            Sign In
          </button>
        </div>
      </nav>
      <br>
      <h5 class="card-header text-center">Vanilla JavaScript SPA calling MS Graph API with MSAL.js</h5>
      <br>
      <div class="row" style="margin:auto">
        <div id="card-div" class="col-md-3" style="display:none">
          <div class="card text-center">
            <div class="card-body">
              <h5 class="card-title" id="WelcomeMessage">Please sign-in to see your profile and read your mails</h5>
              <div id="profile-div"></div>
              <br>
              <br>
              <button class="btn btn-primary" id="seeProfile" onclick="seeProfile()">See Profile</button>
              <br>
              <br>
              <button class="btn btn-primary" id="readMail" onclick="readMail()">Read Mails</button>
            </div>
          </div>
        </div>
        <br>
        <br>
        <div class="col-md-4">
          <div class="list-group" id="list-tab" role="tablist">
          </div>
        </div>
        <div class="col-md-5">
          <div class="tab-content" id="nav-tabContent">
          </div>
        </div>
      </div>
      <br>
      <br>
    
      <!-- importing bootstrap.js and supporting js libraries -->
      <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous"></script>
      <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>
    
      <!-- importing app scripts (load order is important) -->
      <script type="text/javascript" src="./authConfig.js"></script>
      <script type="text/javascript" src="./graphConfig.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="./authPopup.js"></script>
      <script type="text/javascript" src="./graph.js"></script>
    </body>
    
    </html>
    
  2. Selanjutnya, juga di folder aplikasi, buat file bernama ui.js dan tambahkan kode berikut. File ini akan mengakses dan memperbarui elemen DOM.

    // Select DOM elements to work with
    const welcomeDiv = document.getElementById("WelcomeMessage");
    const signInButton = document.getElementById("SignIn");
    const cardDiv = document.getElementById("card-div");
    const mailButton = document.getElementById("readMail");
    const profileButton = document.getElementById("seeProfile");
    const profileDiv = document.getElementById("profile-div");
    
    function showWelcomeMessage(username) {
        // Reconfiguring DOM elements
        cardDiv.style.display = 'initial';
        welcomeDiv.innerHTML = `Welcome ${username}`;
        signInButton.setAttribute("onclick", "signOut();");
        signInButton.setAttribute('class', "btn btn-success")
        signInButton.innerHTML = "Sign Out";
    }
    
    function updateUI(data, endpoint) {
        console.log('Graph API responded at: ' + new Date().toString());
    
        if (endpoint === graphConfig.graphMeEndpoint) {
            profileDiv.innerHTML = ''
            const title = document.createElement('p');
            title.innerHTML = "<strong>Title: </strong>" + data.jobTitle;
            const email = document.createElement('p');
            email.innerHTML = "<strong>Mail: </strong>" + data.mail;
            const phone = document.createElement('p');
            phone.innerHTML = "<strong>Phone: </strong>" + data.businessPhones[0];
            const address = document.createElement('p');
            address.innerHTML = "<strong>Location: </strong>" + data.officeLocation;
            profileDiv.appendChild(title);
            profileDiv.appendChild(email);
            profileDiv.appendChild(phone);
            profileDiv.appendChild(address);
    
        } else if (endpoint === graphConfig.graphMailEndpoint) {
            if (!data.value) {
                alert("You do not have a mailbox!")
            } else if (data.value.length < 1) {
                alert("Your mailbox is empty!")
            } else {
                const tabContent = document.getElementById("nav-tabContent");
                const tabList = document.getElementById("list-tab");
                tabList.innerHTML = ''; // clear tabList at each readMail call
    
                data.value.map((d, i) => {
                    // Keeping it simple
                    if (i < 10) {
                        const listItem = document.createElement("a");
                        listItem.setAttribute("class", "list-group-item list-group-item-action")
                        listItem.setAttribute("id", "list" + i + "list")
                        listItem.setAttribute("data-toggle", "list")
                        listItem.setAttribute("href", "#list" + i)
                        listItem.setAttribute("role", "tab")
                        listItem.setAttribute("aria-controls", i)
                        listItem.innerHTML = d.subject;
                        tabList.appendChild(listItem)
    
                        const contentItem = document.createElement("div");
                        contentItem.setAttribute("class", "tab-pane fade")
                        contentItem.setAttribute("id", "list" + i)
                        contentItem.setAttribute("role", "tabpanel")
                        contentItem.setAttribute("aria-labelledby", "list" + i + "list")
                        contentItem.innerHTML = "<strong> from: " + d.from.emailAddress.address + "</strong><br><br>" + d.bodyPreview + "...";
                        tabContent.appendChild(contentItem);
                    }
                });
            }
        }
    }
    

Mendaftarkan aplikasi Anda

Ikuti langkah-langkah dalam Aplikasi satu halaman: Pendaftaran aplikasi untuk membuat pendaftaran aplikasi untuk SPA Anda.

Di langkah URI Pengalihan: MSAL.js 2.0 dengan alur kode otorisasi, masuk ke http://localhost:3000, lokasi default tempat aplikasi tutorial ini berjalan.

Jika Anda ingin menggunakan port yang berbeda, masukkan http://localhost:<port>, di mana <port> adalah nomor port TCP pilihan Anda. Jika Anda menentukan nomor port selain 3000, perbarui juga server.js dengan nomor port pilihan Anda.

Mengonfigurasi JavaScript SPA

Buat file bernama authConfig.js dalam folder aplikasi untuk memuat parameter konfigurasi Anda untuk autentikasi, lalu tambahkan kode berikut:

/**
 * Configuration object to be passed to MSAL instance on creation. 
 * For a full list of MSAL.js configuration parameters, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md 
 */
const msalConfig = {
    auth: {
        // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
        clientId: "Enter_the_Application_Id_Here",
        // Full directory URL, in the form of https://login.microsoftonline.com/<tenant-id>
        authority: "Enter_the_Cloud_Instance_Id_HereEnter_the_Tenant_Info_Here",
        // Full redirect URL, in form of http://localhost:3000
        redirectUri: "Enter_the_Redirect_Uri_Here",
    },
    cache: {
        cacheLocation: "sessionStorage", // This configures where your cache will be stored
        storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
    },
    system: {	
        loggerOptions: {	
            loggerCallback: (level, message, containsPii) => {	
                if (containsPii) {		
                    return;		
                }		
                switch (level) {		
                    case msal.LogLevel.Error:		
                        console.error(message);		
                        return;		
                    case msal.LogLevel.Info:		
                        console.info(message);		
                        return;		
                    case msal.LogLevel.Verbose:		
                        console.debug(message);		
                        return;		
                    case msal.LogLevel.Warning:		
                        console.warn(message);		
                        return;		
                }	
            }	
        }	
    }
};

/**
 * Scopes you add here will be prompted for user consent during sign-in.
 * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request.
 * For more information about OIDC scopes, visit: 
 * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
 */
const loginRequest = {
    scopes: ["User.Read"]
};

/**
 * Add here the scopes to request when obtaining an access token for MS Graph API. For more information, see:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md
 */
const tokenRequest = {
    scopes: ["User.Read", "Mail.Read"],
    forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token
};

Masih dalam folder aplikasi, buat file bernama graphConfig.js. Tambahkan kode berikut untuk menyediakan parameter konfigurasi kepada aplikasi Anda untuk memanggil Microsoft Graph API:

// Add here the endpoints for MS Graph API services you would like to use.
const graphConfig = {
    graphMeEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me",
    graphMailEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me/messages"
};

Ubah nilai di bagian graphConfig seperti yang dijelaskan di sini:

  • Enter_the_Graph_Endpoint_Here adalah instans Microsoft Graph API yang harus dikomunikasikan dengan aplikasi.
    • Untuk titik akhir Microsoft Graph API global, ganti kedua instans string ini dengan https://graph.microsoft.com.
    • Untuk titik akhir dalam penyebaran cloud nasional, lihat Penyebaran cloud nasional dalam dokumentasi Microsoft Graph.

Nilai graphMeEndpoint dan graphMailEndpoint dalam graphConfig.js Anda harus mirip dengan yang berikut ini jika Anda menggunakan titik akhir global:

graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages"

Menggunakan Microsoft Authentication Library (MSAL) untuk memasukkan pengguna

Muncul

Dalam folder aplikasi, buat file bernama authPopup.js dan tambahkan kode akuisisi autentikasi dan token berikut untuk pop-up masuk:

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

let username = "";

function selectAccount() {

    /**
     * See here for more info 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 === 0) {
        return;
    } else if (currentAccounts.length > 1) {
        // Add choose account code here
        console.warn("Multiple accounts detected.");
    } else if (currentAccounts.length === 1) {
        username = currentAccounts[0].username;
        showWelcomeMessage(username);
    }
}

function handleResponse(response) {

    /**
     * To see the full list of response object properties, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#response
     */

    if (response !== null) {
        username = response.account.username;
        showWelcomeMessage(username);
    } else {
        selectAccount();
    }
}

function signIn() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    myMSALObj.loginPopup(loginRequest)
        .then(handleResponse)
        .catch(error => {
            console.error(error);
        });
}

function signOut() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    const logoutRequest = {
        account: myMSALObj.getAccountByUsername(username),
        postLogoutRedirectUri: msalConfig.auth.redirectUri,
        mainWindowRedirectUri: msalConfig.auth.redirectUri
    };

    myMSALObj.logoutPopup(logoutRequest);
}

function getTokenPopup(request) {

    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */
    request.account = myMSALObj.getAccountByUsername(username);
    
    return myMSALObj.acquireTokenSilent(request)
        .catch(error => {
            console.warn("silent token acquisition fails. acquiring token using popup");
            if (error instanceof msal.InteractionRequiredAuthError) {
                // fallback to interaction when silent call fails
                return myMSALObj.acquireTokenPopup(request)
                    .then(tokenResponse => {
                        console.log(tokenResponse);
                        return tokenResponse;
                    }).catch(error => {
                        console.error(error);
                    });
            } else {
                console.warn(error);   
            }
    });
}

function seeProfile() {
    getTokenPopup(loginRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

function readMail() {
    getTokenPopup(tokenRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMailEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

selectAccount();

Pengalihan

Dalam folder aplikasi, buat file bernama authPopup.js dan tambahkan kode akuisisi autentikasi dan token berikut untuk pop-up masuk:

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

let username = "";

/**
 * A promise handler needs to be registered for handling the
 * response returned from redirect flow. For more information, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/acquire-token.md
 */
myMSALObj.handleRedirectPromise()
    .then(handleResponse)
    .catch((error) => {
        console.error(error);
    });

function selectAccount () {

    /**
     * See here for more info 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 === 0) {
        return;
    } else if (currentAccounts.length > 1) {
        // Add your account choosing logic here
        console.warn("Multiple accounts detected.");
    } else if (currentAccounts.length === 1) {
        username = currentAccounts[0].username;
        showWelcomeMessage(username);
    }
}

function handleResponse(response) {
    if (response !== null) {
        username = response.account.username;
        showWelcomeMessage(username);
    } else {
        selectAccount();
    }
}

function signIn() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    myMSALObj.loginRedirect(loginRequest);
}

function signOut() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    const logoutRequest = {
        account: myMSALObj.getAccountByUsername(username),
        postLogoutRedirectUri: msalConfig.auth.redirectUri,
    };

    myMSALObj.logoutRedirect(logoutRequest);
}

function getTokenRedirect(request) {
    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */
    request.account = myMSALObj.getAccountByUsername(username);

    return myMSALObj.acquireTokenSilent(request)
        .catch(error => {
            console.warn("silent token acquisition fails. acquiring token using redirect");
            if (error instanceof msal.InteractionRequiredAuthError) {
                // fallback to interaction when silent call fails
                return myMSALObj.acquireTokenRedirect(request);
            } else {
                console.warn(error);   
            }
        });
}

function seeProfile() {
    getTokenRedirect(loginRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

function readMail() {
    getTokenRedirect(tokenRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMailEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

Cara kerja kode

Saat pengguna memilih tombol Masuk untuk pertama kalinya, metode signIn akan memanggil loginPopup untuk memasukkan pengguna. Metode loginPopup membuka jendela pop-up dengan titik akhir platform identitas Microsoft untuk meminta dan memvalidasi info masuk pengguna. Setelah berhasil masuk, msal.js memulai alur kode otorisasi.

Pada titik ini, kode otorisasi yang dilindungi PKCE dikirim ke titik akhir token yang dilindungi CORS dan ditukar dengan token. Token ID, token akses, dan token refresh diterima oleh aplikasi Anda dan diproses oleh msal.js, dan informasi yang terkandung dalam token disimpan di-cache.

Token ID berisi informasi dasar tentang pengguna, seperti nama tampilannya. Jika Anda berencana menggunakan data yang diberikan oleh token ID, server back-end Anda harus memvalidasinya untuk menjamin bahwa token dikeluarkan untuk pengguna yang valid untuk aplikasi Anda.

Token akses memiliki masa pakai terbatas dan berakhir setelah 24 jam. Token refresh dapat digunakan untuk secara diam-diam memperoleh token akses baru.

SPA yang telah Anda buat dalam tutorial ini memanggil acquireTokenSilent dan/atau acquireTokenPopup untuk memperoleh token akses yang digunakan untuk membuat kueri Microsoft Graph API untuk info profil pengguna. Jika Anda memerlukan sampel yang memvalidasi token ID, lihat aplikasi sampel active-directory-javascript-singlepageapp-dotnet-webapi-v2 di GitHub. Sampel menggunakan ASP.NET web API untuk validasi token.

Mendapatkan token pengguna secara interaktif

Setelah masuk awal, aplikasi Anda tidak boleh meminta pengguna untuk mengotorisasi ulang setiap kali mereka perlu mengakses sumber daya yang dilindungi (artinya, untuk meminta token). Untuk mencegah permintaan autentikasi ulang tersebut, hubungi acquireTokenSilent. Namun, ada beberapa situasi di mana Anda mungkin harus memaksa pengguna untuk berinteraksi dengan platform identitas Microsoft. Misalnya:

  • Pengguna perlu memasukkan kembali info masuk mereka karena kata sandi telah kedaluwarsa.
  • Aplikasi meminta akses ke sumber daya dan Anda memerlukan persetujuan pengguna.
  • Otentikasi dua faktor diperlukan.

Panggilan acquireTokenPopup membuka jendela pop-up (atau acquireTokenRedirect mengalihkan pengguna ke platform identitas Microsoft). Di jendela tersebut, pengguna perlu berinteraksi dengan mengonfirmasi info masuk mereka, memberikan persetujuan ke sumber daya yang diperlukan, atau menyelesaikan otentikasi dua faktor.

Mendapatkan token pengguna secara diam-diam

Metode acquireTokenSilent ini menangani akuisisi dan perpanjangan token tanpa interaksi pengguna. Setelah loginPopup (atau loginRedirect) dijalankan untuk pertama kalinya, acquireTokenSilent adalah metode yang biasa digunakan untuk mendapatkan token yang digunakan untuk mengakses sumber daya yang dilindungi untuk panggilan berikutnya. (Panggilan untuk meminta atau memperpanjang token dilakukan secara diam-diam.) acquireTokenSilent mungkin gagal dalam beberapa kasus. Misalnya, kata sandi pengguna mungkin telah kedaluwarsa. Aplikasi Anda dapat menangani pengecualian ini dengan dua cara:

  1. Melakukan panggilan ke acquireTokenPopup dengan segera untuk memicu perintah masuk pengguna. Pola ini umumnya digunakan dalam aplikasi online di mana tidak ada konten yang tidak diautentikasi dalam aplikasi yang tersedia untuk pengguna. Sampel yang dihasilkan oleh penyiapan terpandu ini menggunakan pola ini.
  2. Tunjukkan secara visual kepada pengguna bahwa upaya masuk interaktif diperlukan sehingga pengguna dapat memilih waktu yang tepat untuk masuk, atau aplikasi dapat mencoba lagi acquireTokenSilent di lain waktu. Teknik ini biasanya digunakan ketika pengguna dapat menggunakan fungsi aplikasi lain tanpa terkendala. Misalnya, mungkin ada konten yang tidak diautentikasi yang tersedia dalam aplikasi. Dalam situasi ini, pengguna dapat memutuskan kapan mereka ingin masuk untuk mengakses sumber daya yang dilindungi, atau untuk me-refresh informasi yang tidak relevan.

Catatan

Tutorial ini menggunakan metode loginPopup dan acquireTokenPopup secara default. Jika Anda menggunakan Internet Explorer, kami menyarankan agar Anda menggunakan metode loginRedirect dan acquireTokenRedirect karena masalah yang diketahui dengan jendela Internet Explorer dan jendela pop-up. Untuk contoh pencapaian hasil yang sama dengan menggunakan metode pengalihan, lihat authRedirect.js di GitHub.

Menghubungi Microsoft Graph API

Buat file bernama graph.js di folder aplikasi dan tambahkan kode berikut untuk melakukan panggilan REST ke Microsoft Graph API:

/** 
 * Helper function to call MS Graph API endpoint
 * using the authorization bearer token scheme
*/
function callMSGraph(endpoint, token, callback) {
    const headers = new Headers();
    const bearer = `Bearer ${token}`;

    headers.append("Authorization", bearer);

    const options = {
        method: "GET",
        headers: headers
    };

    console.log('request made to Graph API at: ' + new Date().toString());

    fetch(endpoint, options)
        .then(response => response.json())
        .then(response => callback(response, endpoint))
        .catch(error => console.log(error));
}

Dalam aplikasi contoh yang dibuat dalam tutorial ini, metode callMSGraph() digunakan untuk membuat permintaan GET HTTP terhadap sumber daya yang dilindungi yang memerlukan token. Kemudian, permintaan mengembalikan konten ke penelepon. Metode ini akan menambahkan token yang diperoleh di header Otorisasi HTTP. Dalam aplikasi contoh yang dibuat dalam tutorial ini, sumber daya yang dilindungi adalah titik akhir me Microsoft Graph API, yang menampilkan informasi profil pengguna masuk.

Menguji aplikasi Anda

Anda telah menyelesaikan pembuatan aplikasi dan sekarang siap meluncurkan aplikasi server web Node.js dan menguji fungsi aplikasi.

  1. Mulai server web Node.js dengan menjalankan perintah berikut dari dalam akar folder proyek:

    npm start
    
  2. Di browser Anda, navigasikan ke http://localhost:3000 atau http://localhost:<port>, di mana <port> adalah port tempat yang didengarkan server web Anda. Anda akan melihat konten file index.html dan tombol Masuk.

Masuk ke aplikasi

Setelah browser memuat file index.html, pilih Masuk. Anda akan diminta untuk masuk dengan platform identitas Microsoft:

Web browser displaying sign-in dialog

Saat pertama kali masuk ke aplikasi, Anda diminta untuk memberikannya akses ke profil Anda dan membiarkan Anda masuk:

Content dialog displayed in web browser

Jika Anda menyetujui izin yang diminta, aplikasi web menampilkan nama pengguna Anda, menandakan keberhasilan masuk:

Results of a successful sign-in in the web browser

Memanggil Graph API

Setelah masuk, pilih Lihat Profil untuk melihat informasi profil pengguna yang ditampilkan dalam respons dari panggilan ke Microsoft Graph API:

Profile information from Microsoft Graph displayed in the browser

Informasi selengkapnya tentang cakupan dan izin yang didelegasikan

Microsoft Graph API memerlukan cakupan user.read untuk membaca profil pengguna. Secara default, cakupan ini secara otomatis ditambahkan di setiap aplikasi yang terdaftar di pusat admin Microsoft Entra. API lain untuk Microsoft Graph, serta API kustom untuk server ujung belakang, mungkin mewajibkan cakupan tambahan. Misalnya, Microsoft Graph API memerlukan cakupan Mail.Read untuk mencantumkan email pengguna.

Saat Anda menambahkan cakupan, pengguna Anda mungkin diminta untuk memberikan persetujuan tambahan untuk cakupan yang ditambahkan.

Jika API back-end tidak mengharuskan cakupan, yang tidak direkomendasikan, Anda dapat menggunakan clientId sebagai cakupan dalam panggilan untuk memperoleh token.

Bantuan dan dukungan

Jika Anda memerlukan bantuan, ingin melaporkan masalah, atau ingin mempelajari opsi dukungan, lihat Bantuan dan dukungan bagi pengembang.

Langkah berikutnya

  • Pelajari lebih lanjut dengan membangun aplikasi Halaman tunggal React (SPA) yang memasukkan pengguna dalam seri tutorial multi-bagian berikut.