Exemplarische Vorgehensweise: Mehrinstanzenfähige Server-zu-Server-Authentifizierung
Veröffentlicht: Januar 2017
Gilt für: Dynamics 365 (online)
In dieser exemplarischen Vorgehensweise werden die Schritte beschrieben, um eine Mehrmandantenwebanwendung zu erstellen, die sich mit einem Dezember 2016 Update für Microsoft Dynamics 365 (online)-Mandanten über die Microsoft Visual Studio 2015-MVC-Webanwendungsvorlage verbinden kann.
Anforderungen
Visual Studio 2015 mit den Web-Entwickler-Tools installiert
Ein Dezember 2016 Update für Microsoft Dynamics 365 (online)-Mandant, der Ihrem Azure Active Directory-Mandanten (Azure AD) zugeordnet ist.
Ein zweiter Dezember 2016 Update für Microsoft Dynamics 365 (online)-Mandant, der einem anderen Azure AD-Mandaten zugeordnet ist. Dieser Mandant ist der Abonnent Ihrer Anwendung. Es kann sich um ein Dezember 2016 Update für Microsoft Dynamics 365 (online)-Probeabonnement handeln.
Ziel dieser exemplarischen Vorgehensweise
Wenn Sie diese exemplarische Vorgehensweise abgeschlossen haben, haben Sie eine MVC-Webanwendung, die WhoAmIRequest Class zum Abrufen von Daten über den Benutzer verwendet, der die Anwendung zur Verbindung mit dem Dynamics 365 (online)-Mandanten nutzt.
Wenn die App erfolgreich ausgeführt wird, sehen Sie einen Anmelden-Befehl in der oberen rechten Ecke.
Klicken Sie auf den Anmelden-Befehl, und Sie werden zu Azure AD für Ihre Anmeldeinformationen umgeleitet.
Wenn Sie sich anmelden, sehen Sie, den Befehl WhoAmI.
Klicken Sie auf WhoAmI und Sie sollten folgendes sehen:
Wenn Sie Ihren Dynamics 365-Mandanten abrufen, sehen Sie, dass sich die Ergebnisse der WhoAmI-Nachricht auf ein bestimmtes Anwendungsbenutzerkonto beziehen, das Sie konfiguriert haben, damit es statt des aktuell verwendeten Benutzerkontos für die Webanwendung verwendet wird.
Überprüfen des Azure AD-Mandaten
Bevor Sie beginnen, stellen Sie eine Verbindung mit Office 365-Administratorcenterhttps://portal.office.com her und prüfen im Administratorcenter-Dropdown, dass Dynamics 365 und Azure AD angezeigt werden.
Wenn Ihr Azure AD-Abonnement keinem Dynamics 365-Abonnement zugeordnet ist, können Sie keine Rechte für die Anwendung zum Zugriff auf Dynamics 365-Daten gewähren.
Falls Sie diese Option nicht sehen, finden Sie unter Registrieren Ihres kostenlosen Azure Active Directory-Abonnements Informationen zur Registrierung eines Azure AD-Aabonnements.
Wenn Sie bereits ein Azure-Abonnement haben, dies aber nicht Ihrem Microsoft Office 365-Konto zugeordnet ist, erfahren Sie unter Zuordnen des Office 365-Kontos zu Azure AD Informationen zum Erstellen und Verwalten von Apps.
Erstellen einer MVC-Webanwendung
Mit Visual Studio 2015 können Sie eine neue MVC-Webanwendung erstellen und diese mit dem Azure AD-Mandanten registrieren.
Öffnen Sie Visual Studio 2015.
Stellen Sie sicher, dass Sie in Microsoft-Konto mit dem Konto angemeldet sind, das über Zugriff auf den Azure AD-Mandaten hat, den Sie verwenden möchten, um die Anwendung zu registrieren.
Klicken Sie auf Neues Projekt und wählen Sie .NET Framework 4.6.1 und die ASP.NET-Webanwendung-Vorlage aus.
Klicken Sie auf OK und wählen Sie im Dialog "Neues ASP.NET-Projekt" die Option MVC.
Klicken Sie auf die Schaltfläche Authentifizierung ändern, und wählen Sie im Dialogfeld Arbeits- und Schulkonten aus.
Wählen Sie im Dropdown die Option Cloud – mehrere Organisationen aus.
Klicken Sie auf OK, und schließen Sie die Projekterstellung ab.
Hinweis
Ein Visual Studio-Projekt auf diese Art zu erstellen, sorgt für die Registrierung der Anwendung mit Ihrem Azure AD-Mandanten und fügt die folgenden Schlüssel zu Web.Config appSettings hinzu:
<add key="ida:ClientId" value="baee6b74-3c39-4c04-bfa5-4414f3dd1c26" /> <add key="ida:AADInstance" value="https://login.microsoftonline.com/" /> <add key="ida:ClientSecret" value="HyPjzuRCbIl/7VUJ2+vG/+Gia6t1+5y4dvtKAcyztL4=" />
Registrieren der Anwendung bei Azure AD
Wenn Sie die Schritte in Erstellen einer MVC-Webanwendung durchgeführt haben, sollten Sie feststellen, dass das Webanwendungsprojekt, das Sie in Visual Studio erstellt haben, bereits den Azure AD-Anwendungen registriert ist. Es gibt noch einen weiteren Schritt, den Sie im Azure AD-Portal ausführen müssen.
Wechseln Sie zu https://portal.azure.com und wählen Sie Azure Active Directory aus.
Klicken Sie auf App-Registrierungen und suchen Sie nach der Anwendung, die Sie in Visual Studio verwenden. Im Bereich Allgemein überprüfen Sie die Eigenschaften:
Stellen Sie sicher, dass die Anwendungs-ID-Eigenschaft dem ClientId-Wert in Ihrer Web.Config appSettings entspricht.
Der Homepage-URL-Wert muss der SSL URL-Eigenschaft in Ihrem Visual Studio-Projekt entsprechen und sollte auf eine localhost-URL verweisen (z. B. https://localhost:44392/).
Hinweis
Sie müssen dies später ändern, wenn Sie die Anwendung veröffentlichen. Aber Sie müssen dies zum Debuggen auf den richtigen localhost-Wert konfiguriert haben.
Sie müssen Ihrer Anwendung Rechte geben, um auf die Dynamics 365-Daten zuzugreifen. Im Bereich API Zugriff klicken Sie auf Erforderliche Berechtigungen. Sie sollten sehen, dass es bereits die Berechtigungen für Windows Azure Active Directory hat.
Klicken Sie auf Hinzufügen, und wählen Sie Eine API auswählen aus. Wählen Sie in der Liste Dynamics 365 aus, klicken Sie auf die Schaltfläche Auswählen.
In Berechtigungen wählen wählen Sie Zugriff auf Dynamics 365 als Organisationsbenutzer aus. Klicken Sie dann auf die Schaltfläche Auswählen.
Klicken Sie auf Fertig, um diese Berechtigungen hinzufügen. Wenn Sie fertig sind, sollten Sie die übernommenen Berechtigungen finden:
Im Bereich API-Zugriff bestätigen Sie, dass ein Wert Schlüssel hinzugefügt wurde. Der Schlüssel-Wert ist nicht im Azure-Portal sichtbar, nachdem die Anwendung erstellt wurde, jedoch wurde dieser Wert zu Web.Config appSettings als ClientSecret hinzugefügt.
Erstellen eines Anwendungsbenutzers
Mithilfe der Schritte in Erstellen Sie einen Dynamics 365 Anwendungsbenutzer erstellen Sie einen Anwendungs-ID-Wert aus der Anwendungsregistrierung, der dem ClientId-Wert in Web.Config entspricht.
Assemblies hinzufügen
Fügen Sie die folgenden NuGet-Pakete zu Ihrem Projekt hinzu
Paket |
Version |
---|---|
Microsoft.CrmSdk.CoreAssemblies |
Neueste Version |
Microsoft.IdentityModel.Clients.ActiveDirectory |
2.22.302111727 |
Microsoft.IdentityModel.Tokens |
5.0.0 |
Microsoft.Azure.ActiveDirectory.GraphClient |
2.1.0 |
Hinweis
Aktualisieren Sie die Microsoft.IdentityModel.Clients.ActiveDirectory-Assemblies nicht auf die neuste Version. Version 3.x der Assemblies ändern eine Schnittstelle, von der Microsoft.CrmSdk.CoreAssemblies abhängig ist.
Informationen zum Verwalten von NuGet-Paketen finden Sie unter NuGet-Dokumentation: Verwalten von NuGet-Paketen mit der Benutzeroberfläche
Anwenden von Codeänderungen auf die MVC-Vorlage
Die folgenden Codeänderungen bieten grundlegende Funktionalitäten zur Verwendung der Dynamics 365WhoAmI-Nachricht und Prüfung ob die Anwendungsbenutzerkontoidentität von der Anwendung verwendet wird.
Web.config
Fügen Sie die folgenden Schlüssel zu appSettings hinzu.
<add key="ida:OrganizationHostName" value="https://{0}.crm.dynamics.com" />
Der ida:OrganizationHostName-Zeichenfolge wird der Dynamics 365-Online-Organisations-Name des Abonnenten als Platzhalter hinzugefügt, sodass auf den richtigen Service zugegriffen wird.
<add key="owin:appStartup" value="<your app namespace>.Startup" />
Die owin:appStartup-Zeichenfolge stellt sicher, dass die OWIN-Middleware die Startup-Klasse in diesem Projekt verwendet. Andernfalls wird die folgende Fehlermeldung angezeigt:
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
Weitere Informationen: ASP.NET: OWIN-Startklassenerkennung
Controllers/HomeController.cs
Fügen Sie den AllowAnonymous-Decorator zur Index-Aktion hinzu. So ist der Zugriff auf die Standardseite ohne Authentifizierung möglich.
using System.Web.Mvc;
namespace SampleApp.Controllers
{
[Authorize]
public class HomeController : Controller
{
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
Hinweis
In der Webanwendung oder im Service wird nicht erwartet, dass Sie den anonymen Zugriff zulassen. Der anonyme Zugriff wird hier der Einfachheit halber verwendet. Die Steuerung des Zugriffs auf die Anwendung ist kein Teil dieser exemplarischen Vorgehensweise.
Views/Shared/_Layout.cshtml
Um den Befehlslink WhoAmI für authentifizierte Benutzer anzuzeigen, müssen Sie die Datei ändern.
Suchen Sie das div-Element mit einer Klasse navbar-collapse collapse und bearbeiten Sie dieses, um den folgenden Code hinzufügen:
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
@if (Request.IsAuthenticated)
{
<li>@Html.ActionLink("WhoAmI", "Index", "CrmSdk")</li>
}
</ul>
@Html.Partial("_LoginPartial")
</div>
App_Start/Startup.Auth.cs
Die folgenden Änderungen rufen das Consent-Framework auf, wenn sich ein neuer Mandant an der Anwendung anmeldet:
public partial class Startup
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
//Not used
//private string graphResourceID = "https://graph.windows.net";
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private string authority = aadInstance + "common";
private ApplicationDbContext db = new ApplicationDbContext();
//Added
private string OrganizationHostName = ConfigurationManager.AppSettings["ida:OrganizationHostName"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions { });
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
/*
instead of using the default validation
(validating against a single issuer value, as we do in line of business apps),
we inject our own multitenant validation logic
*/
ValidateIssuer = false,
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
SecurityTokenValidated = (context) =>
{
return Task.FromResult(0);
},
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string tenantID = context
.AuthenticationTicket
.Identity
.FindFirst("https://schemas.microsoft.com/identity/claims/tenantid")
.Value;
/* Not used
string signedInUserID = context
.AuthenticationTicket
.Identity
.FindFirst(ClaimTypes.NameIdentifier)
.Value;
*/
//Added
var resource = string.Format(OrganizationHostName, '*');
//Added
Uri returnUri = new Uri(
HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)
);
/* Changed below
AuthenticationContext authContext =
new AuthenticationContext(
aadInstance + tenantID,
new ADALTokenCache(signedInUserID)
);
*/
//Changed version
AuthenticationContext authContext =
new AuthenticationContext(aadInstance + tenantID);
/* Changed below
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code,
new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
credential,
graphResourceID);
*/
//Changed version
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code,
new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
credential,
resource);
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.OwinContext.Response.Redirect("/Home/Error");
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
}
});
}
}
Controllers/CrmSdkController hinzufügen
Fügen Sie die folgenden CrmSdkController.cs zum Controllers-Ordner hinzu. Dieser Code führt die WhoAmI-Nachricht aus
Klicken Sie mit recht auf den Controllers Ordner, und wählen Sie Hinzufügen > Controller… aus
Wählen Sie im Dialogfeld Gerüst hinzufügen die Option MVC5-Controller – leer aus
Klicken Sie auf Hinzufügen.
Fügen Sie den folgenden Code ein. Ersetzen Sie <Your app namespace> mit dem Namespace der App.
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.WebServiceClient;
using System; using System.Configuration;
using System.Linq;
using System.Security.Claims;
using System.Web.Mvc;
namespace <Your app namespace>
{
[Authorize]
public class CrmSdkController : Controller
{
private string clientId =
ConfigurationManager.AppSettings["ida:ClientId"];
private string authority =
ConfigurationManager.AppSettings["ida:AADInstance"] + "common";
private string aadInstance =
ConfigurationManager.AppSettings["ida:AADInstance"];
private string OrganizationHostName =
ConfigurationManager.AppSettings["ida:OrganizationHostName"];
private string appKey =
ConfigurationManager.AppSettings["ida:ClientSecret"];
// GET: CrmSdk
public ActionResult Index()
{
string tenantID = ClaimsPrincipal
.Current
.FindFirst("https://schemas.microsoft.com/identity/claims/tenantid")
.Value;
// Clean organization name from user logged
string organizationName = User.Identity.Name.Substring(
User.Identity.Name.IndexOf('@') + 1,
User.Identity.Name.IndexOf('.') - (User.Identity.Name.IndexOf('@') + 1)
);
//string crmResourceId = "https://[orgname].crm.microsoftonline.com";
var resource = string.Format(OrganizationHostName, organizationName);
// Request a token using application credentials
ClientCredential clientcred = new ClientCredential(clientId, appKey);
AuthenticationContext authenticationContext =
new AuthenticationContext(aadInstance + tenantID);
AuthenticationResult authenticationResult =
authenticationContext.AcquireToken(resource, clientcred);
var requestedToken = authenticationResult.AccessToken;
// Invoke SDK using using the requested token
using (var sdkService =
new OrganizationWebProxyClient(
GetServiceUrl(organizationName), false)
)
{
sdkService.HeaderToken = requestedToken;
OrganizationRequest request = new OrganizationRequest() {
RequestName = "WhoAmI"
};
OrganizationResponse response = sdkService.Execute(request);
return View((object)string.Join(",", response.Results.ToList()));
}
}
private Uri GetServiceUrl(string organizationName)
{
var organizationUrl = new Uri(
string.Format(OrganizationHostName, organizationName)
);
return new Uri(
organizationUrl +
@"/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2"
);
}
}
}
Views/CrmSdk
Fügen Sie eine neue Ansicht namens Index ein.
Klicken Sie mit recht auf den CrmSdk Ordner, und wählen Sie Hinzufügen > Ansicht… aus
Legen Sie im Dialogfeld Ansicht hinzufügen die folgenden Werte fest:
Klicken Sie auf Hinzufügen.
Ersetzen Sie den generierten Code durch Folgendes:
@model string @{ ViewBag.Title = "SDK Connect"; } <h2>@ViewBag.Title.</h2> <p>Connected and executed sdk command WhoAmI.</p> <p>Value: @Model</p>
Debuggen der App
Wenn Sie F5 drücken, um die Anwendung debuggen, können Sie einen Fehler erhalten, dass das Zertifikat, mit dem über SSL auf localhost zugegriffen wird, nicht vertrauenswürdig ist. Die folgenden Links lösen dieses Problem in Visual Studio und IIS-Express:
Hinweis
Für diesen Schritt können Sie einfach die Microsoft-Konto verwenden, die dem Azure AD-Mandaten und dem Dynamics 365-Mandaten zugeordnet ist. Dies ist nicht wirklich ein Multi-Mandanten-Szenario. Wir führen das im nächsten Schritt aus. Dieser Schritt ist nur, um zu überprüfen, ob der Code funktioniert, bevor eine zusätzliche Komplexität durch das Testen der tatsächlichen Multi-Mandanten-Funktion entsteht.
Nutzen Sie die in Ziel dieser exemplarischen Vorgehensweise beschriebenen Schritte, um die Anwendung zu testen.
An dieser Stelle können Sie sicherstellen, dass das Anwendungsbenutzerkonto verwendet wurde. Eine einfache Möglichkeit hierzu ist die Verwendung der Dynamics 365-Web-API. Geben Sie die folgende URL in einer separaten Registerkarte oder in einem Fenster ein. Ersetzen Sie den UserId-Wert aus der Anwendung.
[Organization URI]/api/data/v8.2/systemusers(<UserId value>)?$select=fullname
Die JSON-Antwort soll folgendes anzeigen. Beachten Sie, dass der fullname-Wert der Anwendungsbenutzer ist, den Sie im Erstellen eines Anwendungsbenutzers Schritt erstellt haben, und nicht der Dynamics 365-Benutzer, den Sie verwendet haben, um sich an der Anwendung anzumelden.
{
"@odata.context": "[Organization Uri]/api/data/v8.2/$metadata#systemusers(fullname)/$entity",
"@odata.etag": "W/\"603849\"",
"fullname": "S2S User",
"systemuserid": "31914b34-be8d-e611-80d8-00155d892ddc",
"ownerid": "31914b34-be8d-e611-80d8-00155d892ddc"
}
Konfigurieren des Testabonnenten
Nachdem Sie überprüfen konnten, dass die Anwendung funktioniert, müssen Sie die Konnektivität zu einem andren Dynamics 365 (online)-Mandaten testen. Mit einer anderen Dynamics 365 (online)-Organisation müssen Sie die folgenden Schritte ausführen.
Zustimmung des abonnierenden Mandanten erteilen
Um eine Zustimmung zu gewähren, führen Sie die folgenden Schritte aus, während Sie als Azure AD-Admin angemeldet sind:
Während Sie die Anwendung debuggen, öffnen Sie ein InPrivate- oder Inkognito-Fenster.
Geben Sie im Adressfeld des Fensters die URL für Ihre App ein (z. B. https://localhost:44392/).
Klicken Sie auf die Schaltfläche Anmelden, und Sie werden aufgefordert zuzustimmen.
Nachdem Sie zugestimmt haben, gelangen Sie zur App zurück, aber Sie können diese noch nicht verwenden. Wenn Sie auf WhoAmI klicken, sehen Sie die folgende Ausnahme:
System.ServiceModel.Security.MessageSecurityException
HResult=-2146233087
Message=The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Bearer authorization_uri=https://login.windows.net/4baaeaaf-2771-4583-99eb-7c7e39aa1e74/oauth2/authorize, resource_id=https://<org name>.crm.dynamics.com/'.
InnerException.Message =The remote server returned an error: (401) Unauthorized.
Wenn Sie zustimmen, wird die Anwendung aus Ihrem Azure AD-Mandaten zu den Anwendungen im Active Directory-Mandanten des Abonnenten hinzugefügt.
Erstellen einer benutzerdefinierten Sicherheitsrolle für den Abonnentenmandanten
Der Anwendungsbenutzer, den Sie zum Erstellen benötigen, muss einer benutzerdefinierten Sicherheitsrolle mit seinen Berechtigungen zugeordnet sein. Für diesen manuellen Testsschritt müssen Sie zuerst eine benutzerdefinierte Sicherheitsrolle manuell erstellen.Weitere Informationen:TechNet: Erstellen oder Bearbeiten einer Sicherheitsrolle
Hinweis
Der Anwendungsbenutzer darf nicht einer der standardmäßigen Dynamics 365-Sicherheitsrollen zugeordnet werden. Sie müssen eine benutzerdefinierte Sicherheitsrolle zur Zuordnung mit dem Anwendungsbenutzer erstellen.
Erstellen des Abonnentenanwendungsbenutzers
Für diese exemplarische Vorgehensweise erstellen wir den Anwendungsbenutzer manuell, um die Verbindung von anderen Mandaten zu überprüfen. Wenn Sie für tatsächliche Abonnenten bereitstellen, können Sie dieses automatisieren.Weitere Informationen:Bereiten Sie eine Möglichkeit vor, um den Anwendungsbenutzer bereitzustellen
Sie erstellen den Anwendungsbenutzer manuell mithilfe der gleichen Werte, die Sie für die Entwicklungsorganisation in Erstellen eines Anwendungsbenutzers verwenden. Eine Ausnahme ist, dass Sie den Schritt für die Zustimmung vorher abgeschlossen haben müssen. Wenn Sie den Benutzer speichern, werden die Werte Anwendung-ID-URI und Azure AD-Objekt-ID festgelegt. Es ist nicht möglich den Benutzer zu speichern, wenn Sie nicht zuerst zugestimmt haben.
Ordnen Sie dann den Anwendungsbenutzer mit der benutzerdefinierten Sicherheitsrolle zu, die Sie im vorherigen Schritt erstellt haben.
Testen der Abonnentenverbindung
Wiederholen Sie die Schritte in Debuggen der App. Nutzen Sie jedoch die Anmeldeinformationen eines Benutzers aus dem anderen Dynamics 365-Mandaten.
Siehe auch
Verwenden Sie mehrinstanzenfähige Server-zu-Server-Authentifizierung
Verwenden Sie Einzel-Mandanten-Server-zu-Server-Authentifizierung
Erstellen von Webanwendungen mit Server-to-Server-Authentifizierung (S2S)
Verbinden mit Microsoft Dynamics 365
Microsoft Dynamics 365
© 2017 Microsoft. Alle Rechte vorbehalten. Copyright