Gruppen, Administratorrollen und App-Rollen in Microsoft Entra ID (ME-ID)

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

In diesem Artikel wird erläutert, wie Sie Blazor WebAssembly für die Verwendung von Microsoft Entra ID-Gruppen und -Rollen konfigurieren.

Microsoft Entra ID (ME-ID) bietet mehrere Autorisierungsansätze, die mit ASP.NET Core Identity kombiniert werden können:

  • Gruppen
    • Sicherheit
    • Microsoft 365
    • Verteilung
  • Rollen
    • ME-ID-Administratorrollen
    • App-Rollen

Der Leitfaden in diesem Artikel bezieht sich auf die in den folgenden Artikeln beschriebenen Bereitstellungsszenarios für Blazor WebAssembly-ME-ID:

Dieser Artikel enthält Anleitungen für Client- und Server-Apps:

  • CLIENT: eigenständige Blazor WebAssembly-Apps
  • SERVER: Server- oder API-Apps in ASP.NET Core Bei einer eigenständigen Blazor WebAssembly-App können Sie den Leitfaden SERVER in diesem Artikel ignorieren.
  • CLIENT: Eigenständige Blazor WebAssembly-Apps oder die Client -App einer gehosteten BlazorProjektmappe.
  • SERVER: ASP.NET Core-Server-API-/Web-API-Apps oder die Server-App einer gehosteten Blazor-Lösung. Bei einer eigenständigen Blazor WebAssembly-App können Sie den Leitfaden SERVER in diesem Artikel ignorieren.

Die Beispiele in diesem Artikel nutzen neue .NET/C#-Funktionen. Wenn Sie die Beispiele mit .NET 7 oder früher verwenden, sind geringfügige Änderungen erforderlich. Die Text- und Codebeispiele, die sich auf die Interaktion mit ME-ID und Microsoft Graph beziehen, sind jedoch für alle Versionen von ASP.NET Core identisch.

Voraussetzung

Im Leitfaden in diesem Artikel wird die Microsoft Graph-API gemäß dem Leitfaden zum Graph SDK unter Verwenden der Graph-API mit der Blazor WebAssembly von ASP.NET Core implementiert. Konfigurieren und testen Sie die App gemäß dem Implementierungsleitfaden für das Graph SDK, um sicherzustellen, dass die App Graph-API-Daten für ein Testbenutzerkonto abrufen kann. Lesen Sie außerdem die Informationen zu den Sicherheitskonzepten von Microsoft Graph, die Sie unter den Querlinks im Artikel zur Sicherheit der Graph-API finden.

Beim lokalem Testen mit dem Graph SDK empfehlen wir die Verwendung einer neuen privaten bzw. Inkognito-Browsersitzung für jeden Test, um zu verhindern, dass Tests durch vorhandene cookies beeinträchtigt werden. Weitere Informationen finden Sie unter Sichern einer eigenständigen ASP.NET Core-Blazor WebAssembly-App mit Microsoft Entra ID.

Bereiche

