Share via


Procedura dettagliata: autenticazione tra server multi-tenant

 

Data di pubblicazione: gennaio 2017

Si applica a: Dynamics 365 (online)

Questa procedura dettagliata descriverà i passaggi per la creazione di un'applicazione Web multi-tenant in grado di connettersi a un tenant Aggiornamento di dicembre 2016 per Microsoft Dynamics 365 (online) tramite il modello dell'applicazione Web MVC di Microsoft Visual Studio 2015.

Requisiti

  • Visual Studio 2015 con gli strumenti di sviluppo Web installati

  • Un tenant Aggiornamento di dicembre 2016 per Microsoft Dynamics 365 (online) associato al tenant Azure Active Directory (Azure AD).

  • Un secondo tenant Aggiornamento di dicembre 2016 per Microsoft Dynamics 365 (online) associato a un altro tenant Azure AD. Questo tenant rappresenta un sottoscrittore dell'applicazione. Questa può essere una sottoscrizione Aggiornamento di dicembre 2016 per Microsoft Dynamics 365 (online) di valutazione.

Obiettivo di questa procedura dettagliata

Al termine di questa procedura dettagliata si avrà un'applicazione Web MVC che utilizzerà la WhoAmIRequest Class per recuperare i dati relativi all'utente che l'applicazione usa per connettersi al tenant Dynamics 365 (online).

Quando si esegue correttamente l'app vedrete un comando Accedi nell'angolo superiore destro.

The sign in command in the app

Fai clic sul comando Accedi per essere reindirizzato ad Azure AD per immettere le tue credenziali.

Dopo aver eseguito l'accesso, vedrete un comando WhoAmI.

The WhoAmI command

Fare clic su WhoAmI per visualizzare quanto segue:

Results of a WhoAmI request

Quando si esegue la query sul tenant Dynamics 365 vedrete che i risultati restituiti dal messaggio WhoAmI fanno riferimento a uno specifico account utente dell'applicazione configurato per l'utilizzo nell'applicazione Web anziché l'account utente in uso.

Verificare il tenant Azure AD

Prima di iniziare, connettersi a Interfaccia di amministrazione di Office 365https://portal.office.com e nell'elenco a discesa Interfacce di amministrazione verificare che siano presenti sia Dynamics 365 che Azure AD.

Admin Centers with Azure Active Directory and Dynamics 365

Se la sottoscrizione ad Azure AD non è associata a una sottoscrizione a Dynamics 365, non sarà possibile assegnare privilegi all'applicazione per l'accesso ai dati Dynamics 365.

Se l'opzione non viene visualizzata, vedere la pagina relativa alla registrazione della sottoscrizione gratuita ad Azure Active Directory per informazioni su come registrare per ottenere la sottoscrizione ad Azure AD.

Se si dispone già di una sottoscrizione ad Azure ma non associata all'account Microsoft Office 365, vedere la pagina relativa all'associazione del proprio account di Office 365 ad Azure AD per creare e gestire le app.

Creare un'applicazione Web MVC

Tramite Visual Studio 2015, è possibile creare una nuova applicazione Web MVC e registrarla con il tenant Azure AD.

  1. Aprire Visual Studio 2015.

  2. Verificare che il Account Microsoft con cui si è effettuato l'accesso sia lo stesso con accesso al tenant Azure AD che si desidera utilizzare per registrare la tua applicazione.

  3. Fare su Nuovo progetto e selezionare .NET Framework 4.6.1 e il modello Applicazione Web ASP.NET.

    Fare clic su OK e nella finestra di dialogo Nuovo progetto ASP.NET selezionare MVC.

  4. Fare clic sul pulsante Modifica autenticazione e nella finestra di dialogo selezionare Account aziendale o dell'istituto di istruzione.

  5. Nell'elenco a discesa, selezionare Cloud - Più organizzazioni.

    ASP.NET MVC Change Authentication Dialog

  6. Fare clic su OK e completare l'inizializzazione del progetto.

    Nota

    Creare un progetto Visual Studio in questo modo registrerà l'applicazione con il tenant Azure AD e aggiugerà le chiavi seguenti a Web.Config appSettings:

    <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=" /> 
    

Registare l'applicazione in Azure AD

