Integreer MSAL.NET met Microsoft. Identity.Web in .NET Framework

In deze handleiding ziet u hoe u de token cache en certificaatpakketten van Microsoft.Identity.Web met MSAL.NET kunt gebruiken in .NET Framework, .NET Standard 2.0 en klassieke .NET-toepassingen (.NET 4.7.2+).

Inzicht in het overzicht

Beginnend met Microsoft. Identity.Web 1.17+ kunt u Microsoft gebruiken. Identity.Web utility-pakketten met MSAL.NET in niet-ASP.NET Core omgevingen.

Pakketvoordelen identificeren

Feature Vergoeding
Serialisatie van tokencache Herbruikbare cacheadapters voor in-memory, SQL Server, Redis, Cosmos DB, PostgreSQL
Helpers voor certificaten Vereenvoudigd laden van certificaten vanuit KeyVault-, bestandssysteem- of certificaatarchieven
Claims-extensies Hulpmethoden voor ClaimsPrincipal manipulatie
.NET Standard 2.0 Compatibel met .NET Framework 4.7.2+, .NET Core en .NET 5+
Minimale afhankelijkheden Gerichte pakketten zonder ASP.NET Core afhankelijkheden

Ondersteunde scenario's bekijken

De volgende scenario's worden ondersteund met de beoogde hulpprogrammapakketten.

  • .NET Framework Console Applications (daemon-scenario's)
  • Desktop-toepassingen (.NET Framework)
  • Worker Services (.NET Framework)
  • .NET Standard 2.0-bibliotheken (platformoverschrijdende compatibiliteit)
  • Non-web-MSAL.NET-toepassingen

Opmerking

Zie OWIN Integration voor ASP.NET MVC/Web-API-toepassingen.


Pakketten selecteren

Kies het pakket dat overeenkomt met uw scenario.

Kernpakketten voor MSAL.NET identificeren

Package Purpose Afhankelijkheden .NET doel
Microsoft. Identity.Web.TokenCache Tokencache-serializers, extensies voor ClaimsPrincipal Minimaal .NET Standard 2.0
Microsoft. Identity.Web.Certificate Hulpprogramma's voor het laden van certificaten Minimaal .NET Standard 2.0

Pakketten installeren

Gebruik een van de volgende methoden om de pakketten toe te voegen aan uw project.

Pakketbeheer Console:

# Token cache serialization
Install-Package Microsoft.Identity.Web.TokenCache

# Certificate management
Install-Package Microsoft.Identity.Web.Certificate

.NET CLI:

dotnet add package Microsoft.Identity.Web.TokenCache
dotnet add package Microsoft.Identity.Web.Certificate

Inzicht in basispakketbeperkingen

Het kernpakket Microsoft.Identity.Web bevat ASP.NET Core afhankelijkheden (Microsoft.AspNetCore.*), die:

  • Zijn niet compatibel met ASP.NET Framework
  • De pakketgrootte onnodig vergroten
  • Afhankelijkheidsconflicten maken

Doelpakketten gebruiken voor .NET Framework- en .NET Standard-scenario's.


Serialisatie van tokencache configureren

Begrijp tokencacheadapters

Microsoft. Identity.Web biedt tokencacheadapters die naadloos werken met de IConfidentialClientApplication van MSAL.NET.

Een vertrouwelijke client bouwen met tokencache

In het volgende voorbeeld wordt een vertrouwelijke clienttoepassing gemaakt en wordt gekoppeld aan een tokencache in het geheugen.

using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders;

public class MsalAppBuilder
{
    private static IConfidentialClientApplication _app;

    public static IConfidentialClientApplication BuildConfidentialClientApplication()
    {
        if (_app == null)
        {
            string clientId = ConfigurationManager.AppSettings["AzureAd:ClientId"];
            string clientSecret = ConfigurationManager.AppSettings["AzureAd:ClientSecret"];
            string tenantId = ConfigurationManager.AppSettings["AzureAd:TenantId"];

            // Create the confidential client application
            _app = ConfidentialClientApplicationBuilder.Create(clientId)
                .WithClientSecret(clientSecret)
                .WithTenantId(tenantId)
                .WithAuthority(AzureCloudInstance.AzurePublic, tenantId)
                .Build();

            // Add token cache serialization (choose one option below)
            _app.AddInMemoryTokenCache();
        }

        return _app;
    }
}

Opties voor tokencache kiezen

Selecteer de cacheprovider die het beste past bij uw implementatiescenario.

Tokencache in het geheugen configureren

In het volgende voorbeeld wordt een eenvoudige cache in het geheugen toegevoegd:

using Microsoft.Identity.Web.TokenCacheProviders;

_app.AddInMemoryTokenCache();

In-memory cache met groottelimieten (Microsoft. Identity.Web 1.20+):

using Microsoft.Extensions.Caching.Memory;

_app.AddInMemoryTokenCache(services =>
{
    // Configure memory cache options
    services.Configure<MemoryCacheOptions>(options =>
    {
        options.SizeLimit = 5000000;  // 5 MB limit
    });
});

Kenmerken:

  • Snelle toegang
  • Geen externe afhankelijkheden
  • Niet gedeeld tussen processen
  • Verloren bij opnieuw opstarten van de app

Gebruikssituatie: Enkele instantie console-applicaties, desktoptoepassingen


Gedistribueerde tokencache in het geheugen configureren

Gebruik de volgende code om een gedistribueerde cache in het geheugen toe te voegen voor omgevingen met meerdere exemplaren:

_app.AddDistributedTokenCaches(services =>
{
    // Requires: Microsoft.Extensions.Caching.Memory (NuGet)
    services.AddDistributedMemoryCache();
});

Kenmerken:

  • Gedeeld tussen app-instanties
  • Beter voor scenario's met gelijke taakverdeling
  • Vereist een extra NuGet-pakket
  • Nog steeds verloren bij opnieuw opstarten van de app

Use case: Services met meerdere exemplaren met acceptabele tokenherwerving


SQL Server tokencache configureren

Gebruik de volgende code om een permanente, gedistribueerde SQL Server-cache toe te voegen:

using Microsoft.Extensions.Caching.SqlServer;

_app.AddDistributedTokenCaches(services =>
{
    // Requires: Microsoft.Extensions.Caching.SqlServer (NuGet)
    services.AddDistributedSqlServerCache(options =>
    {
        options.ConnectionString = ConfigurationManager.ConnectionStrings["TokenCache"].ConnectionString;
        options.SchemaName = "dbo";
        options.TableName = "TokenCache";

        // IMPORTANT: Set expiration above token lifetime
        // Access tokens typically expire after 1 hour
        options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
    });
});

Voer de volgende SQL uit om de vereiste cachetabel te maken:

-- Create the cache table
CREATE TABLE [dbo].[TokenCache] (
    [Id] NVARCHAR(449) NOT NULL,
    [Value] VARBINARY(MAX) NOT NULL,
    [ExpiresAtTime] DATETIMEOFFSET NOT NULL,
    [SlidingExpirationInSeconds] BIGINT NULL,
    [AbsoluteExpiration] DATETIMEOFFSET NULL,
    PRIMARY KEY ([Id])
);

-- Create index for performance
CREATE INDEX [Index_ExpiresAtTime] ON [dbo].[TokenCache] ([ExpiresAtTime]);

Kenmerken:

  • Permanent bij opnieuw opstarten
  • Gedeeld over meerdere instanties
  • Betrouwbaar en schaalbaar
  • Vereist SQL Server-installatie

Use case: Productie daemon-services, geplande taken, werkrollen met meerdere exemplaren


Redis-tokencache configureren

Gebruik de volgende code om een gedistribueerde Redis-cache met hoge prestaties toe te voegen:

using StackExchange.Redis;
using Microsoft.Extensions.Caching.StackExchangeRedis;

_app.AddDistributedTokenCaches(services =>
{
    // Requires: Microsoft.Extensions.Caching.StackExchangeRedis (NuGet)
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = ConfigurationManager.AppSettings["Redis:ConnectionString"];
        options.InstanceName = "TokenCache_";
    });
});