So lassen Sie Microsoft Graph-API-Aufrufe für Benutzerprofil-, Rollenzuweisungs- und Gruppenmitgliedschaftsdaten zu:

  • Eine CLIENT-App wird mit dem delegiertenUser.Read Bereich (https://graph.microsoft.com/User.Read) im Azure-Portal konfiguriert, da der Zugriff auf das Lesen von Benutzerdaten durch die Bereiche bestimmt wird, die einzelnen Benutzerinnen und Benutzern gewährt (delegiert) werden.
  • Eine SERVER-App wird mit dem AnwendungsGroupMember.Read.All-Bereich (https://graph.microsoft.com/GroupMember.Read.All) im Azure-Portal konfiguriert, da der Zugriff für die App für den Zugriff auf Informationen zur Gruppenmitgliedschaft gilt, nicht basierend auf der Autorisierung einzelner Benutzerinnen und Benutzer für den Zugriff auf Daten zu Gruppenmitgliedern.

Die oben genannten Bereiche sind zusätzlich zu den in ME-ID-Bereitstellungsszenarios benötigten Bereichen erforderlich, die in den oben aufgeführten Artikeln beschrieben werden (Eigenständig mit Microsoft-Konten oder Eigenständig mit ME-ID).

Die oben genannten Bereiche sind zusätzlich zu den in ME-ID-Bereitstellungsszenarien benötigten Bereichen erforderlich, die in den oben aufgeführten Themen beschrieben werden (Eigenständig mit Microsoft-Konten, Eigenständig mit ME-ID und Gehostet mit ME-ID).

Weitere Informationen finden Sie unter Übersicht über Berechtigungen und Zustimmung in der Microsoft-Identitätsplattform und Übersicht über Microsoft Graph-Berechtigungen.

Hinweis

Die Wörter „Berechtigung“ und „Bereich“ werden im Azure-Portal und in verschiedenen Dokumentationsmaterialien von Microsoft und externen Anbietern austauschbar verwendet. Im vorliegenden Artikel wird „Bereich“ durchgehend für die Berechtigungen verwendet, die einer App im Azure-Portal zugewiesen werden.

groupMembershipClaims-Attribut

Legen Sie im Azure-Portal im App-Manifest für CLIENT- und SERVER-Apps das groupMembershipClaims-Attribut auf All fest. Beim Wert All sendet ME-ID alle Sicherheitsgruppen, Verteilergruppen und Rollen des angemeldeten Benutzers im Anspruch bekannter IDs (wids):

  1. Öffnen Sie die Azure-Portal-Registrierung der App.
  2. Wählen Sie in der Randleiste Verwalten>Manifest aus.
  3. Suchen Sie das groupMembershipClaims-Attribut.
  4. Legen Sie den Wert auf All fest ("groupMembershipClaims": "All").
  5. Wählen Sie die Schaltfläche Speichern aus, wenn Sie Änderungen vorgenommen haben.

Benutzerdefiniertes Benutzerkonto

Weisen Sie Benutzer im Azure-Portal zu ME-ID-Sicherheitsgruppen und ME-ID-Administratorrollen zu.

Für die Beispiele in diesem Artikel gilt:

  • Es wird angenommen, dass einem Benutzer im ME-ID-Mandanten im Azure-Portal die ME-ID-Rolle Abrechnungsadministrator zugewiesen ist, damit dieser Benutzer für den Zugriff auf die Zugriffsserver-API-Daten autorisiert ist.
  • Verwenden Sie Autorisierungsrichtlinien, um den Zugriff innerhalb der CLIENT- und SERVER-Apps zu steuern.

Erweitern Sie RemoteUserAccount in der CLIENT-App, um Eigenschaften für Folgendes einzuschließen:

CustomUserAccount.cs:

using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

namespace BlazorSample;

public class CustomUserAccount : RemoteUserAccount
{
    [JsonPropertyName("roles")]
    public List<string>? Roles { get; set; }

    [JsonPropertyName("wids")]
    public List<string>? Wids { get; set; }

    [JsonPropertyName("oid")]
    public string? Oid { get; set; }
}

Fügen Sie einen Paketverweis zur CLIENT-App für Microsoft.Graph hinzu.

Hinweis

Einen Leitfaden zum Hinzufügen von Paketen zu .NET-Apps finden Sie in Installieren und Verwalten von Paketen unter Workflow der Nutzung von Paketen (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Fügen Sie die Hilfsklassen des Graph SDK und die Konfiguration im Leitfaden zum Graph SDK im Artikel Verwenden der Graph-API mit der Blazor WebAssembly von ASP.NET Core hinzu. Geben Sie wie in der Beispieldatei wwwroot/appsettings.json im Artikel gezeigt den User.Read-Bereich für das Zugriffstoken an.

Fügen Sie der CLIENT-App die folgende benutzerdefinierte Benutzerkontofactory hinzu. Die benutzerdefinierte Benutzerfactory wird verwendet, um Folgendes einzurichten:

  • App-Rollenansprüche (appRole) (beschrieben im Abschnitt App-Rollen)
  • ME-ID-Administratorrollenansprüche (directoryRole).
  • Beispiel für Benutzerprofildaten-Ansprüche für die Mobiltelefonnummer (mobilePhone) und den Bürostandort (officeLocation) des Benutzers
  • ME-ID-Gruppenansprüche (directoryGroup).
  • Ein ILogger (logger) für den Fall, dass Sie Informationen oder Fehler protokollieren möchten

CustomAccountFactory.cs:

Im folgenden Beispiel wird davon ausgegangen, dass die App-Einstellungsdatei des Projekts einen Eintrag für die Basis-URL enthält:

{
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com/{VERSION}",
    ...
  }
}

Im vorherigen Beispiel steht der Platzhalter {VERSION} für die Version der MS Graph-API (z. B. v1.0).

using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using Microsoft.Graph;
using Microsoft.Kiota.Abstractions.Authentication;

namespace BlazorSample;

public class CustomAccountFactory(IAccessTokenProviderAccessor accessor,
        IServiceProvider serviceProvider,
        ILogger<CustomAccountFactory> logger,
        IConfiguration config)
    : AccountClaimsPrincipalFactory<CustomUserAccount>(accessor)
{
    private readonly ILogger<CustomAccountFactory> logger = logger;
    private readonly IServiceProvider serviceProvider = serviceProvider;
    private readonly string? baseUrl = 
        config.GetSection("MicrosoftGraph")["BaseUrl"];

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        CustomUserAccount account,
        RemoteAuthenticationUserOptions options)
    {
        var initialUser = await base.CreateUserAsync(account, options);

        if (initialUser.Identity is not null &&
            initialUser.Identity.IsAuthenticated)
        {
            var userIdentity = initialUser.Identity as ClaimsIdentity;

            if (userIdentity is not null && !string.IsNullOrEmpty(baseUrl))
            {
                account?.Roles?.ForEach((role) =>
                {
                    userIdentity.AddClaim(new Claim("appRole", role));
                });

                account?.Wids?.ForEach((wid) =>
                {
                    userIdentity.AddClaim(new Claim("directoryRole", wid));
                });

                try
                {
                    var client = new GraphServiceClient(
                        new HttpClient(),
                        serviceProvider
                            .GetRequiredService<IAuthenticationProvider>(),
                        baseUrl);

                    var user = await client.Me.GetAsync();

                    if (user is not null)
                    {
                        userIdentity.AddClaim(new Claim("mobilephone",
                            user.MobilePhone ?? "(000) 000-0000"));
                        userIdentity.AddClaim(new Claim("officelocation",
                            user.OfficeLocation ?? "Not set"));
                    }

                    var requestMemberOf = client.Users[account?.Oid].MemberOf;
                    var memberships = await requestMemberOf.Request().GetAsync();

                    if (memberships is not null)
                    {
                        foreach (var entry in memberships)
                        {
                            if (entry.ODataType == "#microsoft.graph.group")
                            {
                                userIdentity.AddClaim(
                                    new Claim("directoryGroup", entry.Id));
                            }
                        }
                    }
                }
                catch (AccessTokenNotAvailableException exception)
                {
                    exception.Redirect();
                }
            }
        }

        return initialUser;
    }
}
using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using Microsoft.Graph;

namespace BlazorSample;

public class CustomAccountFactory(IAccessTokenProviderAccessor accessor,
        IServiceProvider serviceProvider,
        ILogger<CustomAccountFactory> logger)
    : AccountClaimsPrincipalFactory<CustomUserAccount>(accessor)
{
    private readonly ILogger<CustomAccountFactory> logger = logger;
    private readonly IServiceProvider serviceProvider = serviceProvider;

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        CustomUserAccount account,
        RemoteAuthenticationUserOptions options)
    {
        var initialUser = await base.CreateUserAsync(account, options);

        if (initialUser.Identity is not null &&
            initialUser.Identity.IsAuthenticated)
        {
            var userIdentity = initialUser.Identity as ClaimsIdentity;

            if (userIdentity is not null)
            {
                account?.Roles?.ForEach((role) =>
                {
                    userIdentity.AddClaim(new Claim("appRole", role));
                });

                account?.Wids?.ForEach((wid) =>
                {
                    userIdentity.AddClaim(new Claim("directoryRole", wid));
                });

                try
                {
                    var client = ActivatorUtilities
                        .CreateInstance<GraphServiceClient>(serviceProvider);
                    var request = client.Me.Request();
                    var user = await request.GetAsync();

                    if (user is not null)
                    {
                        userIdentity.AddClaim(new Claim("mobilephone",
                            user.MobilePhone ?? "(000) 000-0000"));
                        userIdentity.AddClaim(new Claim("officelocation",
                            user.OfficeLocation ?? "Not set"));
                    }

                    var requestMemberOf = client.Users[account?.Oid].MemberOf;
                    var memberships = await requestMemberOf.Request().GetAsync();

                    if (memberships is not null)
                    {
                        foreach (var entry in memberships)
                        {
                            if (entry.ODataType == "#microsoft.graph.group")
                            {
                                userIdentity.AddClaim(
                                    new Claim("directoryGroup", entry.Id));
                            }
                        }
                    }
                }
                catch (AccessTokenNotAvailableException exception)
                {
                    exception.Redirect();
                }
            }
        }

        return initialUser;
    }
}

