In dieser Anleitung werden Sie eine vertrauliche Clientanwendung von Azure Active Directory Authentifizierungsbibliothek für .NET (ADAL.NET) zu Microsoft Authentication Library (MSAL) für .NET (MSAL.NET) migrieren. Vertrauliche Clientanwendungen umfassen Web-Apps, Web-APIs und Daemon-Anwendungen, die einen anderen Dienst in ihrem eigenen Auftrag aufrufen. Weitere Informationen zu vertraulichen Apps finden Sie unter Authentifizierungsflüsse und Anwendungsszenarien. Wenn Ihre App auf ASP.NET Core basiert, lesen Sie Microsoft. Identity.Web.
Für App-Registrierungen:
- Sie müssen keine neue App-Registrierung erstellen. (Sie behalten dieselbe Client-ID bei.)
- Sie müssen die Vorautorisierungen nicht ändern (administratorzustimmende API-Berechtigungen).
Schritte bei der Migration
Suchen Sie den Code, der ADAL.NET in Ihrer App verwendet.
Der Code, der ADAL in einer vertraulichen Client-App verwendet, instanziiert AuthenticationContext und ruft entweder AcquireTokenByAuthorizationCode oder eine Überschreibung von AcquireTokenAsync mit den folgenden Parametern auf:
- Eine
resourceId Zeichenfolge. Diese Variable ist der App-ID-URI der Web-API, die Sie aufrufen möchten.
- Eine Instanz von
IClientAssertionCertificate oder ClientAssertion. Diese Instanz stellt die Clientanmeldeinformationen für Ihre App bereit, um die Identität Ihrer App nachzuweisen.
Nachdem Sie festgestellt haben, dass Sie Apps haben, die ADAL.NET verwenden, installieren Sie das MSAL.NET-NuGet-Paket Microsoft.Identity.Client und aktualisieren Sie die Verweise auf Ihre Projektbibliotheken. Weitere Informationen finden Sie unter Installieren eines NuGet-Pakets. Um Tokencache-Serialisierer zu verwenden, installieren Sie Microsoft. Identity.Web.TokenCache.
Aktualisieren Sie den Code entsprechend dem vertraulichen Clientszenario. Einige Schritte sind üblich und gelten für alle vertraulichen Clientszenarien. Andere Schritte sind für jedes Szenario eindeutig.
Vertrauliche Clientszenarien:
Möglicherweise haben Sie einen Wrapper um ADAL.NET herum erstellt, um Zertifikate und Caching zu handhaben. In diesem Leitfaden wird derselbe Ansatz verwendet, um den Prozess der Migration von ADAL.NET zu MSAL.NET zu veranschaulichen. Dieser Code dient jedoch nur zu Demonstrationszwecken. Kopieren/einfügen Sie diese Wrapper nicht, oder integrieren Sie sie in Ihren Code wie sie sind.
Migrieren von Daemon-Apps
Daemonszenarien verwenden den OAuth2.0-Clientanmeldeinformationsfluss. Sie werden auch als Service-to-Service-Aufrufe bezeichnet. Ihre App erwirbt ein Token im eigenen Auftrag, nicht im Auftrag eines Benutzers.
Finden Sie heraus, ob Ihr Code Daemonszenarien verwendet
Der ADAL-Code für Ihre App verwendet Daemonszenarien, wenn er einen Aufruf AuthenticationContext.AcquireTokenAsync mit den folgenden Parametern enthält:
- Eine Ressource (App-ID-URI) als ersten Parameter
-
IClientAssertionCertificate oder ClientAssertion als zweiter Parameter
AuthenticationContext.AcquireTokenAsync hat keinen Parameter vom Typ UserAssertion. Wenn dies der Fall ist, handelt es sich bei Ihrer App um eine Web-API, und sie verwendet das Web-API-Szenario, in dem nachgeschaltete Web-APIs aufgerufen werden.
Aktualisieren des Codes von Daemon-Szenarien
Die folgenden Schritte zum Aktualisieren von Code gelten für alle vertraulichen Clientszenarien:
- Fügen Sie den MSAL.NET Namespace in Ihrem Quellcode hinzu:
using Microsoft.Identity.Client;.
- Verwenden Sie statt der Instanziierung von
AuthenticationContextConfidentialClientApplicationBuilder.Create, um IConfidentialClientApplication zu instanziieren.
- Anstelle der
resourceId Zeichenfolge verwendet MSAL.NET Bereiche. Da Anwendungen, die ADAL.NET verwenden, vorautorisiert sind, können Sie immer die folgenden Bereiche verwenden: new string[] { $"{resourceId}/.default" }
- Ersetzen Sie den Aufruf von
AuthenticationContext.AcquireTokenAsync durch einen Aufruf von IConfidentialClientApplication.AcquireTokenXXX, wobei XXX von Ihrem Szenario abhängt.
Ersetzen Sie in diesem Fall den Aufruf von AuthenticationContext.AcquireTokenAsync durch einen Aufruf von IConfidentialClientApplication.AcquireTokenClient.
Hier ist ein Vergleich von ADAL.NET und MSAL.NET Code für Daemonszenarien:
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;
}
}
Profitieren Sie von Token-Caching
Wenn Sie die Tokenzwischenspeicherung nicht einrichten, erfolgt eine Drosselung. Dies führt zu Fehlern. Es dauert auch viel weniger, um ein Token aus dem Cache (10-20 ms) abzurufen, als es von ESTS (500-30000 ms) stammt.
Wenn Sie einen verteilten Tokencache implementieren möchten, lesen Sie den Tokencache für eine Web-App oder Web-API (vertrauliche Clientanwendung).
Erfahren Sie mehr über das Daemon-Szenario und wie es mit MSAL.NET oder Microsoft implementiert wird. Identity.Web in neuen Anwendungen.
Migrieren einer Web-API, die nachgeschaltete Web-APIs aufruft
Web-APIs, die nachgeschaltete Web-APIs aufrufen, verwenden den OAuth 2.0-On-Behalf-Of (OBO)-Flow. Die Web-API verwendet das Zugriffstoken, das aus dem HTTP-Autorisierungsheader abgerufen wurde, und überprüft dieses Token. Dieses Token wird dann gegen ein Token ausgetauscht, um die downstream-Web-API aufzurufen. Dieses Token wird als UserAssertion Instanz in ADAL.NET und MSAL.NET verwendet.
Ermitteln, ob Ihr Code OBO verwendet
Der ADAL-Code für Ihre App verwendet OBO, wenn er einen Aufruf AuthenticationContext.AcquireTokenAsync mit den folgenden Parametern enthält:
- Eine Ressource (App-ID-URI) als ersten Parameter
-
IClientAssertionCertificate oder ClientAssertion als zweiter Parameter
- Ein Parameter vom Typ
UserAssertion
Aktualisieren des Codes mithilfe von OBO
Die folgenden Schritte zum Aktualisieren von Code gelten für alle vertraulichen Clientszenarien:
- Fügen Sie den MSAL.NET Namespace in Ihrem Quellcode hinzu:
using Microsoft.Identity.Client;.
- Verwenden Sie statt der Instanziierung von
AuthenticationContextConfidentialClientApplicationBuilder.Create, um IConfidentialClientApplication zu instanziieren.
- Anstelle der
resourceId Zeichenfolge verwendet MSAL.NET Bereiche. Da Anwendungen, die ADAL.NET verwenden, vorautorisiert sind, können Sie immer die folgenden Bereiche verwenden: new string[] { $"{resourceId}/.default" }
- Ersetzen Sie den Aufruf von
AuthenticationContext.AcquireTokenAsync durch einen Aufruf von IConfidentialClientApplication.AcquireTokenXXX, wobei XXX von Ihrem Szenario abhängt.
In diesem Fall ersetzen wir den Aufruf von AuthenticationContext.AcquireTokenAsync durch den Aufruf von IConfidentialClientApplication.AcquireTokenOnBehalfOf.
Hier ist ein Vergleich des Beispiel-OBO-Codes für ADAL.NET und MSAL.NET:
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/common";
X509Certificate2 certificate = LoadCertificate();
public async Task<AuthenticationResult> GetAuthenticationResult(
string resourceId,
string tokenUsedToCallTheWebApi)
{
var authContext = new AuthenticationContext(authority);
var clientAssertionCert = new ClientAssertionCertificate(
ClientId,
certificate);
var userAssertion = new UserAssertion(tokenUsedToCallTheWebApi);
var authResult = await authContext.AcquireTokenAsync(
resourceId,
clientAssertionCert,
userAssertion,
);
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/common";
X509Certificate2 certificate = LoadCertificate();
IConfidentialClientApplication app;
public async Task<AuthenticationResult> GetAuthenticationResult(
string resourceId,
string tokenUsedToCallTheWebApi)
{
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. For OBO, it is recommended to use a distributed cache like Redis.
app.AddInMemoryTokenCache(services =>
{
// Configure the memory cache options
services.Configure<MemoryCacheOptions>(options =>
{
options.SizeLimit = 1024 * 1024 * 1024; // in bytes (1 GB of memory)
});
}
var userAssertion = new UserAssertion(tokenUsedToCallTheWebApi);
var authResult = await app.AcquireTokenOnBehalfOf(
new string[] { $"{resourceId}/.default" },
userAssertion)
// .WithTenantId(specificTenant)
// See https://aka.ms/msal.net/withTenantId
.ExecuteAsync()
.ConfigureAwait(false);
return authResult;
}
}
Profitieren Sie von Token-Caching
Verwenden Sie für die Zwischenspeicherung von Tokens in OBOs einen verteilten Tokencache. Ausführliche Informationen finden Sie unter Tokencache für eine Web-App oder Web-API (vertrauliche Client-App).
app.UseInMemoryTokenCaches(); // or a distributed token cache.
Erfahren Sie mehr über Web-APIs, die nachgelagerte Web-APIs aufrufen, und wie diese in neuen Anwendungen mit MSAL.NET oder Microsoft.Identity.Web implementiert werden.
Migrieren einer Web-App, die Web-APIs aufruft
Wenn Ihre App ASP.NET Core verwendet, wird dringend empfohlen, auf Microsoft zu aktualisieren. Identity.Web, da alles für Sie verarbeitet wird. Eine kurze Präsentation finden Sie im Microsoft. Identity.Web-Ankündigung der allgemeinen Verfügbarkeit. Ausführliche Informationen zur Verwendung in einer Web-App finden Sie unter "Gründe für die Verwendung von Microsoft". Identity.Web in Web Apps?.
Web-Apps, die Benutzer anmelden und Web-APIs im Auftrag von Benutzern aufrufen, verwenden den OAuth2.0-Autorisierungscodefluss. Typischerweise:
- Die App meldet einen Benutzer an, indem sie den ersten Schritt des Autorisierungscodeflusses ausführt, indem sie den Autorisierungsendpunkt der Microsoft Identity Platform aufruft. Der Benutzer meldet sich an und führt bei Bedarf mehrstufige Authentifizierungen durch. Als Ergebnis dieses Vorgangs erhält die App den Autorisierungscode. Die Authentifizierungsbibliothek wird zu diesem Zeitpunkt nicht verwendet.
- Die App führt den zweiten Teil des Autorisierungscodeflusses aus. Er verwendet den Autorisierungscode, um ein Zugriffstoken, ein ID-Token und ein Aktualisierungstoken abzurufen. Ihre Anwendung muss den Wert
redirectUri bereitstellen, also die URI, unter der der Endpunkt der Microsoft Identity Platform die Sicherheitstoken bereitstellt. Nachdem die App diesen URI erhalten hat, ruft sie in der Regel AcquireTokenByAuthorizationCode für ADAL oder MSAL auf, um den Code gegen ein Token einzutauschen und ein Token abzurufen, das im Token-Cache gespeichert wird.
- Die App verwendet ADAL oder MSAL, um
AcquireTokenSilent aufzurufen und Token abzurufen, mit denen die erforderlichen Web-APIs aus den Controllern der Web-App aufgerufen werden.
Ermitteln, ob Ihr Code den Authentifizierungscodefluss verwendet
Der ADAL-Code für Ihre App verwendet den Autorisierungscodefluss, wenn er einen Aufruf von AuthenticationContext.AcquireTokenByAuthorizationCodeAsync enthält.
Aktualisieren Sie den Code mithilfe des Autorisierungscode-Flows.
Die folgenden Schritte zum Aktualisieren von Code gelten für alle vertraulichen Clientszenarien:
- Fügen Sie den MSAL.NET Namespace in Ihrem Quellcode hinzu:
using Microsoft.Identity.Client;.
- Verwenden Sie statt der Instanziierung von
AuthenticationContextConfidentialClientApplicationBuilder.Create, um IConfidentialClientApplication zu instanziieren.
- Anstelle der
resourceId Zeichenfolge verwendet MSAL.NET Bereiche. Da Anwendungen, die ADAL.NET verwenden, vorautorisiert sind, können Sie immer die folgenden Bereiche verwenden: new string[] { $"{resourceId}/.default" }
- Ersetzen Sie den Aufruf von
AuthenticationContext.AcquireTokenAsync durch einen Aufruf von IConfidentialClientApplication.AcquireTokenXXX, wobei XXX von Ihrem Szenario abhängt.
Ersetzen Sie in diesem Fall den Aufruf von AuthenticationContext.AcquireTokenAsync durch einen Aufruf von IConfidentialClientApplication.AcquireTokenByAuthorizationCode.
Hier ist ein Vergleich der Beispielautorisierungscodeflüsse für ADAL.NET und MSAL.NET:
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/common";
private Uri redirectUri = new Uri("host/login_oidc");
X509Certificate2 certificate = LoadCertificate();
public async Task<AuthenticationResult> GetAuthenticationResult(
string resourceId,
string authorizationCode)
{
var ac = new AuthenticationContext(authority);
var clientAssertionCert = new ClientAssertionCertificate(
ClientId,
certificate);
var authResult = await ac.AcquireTokenByAuthorizationCodeAsync(
authorizationCode,
redirectUri,
clientAssertionCert,
resourceId,
);
return authResult;
}
}
using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using System;
using System.Security.Claims;
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}";
private Uri redirectUri = new Uri("host/login_oidc");
X509Certificate2 certificate = LoadCertificate();
public IConfidentialClientApplication CreateApplication()
{
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithCertificate(certificate)
.WithAuthority(authority)
.WithRedirectUri(redirectUri.ToString())
.WithLegacyCacheCompatibility(false)
.Build();
// Add a token cache. For details about other serialization
// see https://aka.ms/msal-net-cca-token-cache-serialization
app.AddInMemoryTokenCache();
return app;
}
// Called from 'code received event'.
public async Task<AuthenticationResult> GetAuthenticationResult(
string resourceId,
string authorizationCode)
{
IConfidentialClientApplication app = CreateApplication();
var authResult = await app.AcquireTokenByAuthorizationCode(
new[] { $"{resourceId}/.default" },
authorizationCode)
.ExecuteAsync()
.ConfigureAwait(false);
return authResult;
}
}
Durch Aufrufen AcquireTokenByAuthorizationCode wird dem Tokencache ein Token hinzugefügt, wenn der Autorisierungscode empfangen wird. Verwenden Sie AcquireTokenSilent in Ihren Controllern, um zusätzliche Token für andere Ressourcen oder Mandanten abzurufen.
public partial class AuthWrapper
{
// Called from controllers
public async Task<AuthenticationResult> GetAuthenticationResult(
string resourceId2,
string authority)
{
IConfidentialClientApplication app = CreateApplication();
AuthenticationResult authResult;
var scopes = new[] { $"{resourceId2}/.default" };
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());
try
{
// try to get an already cached token
authResult = await app.AcquireTokenSilent(
scopes,
account)
// .WithTenantId(specificTenantId)
// See https://aka.ms/msal.net/withTenantId
.ExecuteAsync().ConfigureAwait(false);
}
catch (MsalUiRequiredException)
{
// The controller will need to challenge the user
// including asking for claims={ex.Claims}
throw;
}
return authResult;
}
}
Profitieren Sie vom Token-Caching
Da Ihre Web-App AcquireTokenByAuthorizationCode verwendet, muss sie zum Zwischenspeichern von Token einen verteilten Token-Cache verwenden. Ausführliche Informationen finden Sie unter Tokencache für eine Web-App oder Web-API.
app.UseInMemoryTokenCaches(); // or a distributed token cache.
Umgang mit MsalUiRequiredException
Wenn Ihr Controller versucht, im Hintergrund ein Token für verschiedene Geltungsbereiche/Ressourcen abzurufen, löst MSAL.NET möglicherweise erwartungsgemäß eine MsalUiRequiredException aus, wenn sich der Benutzer neu anmelden muss oder wenn der Zugriff auf die Ressource zusätzliche Claims erfordert (aufgrund einer Conditional-Access-Richtlinie). Ausführliche Informationen zur Entschärfung finden Sie unter Behandeln von Fehlern und Ausnahmen in MSAL.NET.
Erfahren Sie mehr über Web-Apps, die Web-APIs aufrufen und wie sie mit MSAL.NET oder Microsoft implementiert werden. Identity.Web in neuen Anwendungen.
MSAL-Vorteile
Zu den wichtigsten Vorteilen von MSAL.NET für Ihre App gehören:
Resilienz. MSAL.NET trägt auf folgende Weise zur Widerstandsfähigkeit Ihrer App bei:
- Vorteile von Microsoft Entra ID Cached Credential Service (CCS). CCS dient als Backup für Microsoft Entra.
- Proaktive Erneuerung von Token, wenn die API, die Sie aufrufen, langlebige Token über fortlaufende Zugriffsüberprüfung ermöglicht.
Sicherheit. Sie können PoP-Token (Proof of Possession) erwerben, wenn die Web-API, die Sie aufrufen möchten, dies erfordert. Ausführliche Informationen finden Sie unter "Proof Of Possession"-Token in MSAL.NET
Leistung und Skalierbarkeit. Wenn Sie Ihren Cache nicht für ADAL.NET freigeben müssen, deaktivieren Sie beim Erstellen der vertraulichen Clientanwendung (.WithLegacyCacheCompatibility(false)) die Legacycache-Kompatibilität, um die Leistung erheblich zu steigern.
app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithCertificate(certificate)
.WithAuthority(authority)
.WithLegacyCacheCompatibility(false)
.Build();
Troubleshooting
MsalServiceException
Die folgenden Informationen zur Problembehandlung machen zwei Annahmen:
- Ihr ADAL.NET Code funktionierte.
- Sie haben zu MSAL migriert, indem Sie dieselbe Client-ID beibehalten.
Wenn Sie eine Ausnahme mit einer der folgenden Meldungen erhalten:
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.
Beheben Sie die Ausnahme mithilfe der folgenden Schritte:
- Vergewissern Sie sich, dass Sie die neueste Version von MSAL.NET verwenden.
- Vergewissern Sie sich, dass der Authority-Host, den Sie beim Erstellen der vertraulichen Client-App festgelegt haben, und der Authority-Host, den Sie mit ADAL verwendet haben, übereinstimmen. Ist es insbesondere die gleiche Cloud (Azure Government, Microsoft Azure betrieben von 21Vianet oder Azure Deutschland)?
MsalClientException
Geben Sie in Mehrinstanzen-Apps beim Erstellen der App eine gemeinsame Autorität an, die auf einen bestimmten Mandanten ausgerichtet werden soll, z. B. den Mandanten des Benutzers beim Aufrufen einer Web-API. Seit MSAL.NET 4.37.0 können Sie, wenn Sie beim Erstellen der App .WithAzureRegion angeben, die Autorität bei den Tokenanforderungen nicht mehr mit .WithAuthority angeben. Wenn Sie dies tun, erhalten Sie beim Aktualisieren aus früheren Versionen von MSAL.NET die folgende Fehlermeldung:
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."
Um dieses Problem zu beheben, ersetzen Sie im AcquireTokenXXX-Ausdruck .WithAuthority durch .WithTenantId. Geben Sie den Mandanten mithilfe einer GUID oder eines Domänennamens an.
Nächste Schritte
Weitere Informationen zu: