Migrer des applications clientes confidentielles d’ADAL.NET vers MSAL.NET

Dans ce guide pratique, vous allez migrer une application cliente confidentielle de Azure Active Directory bibliothèque d'authentification pour .NET (ADAL.NET) vers Microsoft Authentication Library pour .NET (MSAL.NET). Les applications clientes confidentielles incluent les applications web, les API web et les applications démon qui appellent un autre service pour leur propre compte. Pour plus d’informations sur les applications confidentielles, consultez les flux d’authentification et les scénarios d’application. Si votre application est basée sur ASP.NET Core, consultez Microsoft. Identity.Web.

Pour les inscriptions d’applications :

  • Vous n’avez pas besoin de créer un nouvel enregistrement d’application. (Vous conservez le même ID client.)
  • Vous n’avez pas besoin de modifier les préauthorisations (autorisations d’API consentées par l’administrateur).

Étapes de la migration

  1. Recherchez le code qui utilise ADAL.NET dans votre application.

    Le code qui utilise ADAL dans une application cliente confidentielle crée une instance de AuthenticationContext et appelle soit AcquireTokenByAuthorizationCode, soit l’une des surcharges de AcquireTokenAsync avec les paramètres suivants :

    • Chaîne resourceId. Cette variable est l’URI d’ID d’application de l’API web que vous souhaitez appeler.
    • Instance de IClientAssertionCertificate ou ClientAssertion. Cette instance fournit les informations d’identification du client pour votre application afin de prouver l’identité de votre application.
  2. Une fois que vous avez identifié que vous avez des applications qui utilisent ADAL.NET, installez le package NuGet MSAL.NET Microsoft.Identity.Client et mettez à jour les références de bibliothèque de votre projet. Pour plus d’informations, consultez Installer un package NuGet. Pour utiliser des sérialiseurs de cache de jetons, installez Microsoft. Identity.Web.TokenCache.

  3. Mettez à jour le code en fonction du scénario client confidentiel. Certaines étapes sont courantes et s’appliquent à tous les scénarios clients confidentiels. Les autres étapes sont uniques à chaque scénario.

    Scénarios client confidentiels :

Vous avez peut-être fourni un wrapper autour de la bibliothèque ADAL.NET pour gérer les certificats et la mise en cache. Ce guide utilise la même approche pour illustrer le processus de migration d’ADAL.NET vers MSAL.NET. Toutefois, ce code est uniquement à des fins de démonstration. Ne copiez/collez pas ces wrappers ou ne les intégrez pas dans votre code tel qu’ils le sont.

Migrer des applications de démon

Les scénarios démon utilisent le flux d’informations d’identification du client OAuth2.0. On les appelle également appels entre services. Votre application acquiert un jeton pour son propre compte, et non pour le compte d’un utilisateur.

Déterminer si votre code utilise des scénarios démon

Le code ADAL de votre application utilise des scénarios de démon s’il contient un appel à AuthenticationContext.AcquireTokenAsync avec les paramètres suivants :

  • Ressource (URI d’ID d’application) en tant que premier paramètre
  • IClientAssertionCertificate ou ClientAssertion en tant que deuxième paramètre

AuthenticationContext.AcquireTokenAsync n’a pas de paramètre de type UserAssertion. Si c’est le cas, votre application est une API web et relève du scénario d’API web appelant des API web en aval.

Mettre à jour le code des scénarios de démon

Les étapes suivantes pour mettre à jour le code s’appliquent à tous les scénarios clients confidentiels :

  1. Ajoutez l’espace de noms MSAL.NET dans votre code source : using Microsoft.Identity.Client;.
  2. Au lieu d’instancier AuthenticationContext, utilisez ConfidentialClientApplicationBuilder.Create pour instancier IConfidentialClientApplication.
  3. Au lieu de la resourceId chaîne, MSAL.NET utilise des étendues. Étant donné que les applications qui utilisent ADAL.NET sont pré-autorisées, vous pouvez toujours utiliser les étendues suivantes : new string[] { $"{resourceId}/.default" }.
  4. Remplacez l’appel à AuthenticationContext.AcquireTokenAsync par un appel à IConfidentialClientApplication.AcquireTokenXXX, où XXX dépend de votre scénario.

Dans ce cas, remplacez l’appel à AuthenticationContext.AcquireTokenAsync par un appel à IConfidentialClientApplication.AcquireTokenClient.

Voici une comparaison de la bibliothèque ADAL.NET et du code MSAL.NET pour les scénarios de démon :

ADAL

MSAL

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public partial class AuthWrapper
{
const string ClientId = "Guid (AppID)";
const string authority 
= "https://login.microsoftonline.com/{tenant}";
// App ID URI of web API to call
const string resourceId = "https://target-api.domain.com";
X509Certificate2 certificate = LoadCertificate();



public async Task<AuthenticationResult> GetAuthenticationResult()
{


var authContext = new AuthenticationContext(authority);
var clientAssertionCert = new ClientAssertionCertificate(
ClientId,
certificate);


var authResult = await authContext.AcquireTokenAsync(
resourceId,
clientAssertionCert,
);

return authResult;
}
}
using Microsoft.Identity.Client;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public partial class AuthWrapper
{
const string ClientId = "Guid (Application ID)";
const string authority 
= "https://login.microsoftonline.com/{tenant}";
// App ID URI of web API to call
const string resourceId = "https://target-api.domain.com";
X509Certificate2 certificate = LoadCertificate();

IConfidentialClientApplication app;

public async Task<AuthenticationResult> GetAuthenticationResult()
{

var app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithCertificate(certificate)
.WithAuthority(authority)
.Build();

// Setup token caching https://learn.microsoft.com/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=aspnet
// For example, for an in-memory cache with 1GB limit, use  
app.AddInMemoryTokenCache(services =>
{
// Configure the memory cache options
services.Configure<MemoryCacheOptions>(options =>
{
options.SizeLimit = 1024 * 1024 * 1024; // in bytes (1 GB of memory)
});
}

var authResult = await app.AcquireTokenForClient(
new [] { $"{resourceId}/.default" })
// .WithTenantId(specificTenant)
// See https://aka.ms/msal.net/withTenantId
.ExecuteAsync()
.ConfigureAwait(false);

return authResult;
}
}

Tirer parti de la mise en cache des jetons

Si vous ne configurez pas la mise en cache des jetons, l’émetteur de jeton vous limite, ce qui entraîne des erreurs. Il faut également beaucoup moins d’obtenir un jeton à partir du cache (10-20 ms) que celui d’ESTS (500-30000 ms).

Si vous souhaitez implémenter un cache de jetons distribué, consultez Cache de jetons pour une application web ou une API web (application cliente confidentielle).

En savoir plus sur le scénario démon et la façon dont il est implémenté avec MSAL.NET ou Microsoft. Identity.Web dans les nouvelles applications.

Avantages MSAL

Les principaux avantages de MSAL.NET pour votre application sont les suivants :

  • Résilience. MSAL.NET vous aide à rendre votre application résiliente grâce à :

    • Avantages du service d’informations d’identification mises en cache (CCS) de Microsoft Entra ID. Le CCS sert de solution de secours pour Microsoft Entra.
    • Renouvellement proactif des jetons si l’API que vous appelez active des jetons de longue durée via l’évaluation continue de l’accès.
  • Sécurité. Vous pouvez acquérir des jetons de preuve de possession (PoP) si l’API web que vous souhaitez appeler l’exige. Pour plus d’informations, consultez les jetons preuve de possession dans MSAL.NET

  • Performances et scalabilité. Si vous n'avez pas besoin de partager votre cache avec ADAL.NET, désactivez la compatibilité du cache hérité lorsque vous créez l'application cliente confidentielle (.WithLegacyCacheCompatibility(false)) pour augmenter considérablement les performances.

    app = ConfidentialClientApplicationBuilder.Create(ClientId)
            .WithCertificate(certificate)
            .WithAuthority(authority)
            .WithLegacyCacheCompatibility(false)
            .Build();
    

Troubleshooting

MsalServiceException

Les informations de résolution des problèmes suivantes font deux hypothèses :

  • Votre code ADAL.NET fonctionnait.
  • Vous avez migré vers MSAL en conservant le même ID client.

Si vous obtenez une exception avec l’un des messages suivants :

AADSTS700027: Client assertion contains an invalid signature. [Reason - The key was not found.]

AADSTS90002: Tenant 'aaaabbbb-0000-cccc-1111-dddd2222eeee' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.

Résolvez les problèmes liés à l’exception en procédant comme suit :

  1. Vérifiez que vous utilisez la dernière version de MSAL.NET.
  2. Vérifiez que l’hôte d’autorité que vous définissez lors de la génération de l’application cliente confidentielle et de l’hôte d’autorité que vous avez utilisé avec ADAL sont similaires. En particulier, le même cloud (Azure Government, Microsoft Azure géré par 21Vianet ou Azure Allemagne) ?

MsalClientException

Dans les applications multilocataires, spécifiez une autorité commune lors de la création de l’application pour cibler un locataire spécifique, par exemple, le locataire de l’utilisateur lors de l’appel d’une API web. Depuis MSAL.NET 4.37.0, lorsque vous spécifiez .WithAzureRegion au moment de la création de l’application, vous ne pouvez plus spécifier l’autorité à l’aide de .WithAuthority lors des demandes de jeton. Si vous le faites, vous obtenez l'erreur suivante lors de la mise à jour à partir des versions précédentes de MSAL.NET :

MsalClientException - "You configured WithAuthority at the request level, and also WithAzureRegion. This is not supported when the environment changes from application to request. Use WithTenantId at the request level instead."

Pour résoudre ce problème, remplacez .WithAuthority l’expression AcquireTokenXXX par .WithTenantId. Spécifiez le locataire à l’aide d’un GUID ou d’un nom de domaine.

Étapes suivantes

Pour en savoir plus :