Der vorangehende Code enthält keine transitiven Mitgliedschaften. Wenn die App direkte und transitive Gruppenmitgliedschaftsansprüche erfordert, ersetzen Sie die MemberOf-Eigenschaft (IUserMemberOfCollectionWithReferencesRequestBuilder) durch TransitiveMemberOf (IUserTransitiveMemberOfCollectionWithReferencesRequestBuilder).

Der obige Code ignoriert Gruppenmitgliedschaftsansprüche (groups), bei denen es sich um ME-ID-Administratorrollen (Typ #microsoft.graph.directoryRole) handelt, weil die von Microsoft Identity Platform zurückgegebenen GUID-Werte Entitäts-IDs und keine Rollenvorlagen-IDs für ME-ID-Administratorrollen sind. Entitäts-IDs bleiben in Microsoft Identity Platform nicht mandantenübergreifend erhalten und sollten nicht zum Erstellen von Autorisierungsrichtlinien für Benutzer in Apps verwendet werden. Verwenden Sie immer Rollenvorlagen-IDs für von wids-Ansprüchen bereitgestellte ME-ID-Administratorrollen.

Konfigurieren Sie in der CLIENT-App die MSAL-Authentifizierung (Microsoft Authentication Library) für die Verwendung der benutzerdefinierten Benutzerkontofactory.

Vergewissern Sie sich, dass die Datei Program den Microsoft.AspNetCore.Components.WebAssembly.Authentication-Namespace verwendet:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Aktualisieren Sie den AddMsalAuthentication-Aufruf wie im Folgenden gezeigt. Beachten Sie, dass das RemoteUserAccount des Blazor-Frameworks durch das CustomUserAccount der App für die MSAL-Authentifizierung und die Kontoanspruchs-Prinzipalfactory ersetzt wird:

builder.Services.AddMsalAuthentication<RemoteAuthenticationState,
    CustomUserAccount>(options =>
    {
        builder.Configuration.Bind("AzureAd",
            options.ProviderOptions.Authentication);
    })
    .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount,
        CustomAccountFactory>();

Vergewissern Sie sich, dass der im Artikel Verwenden der Graph-API mit der Blazor WebAssembly von ASP.NET Core beschriebene Graph SDK-Code vorhanden ist und die Konfiguration von wwwroot/appsettings.json dem Leitfaden zum Graph SDK entspricht:

var baseUrl = string.Join("/", 
    builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"], 
    builder.Configuration.GetSection("MicrosoftGraph")["Version"]);
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
    .Get<List<string>>();

builder.Services.AddGraphClient(baseUrl, scopes);

wwwroot/appsettings.json:

{
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com",
    "Version: "v1.0",
    "Scopes": [
      "user.read"
    ]
  }
}

Konfigurieren der Autorisierung

Erstellen Sie in der CLIENT-App eine Richtlinie für jede App-Rolle, ME-ID-Administratorrolle oder Sicherheitsgruppe in der Program-Datei. Im folgenden Beispiel wird eine Richtlinie für die ME-ID-Rolle Abrechnungsadministrator erstellt:

builder.Services.AddAuthorizationCore(options =>
{
    options.AddPolicy("BillingAdministrator", policy => 
        policy.RequireClaim("directoryRole", 
            "b0f54661-2d74-4c50-afa3-1ec803f12efe"));
});

Die vollständige Liste der IDs für ME-ID Administratorrollen finden Sie unter Rollenvorlagen-IDs in der Entra-Dokumentation. Weitere Informationen zu Autorisierungsrichtlinien finden Sie unter Richtlinienbasierte Autorisierung in ASP.NET Core.

In den folgenden Beispielen verwendet die CLIENT-App die oben genannte Richtlinie zum Autorisieren des Benutzers.

Die AuthorizeView-Komponente verwendet die Richtlinie:

<AuthorizeView Policy="BillingAdministrator">
    <Authorized>
        <p>
            The user is in the 'Billing Administrator' ME-ID Administrator Role
            and can see this content.
        </p>
    </Authorized>
    <NotAuthorized>
        <p>
            The user is NOT in the 'Billing Administrator' role and sees this
            content.
        </p>
    </NotAuthorized>