In het volgende voorbeeld ziet u een Redis-configuratie die gereed is voor productie:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = ConfigurationManager.AppSettings["Redis:ConnectionString"];
    options.InstanceName = "MyDaemonApp_";

    // Optional: Configure Redis options
    options.ConfigurationOptions = new ConfigurationOptions
    {
        AbortOnConnectFail = false,
        ConnectTimeout = 5000,
        SyncTimeout = 5000
    };
});

Kenmerken:

  • Zeer snel
  • Gedeeld tussen instanties
  • Persistent (met Redis-persistentie ingeschakeld)
  • Vereist een Redis-server

Use case: Daemon-apps met grote volumes, gedistribueerde systemen, microservices


Cosmos DB-tokencache configureren

Gebruik de volgende code om een wereldwijd gedistribueerde Cosmos DB-cache toe te voegen:

using Microsoft.Extensions.Caching.Cosmos;

_app.AddDistributedTokenCaches(services =>
{
    // Requires: Microsoft.Extensions.Caching.Cosmos (preview)
    services.AddCosmosCache(options =>
    {
        options.ContainerName = "TokenCache";
        options.DatabaseName = "IdentityCache";
        options.ClientBuilder = new CosmosClientBuilder(
            ConfigurationManager.AppSettings["CosmosConnectionString"]);
        options.CreateIfNotExists = true;
    });
});

