Schnellstart: Registrieren und konfigurieren Sie eine SPA-Anwendung für Dataverse mit msal.js
Dieses Thema beschreibt den Prozess der Registrierung und Konfiguration der einfachsten Single-Page-Application (SPA) für den Zugriff auf Daten in Microsoft Dataverse unter Verwendung von msal.js und Cross-Origin Resource Sharing (CORS). Weitere Informationen: Verwenden Sie OAuth mit Cross-Origin Resource Sharing, um eine Single-Page-Applikation mit Dataverse zu verbinden.
Anforderungen
Greifen Sie auf eine Dataverse-Umgebung zu.
Ein Azure-Konto mit einem aktiven Abonnement.
Das Azure-Konto muss über die Berechtigung zum Verwalten von Anwendungen in Microsoft Entra ID verfügen. Jede der folgenden Microsoft Entra ID-Rollen umfasst die erforderlichen Berechtigungen:
Visual Studio Code (VS Code) Download
Ziel dieses Schnellstarts
Wenn Sie diesen Schnellstart abschließen, können Sie eine einfache SPA-Anwendung ausführen, über die sich der Benutzer authentifizieren und Daten aus Dataverse abrufen kann.
Wenn Sie die Anwendung debuggen, gibt es zunächst nur eine Schaltfläche Anmelden.
Klicken Sie auf Anmeldung, ein Popup-Fenster wird geöffnet, um Ihre Anmeldeinformationen einzugeben.
Nachdem Sie Ihre Anmeldeinformationen eingegeben haben, ist die Schaltflächen Anmelden ausgeblendet und Schaltflächen für Abmelden und Firmen abrufen werden angezeigt. Sie sehen außerdem eine Begrüßung mit Informationen zu Ihrem Benutzerkonto.
Klicken Sie auf die Schaltfläche Firmen abrufen, um 10 Firmendatensätze aus Ihrer Dataverse-Organisation abzurufen. Das Ergebnis wird im folgenden Screenshot angezeigt:
Schließlich können Sie auf die Schaltfläche Abmelden klicken, um sich abzumelden.
Hinweis
Diese SPA-Anwendung ist nicht als Muster zum Entwickeln von SPA-Anwendungen vorgesehen. Sie dient nur zu Beschreibung des Vorgangs der Registrierung und Konfiguration der Anwendung.
Ihren Dataverse Web-API Endpunkt abrufen
Verwenden Sie die Anweisungen in Entwicklerressourcen anzeigen, um eine Web-API Endpunkt für eine Umgebung zu identifizieren, auf die Sie zugreifen können. Sie sollte ungefähr so aussehen: https://yourorg.api.crm.dynamics.com/api/data/v9.2
.
Registrieren Ihrer Anwendung
Erweitern Sie im Power Platform Admin Center in der linken Navigation Admin Center und wählen Sie Microsoft Entra ID aus.
So öffnen Sie das Microsoft Entra Admin Center
Erweitern Sie Anwendungen und wählen Sie App-Registrierungen aus.
Klicken Sie auf Neue Registrierung. Dies öffnet das Formular Eine Anwendung registrieren.
Geben Sie unter Eine Anwendung registrieren einen Namen ein. Verwenden Sie für diesen Schnellstart den Namen Einfache SPA.
Für Unterstützte Kontotypen, sollte die Standardauswahl folgendermaßen sein:
Nur Konten in diesem Organisationsverzeichnis (nur <Mandatenname> – einzelner Mandant). Nehmen Sie hier keine Änderungen vor.Als Umleitungs-URI (optional) verwenden Sie diese Optionen:
- Eine Plattform auswählen: Einzelseitenanwendung (SPA)
e.g. https://example.com/auth
:http://localhost:5500/index.html
Klicken Sie auf Registrieren.
Kopieren Sie im Überblick-Bereich die folgenden Werte, da Sie sie im letzten Schritt von Erstellen eines Webanwendungsprojekts benötigen.
- Anwendungs(client)-ID
- Verzeichnis (Mandant) ID
Wählen Sie API-Berechtigungen aus.
Klicken Sie auf Berechtigung hinzufügen.
In dem Fly-Out API-Berechtigungen anfordern wählen Sie Dynamics CRM aus.
- Wenn Sie Dynamics CRMnicht sehen, suchen Sie nach Dataverse. Oder wählen Sie die Registerkarte Von meiner Organisation verwendete APIs aus und suchen Sie nach Dataverse.
Wählen Sie die delegierte user_impersonation-Berechtigung aus.
Klicken Sie auf Berechtigungen hinzufügen.
Die konfigurierten Berechtigungen sollten wie folgt aussehen, wenn Sie fertig sind:
Live-Server Visual Studio Code-Erweiterung installieren
Live-Server ist eine Visual Studio Code-Erweiterung, mit der Sie ganz einfach einen lokalen Entwicklungsserver für Webseiten starten können.
Befolgen Sie diese Anweisungen, um die Live Server-Erweiterung für VS Code im VS Code Marketplace zu finden und zu installieren:
Nachdem Sie die Live Server-Erweiterung installiert haben, nehmen Sie diese Änderungen an den Standardeinstellungen vor.
Klicken Sie auf das Zahnradsymbol in VS Code und wählen Sie Einstellungen aus, oder verwenden Sie das
Ctrl+,
-Tastaturkürzel.Geben Sie
liveServer.settings.host
in das Suchfenster ein und ändern Sie den Standardwert von127.0.0.1
zulocalhost
.
Erstellen eines Webanwendungsprojekts
Erstellen Sie einen Ordner auf Ihrem Computer. Der Name ist nicht wichtig, aber für den Zweck dieser Anweisungen nennen Sie ihn
simplespa
.Öffnen Sie VS Code und wählen Sie im Menü Datei > Ordner öffnen aus. Wählen Sie den Ordner
simplespa
aus.Erstellen Sie eine neue HTML-Datei im Ordner namens
index.html
. (Nichtindex.htm
)Kopieren Sie den folgenden Inhalt in die Datei Index.html:
<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> const baseUrl = "https://org.api.crm.dynamics.com"; //<= Change this const clientId = "11111111-1111-1111-1111-111111111111"; //<= Change this const tenantId = "22222222-2222-2222-2222-222222222222"; //<= Change this const redirectUrl = "http://localhost:5500/index.html"; const webAPIEndpoint = baseUrl +"/api/data/v9.2"; // Configuration object to be passed to MSAL instance on creation. const msalConfig = { auth: { clientId: clientId, // Full directory URL, in the form of https://login.microsoftonline.com/<tenant-id> authority: "https://login.microsoftonline.com/"+tenantId, redirectUri: redirectUrl, }, cache: { cacheLocation: "sessionStorage" // This configures where your cache will be stored }, 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; } } } } }; </script> <!-- Latest version of msal-browser.js from CDN as of 2022/09 --> <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.28.1/js/msal-browser.min.js"> </script> <style> body { font-family: 'Segoe UI'; } table { border-collapse: collapse; } td, th { border: 1px solid black; } #message { color: green; } </style> </head> <body> <div> <button id="loginButton" onclick="signIn()">Login</button> <button id="logoutButton" onclick="signOut()" style="display:none;">Logout</button> <button id="getAccountsButton" onclick="getAccounts(writeTable)" style="display:none;">Get Accounts</button> <div id="message"></div> <table id="accountsTable" style="display:none;"> <thead><tr><th>Name</th><th>City</th></tr></thead> <tbody id="accountsTableBody"></tbody> </table> </div> <script> const loginButton = document.getElementById("loginButton"); const logoutButton = document.getElementById("logoutButton"); const getAccountsButton = document.getElementById("getAccountsButton"); const accountsTable = document.getElementById("accountsTable"); const accountsTableBody = document.getElementById("accountsTableBody"); const message = document.getElementById("message"); // Create the main myMSALObj instance const myMSALObj = new msal.PublicClientApplication(msalConfig); let username = ""; // Sets the username. Called at the end of this script. function selectAccount() { 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); } } // Called by the loginButton function signIn() { myMSALObj.loginPopup({ scopes: ["User.Read",baseUrl+"/user_impersonation"] //<= Includes Dataverse scope }) .then(response =>{ if (response !== null) { username = response.account.username; showWelcomeMessage(username); } else { selectAccount(); } }) .catch(error => { console.error(error); }); } // Shows greeting and enables logoutButton and getAccountsButton // Called from signIn or selectAccount functions function showWelcomeMessage(username) { message.innerHTML = `Welcome ${username}`; loginButton.style.display = "none"; logoutButton.style.display = "block"; getAccountsButton.style.display = "block"; } // Called by the logoutButton function signOut() { const logoutRequest = { account: myMSALObj.getAccountByUsername(username), postLogoutRedirectUri: msalConfig.auth.redirectUri, mainWindowRedirectUri: msalConfig.auth.redirectUri }; myMSALObj.logoutPopup(logoutRequest); } // Provides the access token for a request, opening pop-up if necessary. // Used by GetAccounts function function getTokenPopup(request) { 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); } }); } // Retrieves top 10 account records from Dataverse function getAccounts(callback) { // Gets the access token getTokenPopup({ scopes: [baseUrl+"/.default"] }) .then(response => { getDataverse("accounts?$select=name,address1_city&$top=10", response.accessToken, callback); }).catch(error => { console.error(error); }); } /** * Helper function to get data from Dataverse * using the authorization bearer token scheme * callback is the writeTable function below */ function getDataverse(url, token, callback) { const headers = new Headers(); const bearer = `Bearer ${token}`; headers.append("Authorization", bearer); // Other Dataverse headers headers.append("Accept", "application/json"); headers.append("OData-MaxVersion", "4.0"); headers.append("OData-Version", "4.0"); const options = { method: "GET", headers: headers }; console.log('GET Request made to Dataverse at: ' + new Date().toString()); fetch(webAPIEndpoint+"/"+url, options) .then(response => response.json()) .then(response => callback(response)) .catch(error => console.log(error)); } // Renders the table with data from GetAccounts function writeTable(data) { data.value.forEach(function (account) { var name = account.name; var city = account.address1_city; var nameCell = document.createElement("td"); nameCell.textContent = name; var cityCell = document.createElement("td"); cityCell.textContent = city; var row = document.createElement("tr"); row.appendChild(nameCell); row.appendChild(cityCell); accountsTableBody.appendChild(row); }); accountsTable.style.display = "block"; getAccountsButton.style.display = "none"; } selectAccount(); </script> </body> </html>
Hinweis
Der JavaScript-Code in der HTML-Seite wurde aus dem hier veröffentlichten Beispielcode angepasst: https://github.com/Azure-Samples/ms-identity-javascript-v2, der eine Verbindung mit Microsoft Graph herstellt.
Der Hauptunterschied besteht in den Bereichen, die beim Abrufen von Zugriffstoken verwendet werden.
Verwenden Sie diese Bereiche für die Anmeldeschaltfläche:
// Called by the loginButton function signIn() { myMSALObj.loginPopup({ scopes: ["User.Read",baseUrl+"/user_impersonation"] //<= Includes Dataverse scope })
Diese Bereiche umfassen sowohl Microsoft Graph
User.Read
-Umfang als auch den Dataverseuser_impersonation
-Umfang. Durch die Einbeziehung dieser beiden Bereiche bei der Anmeldung enthält der anfängliche Zustimmungsdialog alle erforderlichen Bereiche, die in der Anwendung verwendet werden.Wenn Sie dann den Bereich angeben, der für den Aufruf von Dataverse verwendet wird, können Sie
/.default
oder/user_impersonation
verwenden.// Retrieves top 10 account records from Dataverse function getAccounts(callback) { // Gets the access token getTokenPopup({ scopes: [baseUrl+"/.default"] })
Der
/user_impersonation
-Umfang funktioniert nur für delegierte Berechtigungen, was hier der Fall ist, sodass er verwendet werden könnte./.default
funktioniert sowohl für delegierte als auch für Anwendungsberechtigungen.Wenn Sie den
baseUrl+"/user_impersonation"
-Umfang beim Einloggen nicht einschließen, muss der Benutzer ein zweites Mal zustimmen, wenn er zum ersten Mal auf die Schaltfläche Konten abrufen klickt.Weitere SPA-Beispiele und Tutorials finden Sie hier: Dokumentation für einseitige Anwendungen (SPA)..
Suchen Sie auf der Seite Index.html die folgenden Konfigurationsvariablen und legen Sie sie mit den Informationen fest, die Sie in früheren Schritten gesammelt haben: Ihren Dataverse Web-API Endpunkt abrufen und Ihre Anwendung registrieren.
const baseUrl = "https://org.api.crm.dynamics.com"; //<= Change this const clientId = "11111111-1111-1111-1111-111111111111"; //<= Change this const tenantId = "22222222-2222-2222-2222-222222222222"; //<= Change this
App debuggen
Weil Sie die Live Server-Erweiterung in Live-Server Visual Studio Code-Erweiterung installieren installiert haben, sollten Sie diese Schaltfläche in der VS Code-Symbolleiste finden: .
Klicken Sie auf die Schaltfläche Aktiv schalten und ein neues Browserfenster öffnet sich unter
http://localhost:5500/index.html
und rendert die Seite Index.html.Wenn Sie die App zum ersten Mal ausführen und auf die Anmelden-Schaltfläche klicken, erhalten Sie einen Zustimmungsdialog wie diesen:
Wenn Sie ein Administrator sind, können Sie das Zustimmung im Namen Ihrer Organisation-Kontrollkästchen aktivieren, das es anderen ermöglicht, die App ebenfalls auszuführen, ohne den Berechtigungen angefordert-Dialog verwenden zu müssen.
Klicken Sie auf Annehmen, um mit dem Testen fortzufahren, um sicherzustellen, dass die App wie in Ziel dieses Schnellstarts beschrieben funktioniert.
Problembehandlung
Die Erfahrung in diesem Schnellstart hängt davon ab, ob die Live Server-Porteinstellung der Standardwert ist: 5500
. Wenn Sie Live Server bereits installiert und die Porteinstellung geändert haben, müssen Sie die Standardeinstellung oder die in der App-Registrierung festgelegte URL ändern.
Bitte beachten Sie, dass der liveServer.settings.port
auch für den Arbeitsbereich festgelegt werden kann und die Benutzer-Einstellung überschreiben wird.
Wenn Sie mehrere Live Server-Instanzen öffnen, wird die Porteinstellung möglicherweise auf 5501 oder höher erhöht. Dadurch wird der für die Authentifizierung verwendete Rückruf unterbrochen, da der Port in der Anwendungsregistrierung als http://localhost:5500/index.html
„fest codiert“ ist.
Siehe auch
Dokumentation für Einzelseitenanwendungen (SPA)
Verwenden Sie OAuth mit herkunftsübergreifender Ressourcenfreigabe, um eine Single-Page-Anwendung mit Dataverse zu verbinden
Erstellen von Client-Anwendungen
Hinweis
Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)
Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).