Se si è seguita la procedura in Creare un'applicazione Web MVC, si dovrebbe trovare che il progetto di applicazione Web creato in Visual Studio è già registrato nelle applicazioni Azure AD. Ma è presente un ulteriore passaggio che è necessario eseguire all'interno del portale di Azure AD.

  1. Passare a https://portal.azure.com e selezionare Azure Active Directory.

  2. Fare clic su Registrazioni per l'app e cercare l'applicazione creata utilizzando Visual Studio. Nell'area Generale, verificare le proprietà:

    Application registration data in Azure Active Directory

  3. Verificare che la proprietà ID applicazione corrisponda al valore ClientId aggiunto in Web.Config appSettings.

  4. Il valore URL pagina iniziale dovrebbe essere uguale alla proprietà SSL URL nel progetto Visual Studio e deve indirizzare a un URL localhost, ovvero https://localhost:44392/.

    Nota

    È necessario modificare questo in seguito quando si pubblica l'applicazione. Ma è necessario avere questo impostato sul valore localhost corretto per eseguire il debug.

  5. È necessario assegnare all'applicazione i privilegi per accedere ai dati Dynamics 365. Fare clic su Autorizzazioni necessarie nell'area Accesso all'API. Verrà visualizzato che già dispone delle autorizzazioni per Microsoft Azure Active Directory.

  6. Fare clic su Aggiungi, quindi su Selezionare un'API. Nell'elenco, selezionare Dynamics 365 e fare clic sul pulsante Seleziona.

  7. In Selezionare le autorizzazioni, selezionare Accedi a Dynamics 365 come utente dell'organizzazione. Quindi, fare clic sul pulsante Seleziona.

  8. Fare clic su Fine per aggiungere queste autorizzazioni. Al termine verranno visualizzate le autorizzazioni applicate:

    Dynamics 365 permissions applied to application in Azure Active Directory

  9. Nell'area Accesso all'API, verificare che un valore Chiave è stato aggiunto. Il valore Chiave non è visibile nel portale di Azure dopo l'applicazione è stata creata, ma questo valore è stato aggiunto a Web.Config appSettings come ClientSecret.

Creare un utente dell'applicazione

Utilizzando la procedura in a77637f4-420a-4686-9084-d0288d9154af#bkmk_ManuallyCreateUser, creare un utente dell'applicazione con il valore ID applicazione dalla registrazione dell'applicazione che corrisponde al valore ClientId in Web.Config.

Aggiungere assembly

Aggiungere i seguenti pacchetti NuGet al progetto

Pacchetto

Versione

Microsoft.CrmSdk.CoreAssemblies

Ultima versione

Microsoft.IdentityModel.Clients.ActiveDirectory

2.22.302111727

Microsoft.IdentityModel.Tokens

5.0.0

Microsoft.Azure.ActiveDirectory.GraphClient

2.1.0

Nota

Non aggiornare gli assembly Microsoft.IdentityModel.Clients.ActiveDirectory all'ultima versione. La versione 3.x di tali assembly ha modificato un'interfaccia da cui dipende Microsoft.CrmSdk.CoreAssemblies.

Per informazioni sulla gestione dei pacchetti NuGet, vedere NuGet Documentation: Managing NuGet Packages Using the UI

Applicare le modifiche di codice al modello MVC

Le modifiche seguenti di codice forniranno le funzionalità di base per l'utilizzo del messaggio WhoAmIDynamics 365 e verificare che l'identità dell'account utente dell'applicazione è in uso dall'applicazione.

Web.config

Aggiungere le chiavi seguenti a appSettings.

<add key="ida:OrganizationHostName" value="https://{0}.crm.dynamics.com" /> 

La stringa ida:OrganizationHostName avrà il nome dell'organizzazione Dynamics 365 online del sottoscrittore aggiunto al segnaposto in modo che il servizio corretto sia accessibile.

<add key="owin:appStartup" value="<your app namespace>.Startup" />

La stringa owin:appStartup assicura che il middleware OWIN utilizzi la classe Startup nel progetto. In caso contrario verrà visualizzato l'errore seguente:

- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.

Ulteriori informazioni: ASP.NET: OWIN Startup Class Detection

Controllers/HomeController.cs

Aggiungi l'elemento Decorator AllowAnonymous all'azione Index. Ciò consente l'accesso alla pagina predefinita senza autenticazione.

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();
        }
    }
}

Nota

Nell'applicazione o servizio Web, non è previsto che sia consentito l'accesso anonimo. L'accesso anonimo è utilizzato qui per semplicità. Il controllo di accesso all'applicazione non è incluso nell'ambito di questa procedura dettagliata.

Views/Shared/_Layout.cshtml

Per visualizzare il collegamento del comando WhoAmI per gli utenti autenticati, è necessario modificare questo file.

Individuare l'elemento div con la classe navbar-collapse collapse e modificarlo per includere codice seguente:

<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

Le modifiche seguenti invocheranno il framework di consenso quando un nuovo tenant accede all'applicazione:

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);
                  }
        }
       });

  }
 }

Aggiungere Controllers/CrmSdkController

Aggiungere il seguente CrmSdkController.cs alla cartella Controllers. Questo codice eseguirà il messaggio WhoAmI.

  1. Fare clic con il pulsante destro del mouse sulla cartella Controllers e selezionare Aggiungi > Controller

  2. Nella finestra di dialogo Aggiungi scaffolding selezionare Controller MVC5 - Vuoto

  3. Fare clic su Aggiungi

  4. Incollare il codice seguente sostituendo <Your app namespace> con lo spazio dei nomi dell'applicazione.

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

Aggiungere una nuova visualizzazione denominata Index.

  1. Fare clic con il pulsante destro del mouse sulla cartella CrmSdk e selezionare Aggiungi > Visualizzazione

  2. Nella finestra di dialogo Aggiungi visualizzazione, impostare i valori seguenti:

    MVC Add View Dialog

  3. Fare clic su Aggiungi

  4. Sostituire il codice generati con quanto segue:

    @model string
    @{
     ViewBag.Title = "SDK Connect";
    }
    
    
    <h2>@ViewBag.Title.</h2>
    
    <p>Connected and executed sdk command WhoAmI.</p>
    
    <p>Value: @Model</p>
    