Kenmerken:

  • Wereldwijd gedistribueerd
  • Maximaal beschikbaar
  • Automatisch schalen
  • Hogere latentie dan Redis
  • Hogere kosten

Use case: Wereldwijde daemon-services, geografisch gedistribueerde toepassingen


PostgreSQL-tokencache configureren

Gebruik de volgende code om een gedistribueerde PostgreSQL-cache toe te voegen:

_app.AddDistributedTokenCaches(services =>
{
    // Requires: Microsoft.Extensions.Caching.Postgres (NuGet)
    services.AddDistributedPostgresCache(options =>
    {
        options.ConnectionString = ConfigurationManager.ConnectionStrings["PostgresCache"].ConnectionString;
        options.SchemaName = ConfigurationManager.AppSettings["PostgresCache:SchemaName"];
        options.TableName = ConfigurationManager.AppSettings["PostgresCache:TableName"];
        options.CreateIfNotExists = bool.Parse(
            ConfigurationManager.AppSettings["PostgresCache:CreateIfNotExists"] ?? "true");

        // Set expiration above token lifetime.
        // Access tokens typically expire after 1 hour.
        options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
    });
});

Kenmerken:

  • Permanent bij opnieuw opstarten
  • Gedeeld over meerdere instanties
  • Vertrouwde SQL-semantiek
  • Werkt met Azure Database for PostgreSQL
  • Vereist een PostgreSQL-server

Gebruiksvoorbeeld: Toepassingen maken al gebruik van PostgreSQL als primaire database of Azure gehoste services met behulp van Azure Database for PostgreSQL


Een volledige daemon-toepassing bouwen

In het volgende voorbeeld ziet u een volledige daemon-toepassing die tokens verkrijgt met behulp van clientreferenties en een SQL Server tokencache.

using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders;
using System;
using System.Threading.Tasks;

namespace DaemonApp
{
    class Program
    {
        private static IConfidentialClientApplication _app;

        static async Task Main(string[] args)
        {
            // Build confidential client with token cache
            _app = BuildConfidentialClient();

            // Acquire token for app-only access
            string[] scopes = new[] { "https://graph.microsoft.com/.default" };

            try
            {
                var result = await _app.AcquireTokenForClient(scopes)
                    .ExecuteAsync();

                Console.WriteLine($"Token acquired successfully!");
                Console.WriteLine($"Token source: {result.AuthenticationResultMetadata.TokenSource}");
                Console.WriteLine($"Expires on: {result.ExpiresOn}");

                // Use token to call API
                await CallProtectedApi(result.AccessToken);
            }
            catch (MsalServiceException ex)
            {
                Console.WriteLine($"Error acquiring token: {ex.ErrorCode}");
                Console.WriteLine($"CorrelationId: {ex.CorrelationId}");
            }
        }

        private static IConfidentialClientApplication BuildConfidentialClient()
        {
            var app = ConfidentialClientApplicationBuilder
                .Create(ConfigurationManager.AppSettings["ClientId"])
                .WithClientSecret(ConfigurationManager.AppSettings["ClientSecret"])
                .WithTenantId(ConfigurationManager.AppSettings["TenantId"])
                .Build();

            // Add SQL Server token cache for persistence
            app.AddDistributedTokenCaches(services =>
            {
                services.AddDistributedSqlServerCache(options =>
                {
                    options.ConnectionString = ConfigurationManager
                        .ConnectionStrings["TokenCache"].ConnectionString;
                    options.SchemaName = "dbo";
                    options.TableName = "TokenCache";
                    options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
                });
            });

            return app;
        }

        private static async Task CallProtectedApi(string accessToken)
        {
            // Your API call logic
        }
    }
}

Certificaten beheren

Inzicht in het laden van certificaten

Microsoft. Identity.Web vereenvoudigt het laden van certificaten uit verschillende bronnen voor clientreferentiestromen.

Certificaten laden met DefaultCertificateLoader

In het volgende voorbeeld ziet u hoe u een certificaat uit Azure Key Vault laadt en een vertrouwelijke clienttoepassing maakt.

using Microsoft.Identity.Web;
using Microsoft.Identity.Client;

public class CertificateHelper
{
    public static IConfidentialClientApplication CreateAppWithCertificate()
    {
        string clientId = ConfigurationManager.AppSettings["AzureAd:ClientId"];
        string tenantId = ConfigurationManager.AppSettings["AzureAd:TenantId"];

        // Define certificate source
        var certDescription = CertificateDescription.FromKeyVault(
            keyVaultUrl: "https://my-keyvault.vault.azure.net",
            keyVaultCertificateName: "MyCertificate"
        );

        // Load certificate
        ICertificateLoader certificateLoader = new DefaultCertificateLoader();
        certificateLoader.LoadIfNeeded(certDescription);

        // Create confidential client with certificate
        var app = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithCertificate(certDescription.Certificate)
            .WithTenantId(tenantId)
            .Build();

        // Add token cache
        app.AddInMemoryTokenCache();

        return app;
    }
}

Certificaatbronnen kiezen

Laden vanuit Azure Key Vault

Laad een certificaat dat is opgeslagen in Azure Key Vault door de kluis-URL en certificaatnaam op te geven.

var certDescription = CertificateDescription.FromKeyVault(
    keyVaultUrl: "https://my-keyvault.vault.azure.net",
    keyVaultCertificateName: "MyApplicationCert"
);

ICertificateLoader loader = new DefaultCertificateLoader();
loader.LoadIfNeeded(certDescription);

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithCertificate(certDescription.Certificate)
    .WithTenantId(tenantId)
    .Build();

Voorwaarden:

  • Beheerde identiteit of service-principal met toegang tot Key Vault
  • Azure.Identity NuGet-pakket
  • Key Vault-toestemmingen: Get voor certificaten

Verladen vanuit certificaatopslag

Laad een certificaat uit de Windows certificaatopslag met een onderscheidende naam.

var certDescription = CertificateDescription.FromStoreWithDistinguishedName(
    distinguishedName: "CN=MyApp.contoso.com",
    storeName: StoreName.My,
    storeLocation: StoreLocation.CurrentUser
);

ICertificateLoader loader = new DefaultCertificateLoader();
loader.LoadIfNeeded(certDescription);

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithCertificate(certDescription.Certificate)
    .WithTenantId(tenantId)
    .Build();

U kunt ook een certificaat vinden via vingerafdruk:

var certDescription = CertificateDescription.FromStoreWithThumbprint(
    thumbprint: "ABCDEF1234567890ABCDEF1234567890ABCDEF12",
    storeName: StoreName.My,
    storeLocation: StoreLocation.LocalMachine
);

Laden vanuit bestandssysteem

Laad een certificaat uit een PFX-bestand op het lokale bestandssysteem.

var certDescription = CertificateDescription.FromPath(
    path: @"C:\Certificates\MyAppCert.pfx",
    password: ConfigurationManager.AppSettings["Certificate:Password"]
);

ICertificateLoader loader = new DefaultCertificateLoader();
loader.LoadIfNeeded(certDescription);

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithCertificate(certDescription.Certificate)
    .WithTenantId(tenantId)
    .Build();

Beveiligingsnotitie: Codeer nooit wachtwoorden. Veilige configuratie gebruiken.


Laden vanuit met Base64 gecodeerde tekenreeks

Laad een certificaat uit een met Base64 gecodeerde tekenreeks die is opgeslagen in de configuratie.

string base64Cert = ConfigurationManager.AppSettings["Certificate:Base64"];

var certDescription = CertificateDescription.FromBase64Encoded(
    base64EncodedValue: base64Cert,
    password: ConfigurationManager.AppSettings["Certificate:Password"]  // Optional
);

ICertificateLoader loader = new DefaultCertificateLoader();
loader.LoadIfNeeded(certDescription);

Certificaat laden vanuit App.config configureren

Definieer certificaatinstellingen in uw App.config-bestand en laad deze tijdens runtime.

App.config:

<appSettings>
  <add key="AzureAd:ClientId" value="your-client-id" />
  <add key="AzureAd:TenantId" value="your-tenant-id" />

  <!-- Option 1: KeyVault -->
  <add key="Certificate:SourceType" value="KeyVault" />
  <add key="Certificate:KeyVaultUrl" value="https://my-vault.vault.azure.net" />
  <add key="Certificate:KeyVaultCertificateName" value="MyCert" />

  <!-- Option 2: Store -->
  <!--
  <add key="Certificate:SourceType" value="StoreWithThumbprint" />
  <add key="Certificate:CertificateThumbprint" value="ABCD..." />
  <add key="Certificate:CertificateStorePath" value="CurrentUser/My" />
  -->
</appSettings>

<connectionStrings>
  <add name="TokenCache"
       connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TokenCache;Integrated Security=True;" />
</connectionStrings>

Gebruik de volgende helpermethode om het certificaat te laden op basis van de configuratie:

public static CertificateDescription GetCertificateFromConfig()
{
    string sourceType = ConfigurationManager.AppSettings["Certificate:SourceType"];

    return sourceType switch
    {
        "KeyVault" => CertificateDescription.FromKeyVault(
            ConfigurationManager.AppSettings["Certificate:KeyVaultUrl"],
            ConfigurationManager.AppSettings["Certificate:KeyVaultCertificateName"]
        ),

        "StoreWithThumbprint" => CertificateDescription.FromStoreWithThumbprint(
            ConfigurationManager.AppSettings["Certificate:CertificateThumbprint"],
            StoreName.My,
            StoreLocation.CurrentUser
        ),

        _ => throw new ConfigurationErrorsException("Invalid certificate source type")
    };
}

Voorbeeldtoepassingen verkennen

Bekijk deze voorbeelden om werkende implementaties te bekijken.

Officiële Microsoft voorbeelden bekijken

De volgende tabel bevat officiële voorbeelden die het laden van tokens in cache en het laden van certificaten demonstreren.

voorbeeld Platform Beschrijving
ConfidentialClientTokenCache Console (.NET Framework) Serialisatiepatronen voor tokencache
active-directory-dotnetcore-daemon-v2 Console (.NET Core) Certificaat laden vanuit Key Vault

Best practices volgen

Pas deze patronen toe om betrouwbare en veilige toepassingen te bouwen.

1. Gebruik het singleton-patroon voor IConfidentialClientApplication:

Maak één exemplaar en gebruik deze opnieuw in uw toepassing.

private static IConfidentialClientApplication _app;

public static IConfidentialClientApplication GetApp()
{
    if (_app == null)
    {
        _app = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret(clientSecret)
            .WithTenantId(tenantId)
            .Build();

        _app.AddDistributedTokenCaches(/* ... */);
    }

    return _app;
}

2. Stel de juiste verlooptijd van de tokencache in:

Configureer de verloopinstellingen zodanig dat deze langer zijn dan de levensduur van het token om onnodig opnieuw verkrijgen te voorkomen.

// Access tokens typically expire after 1 hour
// Set cache expiration ABOVE token lifetime
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);

3. Gebruik beveiligde certificaatopslag:

Sla certificaten op in Azure Key Vault of een correct beveiligd certificaatarchief.

// Azure Key Vault (production)
var cert = CertificateDescription.FromKeyVault(keyVaultUrl, certName);

// Certificate store with proper permissions
var cert = CertificateDescription.FromStoreWithThumbprint(
    thumbprint, StoreName.My, StoreLocation.LocalMachine);

4. De juiste foutafhandeling implementeren:

Onderschep MSAL-uitzonderingen en registreer de correlatie-id voor foutopsporing.

try
{
    var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
}
catch (MsalServiceException ex)
{
    logger.Error($"Token acquisition failed. CorrelationId: {ex.CorrelationId}, ErrorCode: {ex.ErrorCode}");
    throw;
}

5. Gebruik een gedistribueerde cache voor productie:

Een gedistribueerde cache deelt tokens tussen exemplaren en blijft behouden tijdens het opnieuw opstarten.

// Correct for daemon services
app.AddDistributedTokenCaches(services =>
{
    services.AddDistributedSqlServerCache(/* ... */);
});

Veelvoorkomende fouten voorkomen

1. Maak niet herhaaldelijk nieuwe IConfidentialClientApplication-exemplaren:

// Wrong - creates new instance every time
public void AcquireToken()
{
    var app = ConfidentialClientApplicationBuilder.Create(clientId).Build();
    // ...
}

// Correct - use singleton
private static readonly IConfidentialClientApplication _app = BuildApp();

2. Codeer geen geheimen:

// Wrong
.WithClientSecret("supersecretvalue123")

// Correct
.WithClientSecret(ConfigurationManager.AppSettings["AzureAd:ClientSecret"])

3. Gebruik geen cache in het geheugen voor services met meerdere exemplaren:

// Wrong for services with multiple instances
app.AddInMemoryTokenCache();

// Correct - use distributed cache
app.AddDistributedTokenCaches(services =>
{
    services.AddDistributedSqlServerCache(/* ... */);
});

4. Negeer certificaatvalidatie niet:

// Wrong - skips validation
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, errors) => true;

// Correct - validate certificates properly

Migreren vanuit ADAL.NET

Bekijk de belangrijkste verschillen en werk uw code bij om MSAL.NET te gebruiken met Microsoft. Identity.Web.

Belangrijke verschillen begrijpen

Aspect ADAL.NET (afgeschaft) MSAL.NET + Microsoft. Identity.Web
Scopes Bronnengebaseerd (https://graph.microsoft.com) Op bereik gebaseerd (https://graph.microsoft.com/.default)
Tokencache Handmatige serialisatie vereist Ingebouwde adapters via extensiemethoden
Certificates Handmatig X509Certificate2 laden DefaultCertificateLoader met meerdere bronnen
Autoriteit Vast bij de bouw Kan per aanvraag worden overschreven

Migratievoorbeelden vergelijken

ADAL.NET (oud):

AuthenticationContext authContext = new AuthenticationContext(authority);
ClientCredential credential = new ClientCredential(clientId, clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, credential);

MSAL.NET met Microsoft. Identity.Web (nieuw):

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithClientSecret(clientSecret)
    .WithTenantId(tenantId)
    .Build();

app.AddInMemoryTokenCache();  // Add token cache

string[] scopes = new[] { "https://graph.microsoft.com/.default" };
AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();

Gebruik deze resources voor meer informatie over gerelateerde scenario's.