</AuthorizeView>

Durch Verwendung einer [Authorize]-Attributanweisung (AuthorizeAttribute) kann mithilfe der Richtlinie der Zugriff auf eine gesamte Komponente geregelt werden:

@page "/"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "BillingAdministrator")]

Wenn der Benutzer nicht autorisiert ist, wird er zur ME-ID-Anmeldeseite umgeleitet.

Eine Richtlinienüberprüfung kann auch in Code mit prozeduraler Logik durchgeführt werden.

CheckPolicy.razor:

@page "/checkpolicy"
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService

<h1>Check Policy</h1>

<p>This component checks a policy in code.</p>

<button @onclick="CheckPolicy">Check 'BillingAdministrator' policy</button>

<p>Policy Message: @policyMessage</p>

@code {
    private string policyMessage = "Check hasn't been made yet.";

    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    private async Task CheckPolicy()
    {
        var user = (await authenticationStateTask).User;

        if ((await AuthorizationService.AuthorizeAsync(user, 
            "BillingAdministrator")).Succeeded)
        {
            policyMessage = "Yes! The 'BillingAdministrator' policy is met.";
        }
        else
        {
            policyMessage = "No! 'BillingAdministrator' policy is NOT met.";
        }
    }
}

Autorisieren des Server-API-/Web-API-Zugriffs

Eine SERVER-API-App kann Benutzer mit Autorisierungsrichtlinien für Sicherheitsgruppen, ME-ID-Administratorrollen und App-Rollen für den Zugriff auf sichere API-Endpunkte autorisieren, wenn ein Zugriffstoken groups-, wids- und role-Ansprüche enthält. Das folgende Beispiel erstellt eine Richtlinie für die ME-ID-Rolle Abrechnungsadministrator in der Program-Datei mithilfe der wids-Ansprüche (bekannte IDs oder Rollenvorlagen-IDs):

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("BillingAdministrator", policy => 
        policy.RequireClaim("wids", "b0f54661-2d74-4c50-afa3-1ec803f12efe"));
});

Die vollständige Liste der IDs für ME-ID-Administratorrollen finden Sie in der Azure-Dokumentation unter Rollenvorlagen-IDs. Weitere Informationen zu Autorisierungsrichtlinien finden Sie unter Richtlinienbasierte Autorisierung in ASP.NET Core.

Der Zugriff auf einen Controller in der SERVER-App kann auf der Verwendung eines [Authorize]-Attributs mit dem Namen der Richtlinie basieren (API-Dokumentation: AuthorizeAttribute).

Das folgende Beispiel beschränkt den Zugriff auf Abrechnungsdaten vom BillingDataController auf Azure-Abrechnungsadministratoren mit dem Richtliniennamen BillingAdministrator:

using Microsoft.AspNetCore.Authorization;
[Authorize(Policy = "BillingAdministrator")]
[ApiController]
[Route("[controller]")]
public class BillingDataController : ControllerBase
{
    ...
}

Weitere Informationen finden Sie unter Richtlinienbasierte Autorisierung in ASP.NET Core.

App-Rollen

Um die Anwendung im Azure-Portal so zu konfigurieren, dass sie Mitgliedschaftsansprüche von Anwendungsrollen bereitstellt, lesen Sie den Abschnitt Anwendungsrollen zu Ihrer Anwendung hinzufügen und im Token empfangen in der Entra-Dokumentation.

Im folgenden Beispiel wird angenommen, dass die CLIENT- und SERVER-Apps mit zwei Rollen konfiguriert und die Rollen einem Testbenutzer zugewiesen sind:

  • Admin
  • Developer

Hinweis

Wenn Sie ein Clientserverpaar aus eigenständigen Apps (einer eigenständigen Blazor WebAssembly-App und einer Server- oder API-App in ASP.NET Core) entwickeln, muss die Manifesteigenschaft appRoles der App-Registrierungen des Clients und des Servers im Azure-Portal dieselben konfigurierten Rollen enthalten. Nachdem die Rollen im Manifest der Client-App festgelegt wurden, kopieren Sie diese in Gänze in das Manifest der Server-App. Wenn Sie die appRoles-Manifesteigenschaft der Client- und Server-App-Registrierungen nicht spiegeln, werden keine Rollenansprüche für authentifizierte Benutzer der Server-API/Web-API erstellt, auch wenn das Zugriffstoken über die richtigen Einträge in den role-Ansprüchen verfügt.

Hinweis

Wenn Sie eine gehostete Blazor WebAssembly-App oder ein Client-Server-Paar aus eigenständigen Apps (einer eigenständigen Blazor WebAssembly-App und einer ASP.NET Core-Server-API-/Web-API-App) entwickeln, muss die Manifesteigenschaft appRoles der Registrierungen des Clients und des Servers im Azure-Portal dieselben konfigurierten Rollen enthalten. Nachdem die Rollen im Manifest der Client-App festgelegt wurden, kopieren Sie diese in Gänze in das Manifest der Server-App. Wenn Sie die appRoles-Manifesteigenschaft der Client- und Server-App-Registrierungen nicht spiegeln, werden keine Rollenansprüche für authentifizierte Benutzer der Server-API/Web-API erstellt, auch wenn das Zugriffstoken über die richtigen Einträge in den role-Ansprüchen verfügt.

Ohne Microsoft Entra ID Premium-Konto können Sie Gruppen keine Rollen zuweisen. Sie können jedoch mit einem Azure-Standardkonto Benutzern Rollen zuweisen und einen role-Anspruch für Benutzer erhalten. Für die Schritte in diesem Abschnitt ist kein ME-ID Premium-Konto erforderlich.

Wenn Sie über ein Azure-Konto im Premium-Tarif verfügen, wird im Azure-Portal auf der Randleiste der App-Registrierung Verwalten>App-Rollen angezeigt. Folgen Sie der Anleitung unter Anwendungsrollen zu Ihrer Anwendung hinzufügen und im Token empfangen, um die Rollen der Anwendung zu konfigurieren.

Falls Sie kein Azure-Konto im Premium-Tarif haben, bearbeiten Sie das App-Manifest im Azure-Portal. Befolgen Sie den Leitfaden unter Anwendungsrollen: Implementierung, um die Rollen der App manuell im appRoles-Eintrag der Manifestdatei einzurichten. Speichern Sie die Änderungen in der Datei.

Im Folgenden sehen Sie einen appRoles-Beispieleintrag, der Admin- und Developer-Rollen erstellt. Diese Beispielrollen werden an späterer Stelle im Beispiel in diesem Abschnitt auf Komponentenebene verwendet, um Zugriffsbeschränkungen zu implementieren:

"appRoles": [
  {
    "allowedMemberTypes": [
      "User"
    ],
    "description": "Administrators manage developers.",
    "displayName": "Admin",
    "id": "584e483a-7101-404b-9bb1-83bf9463e335",
    "isEnabled": true,
    "lang": null,
    "origin": "Application",
    "value": "Admin"
  },
  {
    "allowedMemberTypes": [
      "User"
    ],
    "description": "Developers write code.",
    "displayName": "Developer",
    "id": "82770d35-2a93-4182-b3f5-3d7bfe9dfe46",
    "isEnabled": true,
    "lang": null,
    "origin": "Application",
    "value": "Developer"
  }
],

Hinweis

Sie können GUIDs mit einem Online-GUID-Generator-Tool (Google-Suchergebnis für „GUID-Generator“) generieren.

So weisen Sie einem Benutzer (oder einer Gruppe, wenn Sie über ein Azure-Konto im Premium-Tarif verfügen) eine Rolle zu:

  1. Navigieren Sie im ME-ID-Bereich des Azure-Portals zu Unternehmensanwendungen.
  2. Wählen Sie die App aus. Wählen Sie auf der Randleiste Verwalten>Benutzer und Gruppen aus.
  3. Aktivieren Sie das Kontrollkästchen für ein oder mehrere Benutzerkonten.
  4. Wählen Sie im Menü über der Liste der Benutzer die Option Zuweisung bearbeiten aus.
  5. Wählen Sie für den Eintrag Rolle auswählen die Option Keine ausgewählt aus.
  6. Klicken Sie in der Liste auf eine Rolle, und wählen Sie sie mit der Schaltfläche Auswählen aus.
  7. Verwenden Sie die Schaltfläche Zuweisen am unteren Bildschirmrand, um die Rolle zuzuweisen.