Eseguire il debug dell'app

Quando si preme F5 per eseguire il debug dell'applicazione può venire visualizzato l'errore che il certificato che accede a localhost utilizzando SSL non è attendibile. Di seguito sono riportati collegamenti per risolvere questo problema con Visual Studio e IIS Express:

Nota

Per questo passaggio, è sufficiente utilizzare il Account Microsoft associato al tenant Azure AD e il tenant Dynamics 365 associato. Questo non dimostra uno scenario multi-tenant. Faremo questo nel passaggio successivo. Questo passaggio è solo per verificare che il codice funzioni prima di introdurre la complessità aggiuntiva di verificare l'effettiva funzionalità multi-tenant.

Fare riferimento ai passaggi descritti in Obiettivo di questa procedura dettagliata per verificare l'applicazione.

A questo punto è possibile verificare che l'account utente dell'applicazione sia stato utilizzato. Un modo semplice per controllare questo è mediante l'API Web di Dynamics 365. Digitare l'URL seguente in una scheda o in una finestra separata, sostituendo il valore UserId dell'applicazione.

[Organization URI]/api/data/v8.2/systemusers(<UserId value>)?$select=fullname

La risposta JSON dovrebbe essere simile al seguente. Si noti che il valore fullname sarà quello dell'utente dell'applicazione creato nel passaggio Creare un utente dell'applicazione, anziché dell'utente Dynamics 365 utilizzato per eseguire l'accesso nell'applicazione.

    {
        "@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"
    }

Configurare il sottoscrittore di prova

Dopo aver verificato che l'applicazione funziona, è il momento di verificare la connettività a un tenant Dynamics 365 (online) diverso. Con un'organizzazione Dynamics 365 (online) diversa è necessario eseguire la procedura seguente.

Concedere il consenso dal tenant di sottoscrizione

Per concedere il consenso, eseguire la procedura seguente collegati come amministratore di Azure AD:

  1. Durante il debug dell'applicazione, aprire una finestra InPrivate o in incognito separata.

  2. Nel campo di indirizzo della finestra digitare l'URL dell'app, cioè https://localhost:44392/

  3. Fare clic sul pulsante Accedi e verrà richiesto di concedere il consenso.

    Azure Active Directory consent form

Dopo aver concesso il consenso ritornerete all'app, ma non sarà possibile utilizzarla ancora. Se si fa clic su WhoAmI in questa fase è prevedibile visualizzare la seguente eccezione:

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.

Concedendo il consenso, l'applicazione dal tenant di Azure AD verrà aggiunta alle applicazioni nel tenant di Active Directory del sottoscrittore.

Creare un ruolo di sicurezza personalizzato nel tenant del sottoscrittore

L'utente dell'applicazione che sarà necessario creare deve essere associato a un ruolo di sicurezza personalizzato che ne definisce i privilegi. Per questo passaggio di prova manuale, è prima necessario creare manualmente un ruolo di sicurezza personalizzato.Ulteriori informazioni:TechNet: Per creare o modificare un ruolo di sicurezza

Nota

L'utente dell'applicazione non può essere associato a uno dei ruoli di sicurezza Dynamics 365 predefiniti. È necessario creare un ruolo di sicurezza personalizzato da associare all'utente dell'applicazione.

Creare un utente dell'applicazione sottoscrittore

Ai fini di questa procedura dettagliata, viene creato manualmente l'utente dell'applicazione per verificare la connettività da un tenant diverso. Quando si distribuisce ai sottoscrittori effettivi, si vorrà automatizzare il processo.Ulteriori informazioni:a77637f4-420a-4686-9084-d0288d9154af#bkmk_PrepareMethodToDeployAppUser

Creare manualmente l'utente dell'applicazione utilizzando gli stessi valori utilizzati per l'organizzazione di sviluppo in Creare un utente dell'applicazione. L'eccezione è che è necessario avere prima completato il passaggio per concedere il consenso. Quando si salva l'utente, i valori URI dell'ID applicazione e ID oggetto di Azure AD vengono impostati. Non sarà possibile salvare l'utente se non si dispone del consenso preventivo.

Infine, associare l'utente dell'applicazione con il ruolo di sicurezza personalizzato aggiunto nel passaggio precedente.

Verifica la connessione del sottoscrittore

Ripetere i passaggi Eseguire il debug dell'app tranne l'uso delle credenziali per un utente dall'altro tenant Dynamics 365.

Vedere anche

Utilizzare l'autenticazione tra server multi-tenant
Utilizzare l'autenticazione tra server single-tenant
Compilare applicazioni Web utilizzando l'autenticazione tra server (S2S)
Eseguire la connessione a Microsoft Dynamics 365

Microsoft Dynamics 365

© 2017 Microsoft. Tutti i diritti sono riservati. Copyright