Mehrere Rollen werden im Azure-Portal durch separates Hinzufügen eines Benutzers für jede weitere Rollenzuweisung zugewiesen. Verwenden Sie die Schaltfläche Benutzer/Gruppe hinzufügen oben in der Liste der Benutzer, um einen Benutzer erneut hinzuzufügen. Führen Sie die obigen Schritte aus, um dem Benutzer eine weitere Rolle zuzuweisen. Sie können diesen Vorgang beliebig oft wiederholen, um einem Benutzer (oder einer Gruppe) zusätzliche Rollen hinzuzufügen.

Die im Abschnitt Benutzerdefiniertes Benutzerkonto gezeigte CustomAccountFactory ist so konfiguriert, dass sie auf einen role-Anspruch mit einem JSON-Arraywert reagiert. Fügen Sie die CustomAccountFactory in der CLIENT-App hinzu, und registrieren Sie sie, wie im Abschnitt Benutzerdefiniertes Benutzerkonto gezeigt. Für das Entfernen des ursprünglichen role-Anspruchs muss kein Code bereitgestellt werden, da das Framework diesen automatisch entfernt.

Geben Sie in der Program-Datei einer CLIENT-App den Anspruch namens appRole als Rollenanspruch für ClaimsPrincipal.IsInRole-Überprüfungen an:

builder.Services.AddMsalAuthentication(options =>
{
    ...

    options.UserOptions.RoleClaim = "appRole";
});

Hinweis

Wenn Sie lieber den directoryRoles-Anspruch (ADD-Administratorrollen) verwenden möchten, weisen Sie directoryRoles zu RemoteAuthenticationUserOptions.RoleClaim zu.

Geben Sie in der Program-Datei einer SERVER-App den Anspruch namens http://schemas.microsoft.com/ws/2008/06/identity/claims/role als Rollenanspruch für ClaimsPrincipal.IsInRole-Überprüfungen an:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(options =>
    {
        Configuration.Bind("AzureAd", options);
        options.TokenValidationParameters.RoleClaimType = 
            "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
    },
    options => { Configuration.Bind("AzureAd", options); });

Hinweis

Wenn ein einzelnes Authentifizierungsschema registriert ist, wird es automatisch als Standardschema der App verwendet, und es ist nicht erforderlich, das Schema auf AddAuthentication oder über AuthenticationOptions anzugeben. Weitere Informationen finden Sie in der Übersicht über die ASP.NET Core- Authentifizierung und in der ASP.NET Core-Ankündigung (aspnet/Announcements #490).

Hinweis

Wenn Sie lieber den wids-Anspruch (ADD-Administratorrollen) verwenden möchten, weisen Sie wids zu TokenValidationParameters.RoleClaimType zu.

Nachdem Sie die vorherigen Schritte zum Erstellen und Zuweisen von Rollen für Benutzer (oder Gruppen, wenn Sie über ein Azure-Konto im Premium-Tarif verfügen) ausgeführt und die CustomAccountFactory mit dem Graph SDK wie weiter oben in diesem Artikel und unter Verwenden der Graph-API mit der Blazor WebAssembly von ASP.NET Core beschrieben implementiert haben, sollte ein appRole-Anspruch für jede Rolle, die einem angemeldeten Benutzer zugewiesen ist (oder Rollen, die Gruppen zugewiesen sind, denen er angehört), angezeigt werden. Führen Sie die App mit einem Testbenutzer aus, um sicherzustellen, dass die Ansprüche wie erwartet vorhanden sind. Beim lokalem Testen mit dem Graph SDK empfehlen wir die Verwendung einer neuen privaten bzw. Inkognito-Browsersitzung für jeden Test, um zu verhindern, dass Tests durch vorhandene cookies beeinträchtigt werden. Weitere Informationen finden Sie unter Sichern einer eigenständigen ASP.NET Core-Blazor WebAssembly-App mit Microsoft Entra ID.

Die Komponentenautorisierungsansätze sind Stand jetzt funktional. Jeder der Autorisierungsmechanismen in Komponenten der CLIENT-App kann die Rolle Admin verwenden, um Benutzer zu autorisieren:

Mehrere Rollentests werden unterstützt:

  • Legen Sie mithilfe der AuthorizeView-Komponente als erforderlich fest, dass der Benutzer entweder die Rolle Adminoder die Rolle Developer innehat:

    <AuthorizeView Roles="Admin, Developer">
        ...
    </AuthorizeView>
    
  • Legen Sie mithilfe der AuthorizeView-Komponente als erforderlich fest, dass der Benutzer sowohl die Rolle Adminals auch die Rolle Developer innehat:

    <AuthorizeView Roles="Admin">
        <AuthorizeView Roles="Developer" Context="innerContext">
            ...
        </AuthorizeView>
    </AuthorizeView>
    

    Weitere Informationen zu Context für die innere AuthorizeView finden Sie unter ASP.NET Core-Blazor-Authentifizierung und -Autorisierung.

  • Legen Sie mithilfe des [Authorize]-Attributs als erforderlich fest, dass der Benutzer entweder die Rolle Adminoder die Rolle Developer innehat:

    @attribute [Authorize(Roles = "Admin, Developer")]
    
  • Legen Sie mithilfe des [Authorize]-Attributs als erforderlich fest, dass der Benutzer sowohl die Rolle Adminals auch die Rolle Developer innehat:

    @attribute [Authorize(Roles = "Admin")]
    @attribute [Authorize(Roles = "Developer")]
    
  • Legen Sie mit prozeduralem Code als erforderlich fest, dass der Benutzer entweder die Rolle Adminoder die Rolle Developer innehat:

    @code {
        private async Task DoSomething()
        {
            var authState = await AuthenticationStateProvider
                .GetAuthenticationStateAsync();
            var user = authState.User;
    
            if (user.IsInRole("Admin") || user.IsInRole("Developer"))
            {
                ...
            }
            else
            {
                ...
            }
        }
    }
    
  • Legen Sie mit prozeduralem Code als erforderlich fest, dass der Benutzer sowohl die Rolle Adminals auch die Rolle Developer innehat. Ändern Sie dazu im vorherigen Beispiel das bedingte OR (||) in ein bedingtes AND (&&):

    if (user.IsInRole("Admin") && user.IsInRole("Developer"))
    

Jeder der Autorisierungsmechanismen in Controllern der SERVER-App kann die Rolle Admin verwenden, um Benutzer zu autorisieren:

Mehrere Rollentests werden unterstützt:

  • Legen Sie mithilfe des [Authorize]-Attributs als erforderlich fest, dass der Benutzer entweder die Rolle Adminoder die Rolle Developer innehat:

    [Authorize(Roles = "Admin, Developer")]
    
  • Legen Sie mithilfe des [Authorize]-Attributs als erforderlich fest, dass der Benutzer sowohl die Rolle Adminals auch die Rolle Developer innehat:

    [Authorize(Roles = "Admin")]
    [Authorize(Roles = "Developer")]
    
  • Legen Sie mit prozeduralem Code als erforderlich fest, dass der Benutzer entweder die Rolle Adminoder die Rolle Developer innehat:

    static readonly string[] scopeRequiredByApi = new string[] { "API.Access" };
    
    ...
    
    [HttpGet]
    public IEnumerable<ReturnType> Get()
    {
        HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
    
        if (User.IsInRole("Admin") || User.IsInRole("Developer"))
        {
            ...
        }
        else
        {
            ...
        }
    
        return ...
    }
    
  • Legen Sie mit prozeduralem Code als erforderlich fest, dass der Benutzer sowohl die Rolle Adminals auch die Rolle Developer innehat. Ändern Sie dazu im vorherigen Beispiel das bedingte OR (||) in ein bedingtes AND (&&):

    if (User.IsInRole("Admin") && User.IsInRole("Developer"))
    

Da bei .NET-Zeichenfolgenvergleichen standardmäßig die Groß-/Kleinschreibung beachtet wird, wird beim Abgleich von Rollennamen auch die Groß-/Kleinschreibung beachtet. Beispielsweise wird Admin (mit Großbuchstabe A) nicht als dieselbe Rolle wie admin (mit Kleinbuchstabe a) behandelt.

Die Pascal-Schreibweise wird in der Regel für Rollennamen (z. B. BillingAdministrator) verwendet, aber die Verwendung der Pascal-Schreibweise ist keine strenge Anforderung. Unterschiedliche Groß-/Kleinschreibungen wie Camel Case, Kebab Case und Snake Case sind zulässig. Die Verwendung von Leerzeichen in Rollennamen ist ebenfalls ungewöhnlich, aber zulässig. Beispielsweise ist billing administrator ein ungewöhnliches Rollennamenformat in .NET-Apps, aber gültig.

Zusätzliche Ressourcen