Dela via


Använda Graph API med ASP.NET Core Blazor WebAssembly

Anmärkning

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Viktigt!

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Den här artikeln beskriver hur du använder Microsoft Graph i Blazor WebAssembly appar, vilket gör det möjligt för appar att komma åt Microsoft Cloud-resurser.

Två metoder beskrivs:

  • Graph SDK: Microsoft Graph SDK förenklar skapandet av högkvalitativa, effektiva och motståndskraftiga appar som har åtkomst till Microsoft Graph. Välj knappen Graph SDK överst i den här artikeln för att använda den här metoden.

  • Med namnet HttpClient med Graph API: Ett namngivet HttpClient kan utfärda Microsoft Graph API-begäranden direkt till Microsoft Graph. Välj knappen Namngiven HttpClient med Graph API överst i den här artikeln för att anta denna metod.

Vägledningen i den här artikeln är inte avsedd att ersätta Microsoft Graph-dokumentationen och Azures säkerhetsvägledning i andra Microsoft-dokumentationsuppsättningar. Utvärdera säkerhetsvägledningen i avsnittet Ytterligare resurser i den här artikeln innan du implementerar Microsoft Graph i en produktionsmiljö. Följ Microsofts metodtips för att begränsa sårbarheterna i dina appar.

Ytterligare metoder för att arbeta med Microsoft Graph och Blazor WebAssembly tillhandahålls av följande Microsoft Graph- och Azure-exempel:

Om du vill ge feedback om något av de föregående två exemplen öppnar du ett problem på exemplets GitHub-lagringsplats. Om du öppnar ett problem för Azure-exemplet anger du en länk till exemplet i din inledande kommentar eftersom Azure-exempellagringsplatsen (Azure-Samples) innehåller många exempel. Beskriv problemet i detalj och inkludera exempelkod efter behov. Placera en minimal app i GitHub som återskapar problemet eller felet. Se till att ta bort Azure-kontokonfigurationsdata från exemplet innan du lägger upp dem i det offentliga arkivet.

Om du vill ge feedback eller söka hjälp med den här artikeln eller ASP.NET Core kan du läsa grunderna i ASP.NET CoreBlazor.

Viktigt!

Scenarierna som beskrivs i den här artikeln gäller för användning av Microsoft Entra (ME-ID) som identitetsprovider, inte AAD B2C. Användning av Microsoft Graph med en app på klientsidan Blazor WebAssembly och AAD B2C-identitetsprovidern stöds inte just nu eftersom appen skulle kräva en klienthemlighet som inte kan skyddas i appen på klientsidan Blazor . För en fristående Blazor WebAssembly AAD B2C-app använder du Graph API genom att skapa ett server-API (webb) för att få åtkomst till Graph API för användarnas räkning. Appen på klientsidan autentiserar och auktoriserar användare att anropa webb-API:et för säker åtkomst till Microsoft Graph och returnera data till appen på klientsidan Blazor från ditt serverbaserade webb-API. Klienthemligheten underhålls på ett säkert sätt i det serverbaserade webb-API:et Blazor , inte i appen på klienten. Lagra aldrig en klienthemlighet i en app på klientsidan Blazor .

Användning av en värdbaserad Blazor WebAssembly app stöds, där Server appen använder Graph SDK/API för att tillhandahålla Graph-data till Client appen via webb-API. För mer information, se avsnittet hostade Blazor WebAssembly lösningar i den här artikeln.

Exemplen i den här artikeln drar nytta av nya .NET/C#-funktioner. När du använder exemplen med .NET 7 eller tidigare krävs mindre ändringar. De text- och kodexempel som gäller interaktion med Microsoft Graph är dock desamma för alla versioner av ASP.NET Core.

Följande vägledning gäller för Microsoft Graph v5.

Microsoft Graph SDK för användning i Blazor appar kallas Microsoft Graph .NET-klientbiblioteket.

Graph SDK-exemplen kräver följande paketreferenser i den fristående Blazor WebAssembly appen. De två första paketen refereras redan om appen har aktiverats för MSAL-autentisering, till exempel när du skapar appen genom att följa anvisningarna i Skydda en fristående ASP.NET Core-app Blazor WebAssembly med Microsoft Entra-ID.

Graph SDK-exemplen kräver följande paketreferenser i den fristående Blazor WebAssembly appen eller appen för Client en värdbaserad Blazor WebAssembly lösning. De två första paketen refereras redan om appen har aktiverats för MSAL-autentisering, till exempel när du skapar appen genom att följa anvisningarna i Skydda en fristående ASP.NET Core-app Blazor WebAssembly med Microsoft Entra-ID.

Anmärkning

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

I Azure-portalen beviljar du delegerade behörigheter (omfång)† för Microsoft Graph-data som appen ska kunna komma åt för en användares räkning. I exemplet i den här artikeln bör appens registrering innehålla delegerad behörighet att läsa användardata (Microsoft.Graph>User.Read omfång i API-behörigheter, Typ: Delegerad). Omfånget User.Read gör det möjligt för användare att logga in på appen och gör att appen kan läsa profil- och företagsinformation för inloggade användare. Mer information finns i Översikt över behörigheter och medgivande i Microsofts identitetsplattform och Översikt över Microsoft Graph-behörigheter.

Behörigheter och omfång betyder samma sak och används på samma sätt i säkerhetsdokumentationen och Azure-portalen. Om inte texten refererar till Azure-portalen använder den här artikeln omfången / när den refererar till Graph-behörigheter.

Scopes är okänsliga för skiftläget, så User.Read är samma som user.read. Använd gärna något av formaten, men vi rekommenderar ett konsekvent val i programkoden.

När du har lagt till Microsoft Graph API-omfång i appens registrering i Azure-portalen lägger du till följande konfiguration av appinställningar i wwwroot/appsettings.json filen i appen, som innehåller Graph-bas-URL:en med Microsoft Graph-versionen och omfången. I följande exempel anges omfånget User.Read för exemplen i senare avsnitt i den här artikeln. Omfång är inte skiftlägeskänsliga.

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

I föregående exempel {VERSION} är platshållaren versionen av Microsoft Graph API (till exempel: v1.0).

Följande är ett exempel på en fullständig wwwroot/appsettings.json konfigurationsfil för en app som använder ME-ID som identitetsprovider, där läsning av användardata (user.read omfång) anges för Microsoft Graph:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/{TENANT ID}",
    "ClientId": "{CLIENT ID}",
    "ValidateAuthority": true
  },
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com",
    "Version": "v1.0",
    "Scopes": [
      "user.read"
    ]
  }
}

I det föregående exemplet är {TENANT ID}-platshållaren den katalogens (hyresgäst) ID och {CLIENT ID}-platshållaren är applikationens (klient) ID. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Lägg till följande GraphClientExtensions klass i den fristående appen. Omfången tillhandahålls som egenskapen Scopes till AccessTokenRequestOptions i metoden AuthenticateRequestAsync.

Lägg till följande GraphClientExtensions klass i den fristående appen eller Client appen för en värdbaserad Blazor WebAssemblylösning. Omfången tillhandahålls som egenskapen Scopes till AccessTokenRequestOptions i metoden AuthenticateRequestAsync.

När en åtkomsttoken inte hämtas, anger följande kod inte ett Bearer-autoriseringshuvud för Graph-begäranden.

GraphClientExtensions.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.Authentication.WebAssembly.Msal.Models;
using Microsoft.Graph;
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Authentication;
using IAccessTokenProvider = 
    Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider;

namespace BlazorSample;

internal static class GraphClientExtensions
{
    public static IServiceCollection AddGraphClient(
            this IServiceCollection services, string? baseUrl, List<string>? scopes)
    {
        if (string.IsNullOrEmpty(baseUrl) || scopes?.Count == 0)
        {
            return services;
        }

        services.Configure<RemoteAuthenticationOptions<MsalProviderOptions>>(
            options =>
            {
                scopes?.ForEach((scope) =>
                {
                    options.ProviderOptions.DefaultAccessTokenScopes.Add(scope);
                });
            });

        services.AddScoped<IAuthenticationProvider, GraphAuthenticationProvider>();

        services.AddScoped(sp =>
        {
            return new GraphServiceClient(
                new HttpClient(),
                sp.GetRequiredService<IAuthenticationProvider>(),
                baseUrl);
        });

        return services;
    }

    private class GraphAuthenticationProvider(IAccessTokenProvider tokenProvider, 
        IConfiguration config) : IAuthenticationProvider
    {
        private readonly IConfiguration config = config;

        public IAccessTokenProvider TokenProvider { get; } = tokenProvider;

        public async Task AuthenticateRequestAsync(RequestInformation request, 
            Dictionary<string, object>? additionalAuthenticationContext = null, 
            CancellationToken cancellationToken = default)
        {
            var result = await TokenProvider.RequestAccessToken(
                new AccessTokenRequestOptions()
                {
                    Scopes = 
                        config.GetSection("MicrosoftGraph:Scopes").Get<string[]>() ??
                        [ "user.read" ]
                });

            if (result.TryGetToken(out var token))
            {
                request.Headers.Add("Authorization", 
                    $"{CoreConstants.Headers.Bearer} {token.Value}");
            }
        }
    }
}

Viktigt!

Se avsnittet DefaultAccessTokenScopes kontra AdditionalScopesToConsent för en förklaring av varför den tidigare koden använder DefaultAccessTokenScopes för att lägga till omfattningarna i stället för AdditionalScopesToConsent.

I filen Program lägger du till klienttjänster och konfiguration för Graph med tilläggsmetoden AddGraphClient. Följande kod använder standardinställningarna för Microsoft Graph-basadressen version 1.0 och User.Read-omfången om dessa inställningar inte finns i appens inställningsfil:

var baseUrl = string.Join("/",
    builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
        "https://graph.microsoft.com",
    builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
        "v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
    .Get<List<string>>() ?? [ "user.read" ];

builder.Services.AddGraphClient(baseUrl, scopes);

Anropa Graph API från en komponent med hjälp av Graph SDK

Följande UserData komponent använder en matad GraphServiceClient för att hämta användarens ME-ID profildata och visa deras mobiltelefonnummer.

För alla testanvändare som du skapar i ME-ID kontrollerar du att du ger användarens ME-ID profil ett mobiltelefonnummer i Azure-portalen.

UserData.razor:

@page "/user-data"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.Graph
@attribute [Authorize]
@inject GraphServiceClient Client

<PageTitle>User Data</PageTitle>

<h1>Microsoft Graph User Data</h1>

@if (!string.IsNullOrEmpty(user?.MobilePhone))
{
    <p>Mobile Phone: @user.MobilePhone</p>
}

@code {
    private Microsoft.Graph.Models.User? user;

    protected override async Task OnInitializedAsync()
    {
        user = await Client.Me.GetAsync();
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-data">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Data
    </NavLink>
</div>

Tips/Råd

Information om hur du lägger till användare i en app finns i avsnittet Tilldela användare till en appregistrering med eller utan approller .

När du testar med Graph SDK lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testerna. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Anpassa användaranspråk med hjälp av Graph SDK

I följande exempel skapar appen mobiltelefonnummer och kontorsplatsanspråk av en användare baserat på data från deras ME-ID-användarprofil. Appen måste ha User.Read Graph API-omfånget konfigurerat i ME-ID. Alla testanvändare för det här scenariot måste ha ett mobiltelefonnummer och en kontorsplats i sin ME-ID profil, som kan läggas till via Azure-portalen.

I följande anpassade användarkontofabrik:

  • En ILogger (logger) ingår för enkelhetens skull om du vill logga information eller fel i CreateUserAsync metoden.
  • Om en AccessTokenNotAvailableException utlöses omdirigeras användaren till identitetsprovidern för att logga in på sitt konto. Ytterligare eller olika åtgärder kan vidtas när begäran om en åtkomsttoken misslyckas. Appen kan till exempel logga AccessTokenNotAvailableException och skapa ett supportärende för ytterligare undersökning.
  • Ramverket RemoteUserAccount representerar användarens konto. Om appen kräver en anpassad användarkontoklass som utökar RemoteUserAccountbyter du din anpassade användarkontoklass mot RemoteUserAccount i följande kod.

CustomAccountFactory.cs:

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;

public class CustomAccountFactory(IAccessTokenProviderAccessor accessor,
        IServiceProvider serviceProvider, ILogger<CustomAccountFactory> logger,
        IConfiguration config) 
    : AccountClaimsPrincipalFactory<RemoteUserAccount>(accessor)
{
    private readonly ILogger<CustomAccountFactory> logger = logger;
    private readonly IServiceProvider serviceProvider = serviceProvider;
    private readonly string? baseUrl = string.Join("/",
        config.GetSection("MicrosoftGraph")["BaseUrl"] ?? 
            "https://graph.microsoft.com",
        config.GetSection("MicrosoftGraph")["Version"] ??
            "v1.0");

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        RemoteUserAccount 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))
            {
                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"));
                    }
                }
                catch (AccessTokenNotAvailableException exception)
                {
                    exception.Redirect();
                }
            }
        }

        return initialUser;
    }
}

Konfigurera MSAL-autentiseringen så att den använder den anpassade användarkontofabriken.

Bekräfta att Program-filen använder namnområdet Microsoft.AspNetCore.Components.WebAssembly.Authentication:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Exemplet i det här avsnittet bygger på metoden att läsa bas-URL:en med version och omfång från appkonfiguration via MicrosoftGraph avsnittet i wwwroot/appsettings.json filen. Följande rader bör redan finnas i Program filen från att följa riktlinjerna tidigare i den här artikeln:

var baseUrl = string.Join("/",
    builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
        "https://graph.microsoft.com",
    builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
        "v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
    .Get<List<string>>() ?? [ "user.read" ];

builder.Services.AddGraphClient(baseUrl, scopes);

I Program-filen, hitta anropet till AddMsalAuthentication-tilläggsmetoden. Uppdatera koden till följande, vilket inkluderar ett anrop till AddAccountClaimsPrincipalFactory som lägger till en huvudfabrik för kontoanspråk med CustomAccountFactory.

Om appen använder en anpassad användarkontoklass som utökar RemoteUserAccountbyter du den anpassade användarkontoklassen mot RemoteUserAccount i följande kod.

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

Du kan använda följande UserClaims komponent för att studera användarens anspråk när användaren har autentiserats med ME-ID:

UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}
else
{
    <p>No claims found.</p>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        claims = user.Claims;
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-claims">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Claims
    </NavLink>
</div>

När du testar med Graph SDK lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testerna. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Följande vägledning gäller för Microsoft Graph v4. Om du uppgraderar en app från SDK v4 till v5 läser du ändringsloggen och uppgraderingsguiden för Microsoft Graph .NET SDK v5.

Microsoft Graph SDK för användning i Blazor appar kallas Microsoft Graph .NET-klientbiblioteket.

Graph SDK-exemplen kräver följande paketreferenser i den fristående Blazor WebAssembly appen. De två första paketen refereras redan om appen har aktiverats för MSAL-autentisering, till exempel när du skapar appen genom att följa anvisningarna i Skydda en fristående ASP.NET Core-app Blazor WebAssembly med Microsoft Entra-ID.

Graph SDK-exemplen kräver följande paketreferenser i den fristående Blazor WebAssembly appen eller appen för Client en värdbaserad Blazor WebAssembly lösning. De två första paketen refereras redan om appen har aktiverats för MSAL-autentisering, till exempel när du skapar appen genom att följa anvisningarna i Skydda en fristående ASP.NET Core-app Blazor WebAssembly med Microsoft Entra-ID.

Anmärkning

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

I Azure-portalen beviljar du delegerade behörigheter (omfång)† för Microsoft Graph-data som appen ska kunna komma åt för en användares räkning. I exemplet i den här artikeln bör appens registrering innehålla delegerad behörighet att läsa användardata (Microsoft.Graph>User.Read omfång i API-behörigheter, Typ: Delegerad). Omfånget User.Read gör det möjligt för användare att logga in på appen och gör att appen kan läsa profil- och företagsinformation för inloggade användare. Mer information finns i Översikt över behörigheter och medgivande i Microsofts identitetsplattform och Översikt över Microsoft Graph-behörigheter.

Behörigheter och omfång betyder samma sak och används på samma sätt i säkerhetsdokumentationen och Azure-portalen. Om inte texten refererar till Azure-portalen använder den här artikeln omfången / när den refererar till Graph-behörigheter.

Scopes är okänsliga för skiftläget, så User.Read är samma som user.read. Använd gärna något av formaten, men vi rekommenderar ett konsekvent val i programkoden.

När du har lagt till Microsoft Graph API-omfång i appens registrering i Azure-portalen lägger du till följande konfiguration av appinställningar i wwwroot/appsettings.json filen i appen, som innehåller Graph-bas-URL:en med Microsoft Graph-versionen och omfången. I följande exempel anges omfånget User.Read för exemplen i senare avsnitt i den här artikeln. Omfång är inte skiftlägeskänsliga.

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

I föregående exempel {VERSION} är platshållaren versionen av Microsoft Graph API (till exempel: v1.0).

Följande är ett exempel på en fullständig wwwroot/appsettings.json konfigurationsfil för en app som använder ME-ID som identitetsprovider, där läsning av användardata (user.read omfång) anges för Microsoft Graph:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/{TENANT ID}",
    "ClientId": "{CLIENT ID}",
    "ValidateAuthority": true
  },
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com",
    "Version": "v1.0",
    "Scopes": [
      "user.read"
    ]
  }
}

I det föregående exemplet är {TENANT ID}-platshållaren den katalogens (hyresgäst) ID och {CLIENT ID}-platshållaren är applikationens (klient) ID. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Lägg till följande GraphClientExtensions klass i den fristående appen. Omfången tillhandahålls som egenskapen Scopes till AccessTokenRequestOptions i metoden AuthenticateRequestAsync. IHttpProvider.OverallTimeout Utökas från standardvärdet 100 sekunder till 300 sekunder för att ge HttpClient mer tid att ta emot ett svar från Microsoft Graph.

Lägg till följande GraphClientExtensions klass i den fristående appen eller Client appen för en värdbaserad Blazor WebAssemblylösning. Omfången tillhandahålls som egenskapen Scopes till AccessTokenRequestOptions i metoden AuthenticateRequestAsync. IHttpProvider.OverallTimeout Utökas från standardvärdet 100 sekunder till 300 sekunder för att ge HttpClient mer tid att ta emot ett svar från Microsoft Graph.

När en åtkomsttoken inte hämtas, anger följande kod inte ett Bearer-autoriseringshuvud för Graph-begäranden.

GraphClientExtensions.cs:

using System.Net.Http.Headers;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.Authentication.WebAssembly.Msal.Models;
using Microsoft.Graph;

namespace BlazorSample;

internal static class GraphClientExtensions
{
    public static IServiceCollection AddGraphClient(
        this IServiceCollection services, string? baseUrl, List<string>? scopes)
    {
        if (string.IsNullOrEmpty(baseUrl) || scopes?.Count == 0)
        {
            return services;
        }

        services.Configure<RemoteAuthenticationOptions<MsalProviderOptions>>(
            options =>
            {
                scopes?.ForEach((scope) =>
                {
                    options.ProviderOptions.DefaultAccessTokenScopes.Add(scope);
                });
            });

        services.AddScoped<IAuthenticationProvider, GraphAuthenticationProvider>();

        services.AddScoped<IHttpProvider, HttpClientHttpProvider>(sp =>
            new HttpClientHttpProvider(new HttpClient()));

        services.AddScoped(sp =>
        {
            return new GraphServiceClient(
                baseUrl,
                sp.GetRequiredService<IAuthenticationProvider>(),
                sp.GetRequiredService<IHttpProvider>());
        });

        return services;
    }

    private class GraphAuthenticationProvider(IAccessTokenProvider tokenProvider, 
        IConfiguration config) : IAuthenticationProvider
    {
        private readonly IConfiguration config = config;

        public IAccessTokenProvider TokenProvider { get; } = tokenProvider;

        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            var result = await TokenProvider.RequestAccessToken(
                new AccessTokenRequestOptions()
                { 
                    Scopes = config.GetSection("MicrosoftGraph:Scopes").Get<string[]>()
                });

            if (result.TryGetToken(out var token))
            {
                request.Headers.Authorization ??= new AuthenticationHeaderValue(
                    "Bearer", token.Value);
            }
        }
    }

    private class HttpClientHttpProvider(HttpClient client) : IHttpProvider
    {
        private readonly HttpClient client = client;

        public ISerializer Serializer { get; } = new Serializer();

        public TimeSpan OverallTimeout { get; set; } = TimeSpan.FromSeconds(300);

        public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
        {
            return client.SendAsync(request);
        }

        public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
            HttpCompletionOption completionOption,
            CancellationToken cancellationToken)
        {
            return client.SendAsync(request, completionOption, cancellationToken);
        }

        public void Dispose()
        {
        }
    }
}

Viktigt!

Se avsnittet DefaultAccessTokenScopes kontra AdditionalScopesToConsent för en förklaring av varför den tidigare koden använder DefaultAccessTokenScopes för att lägga till omfattningarna i stället för AdditionalScopesToConsent.

Program I filen lägger du till Graph-klienttjänster och -konfigurationen AddGraphClient med tilläggsmetoden:

var baseUrl = string.Join("/",
    builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
        "https://graph.microsoft.com",
    builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
        "v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
    .Get<List<string>>() ?? [ "user.read" ];

builder.Services.AddGraphClient(baseUrl, scopes);

Anropa Graph API från en komponent med hjälp av Graph SDK

Följande UserData komponent använder en matad GraphServiceClient för att hämta användarens ME-ID profildata och visa deras mobiltelefonnummer. För alla testanvändare som du skapar i ME-ID kontrollerar du att du ger användarens ME-ID profil ett mobiltelefonnummer i Azure-portalen.

UserData.razor:

@page "/user-data"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.Graph
@attribute [Authorize]
@inject GraphServiceClient Client

<PageTitle>User Data</PageTitle>

<h1>Microsoft Graph User Data</h1>

@if (!string.IsNullOrEmpty(user?.MobilePhone))
{
    <p>Mobile Phone: @user.MobilePhone</p>
}

@code {
    private Microsoft.Graph.User? user;

    protected override async Task OnInitializedAsync()
    {
        var request = Client.Me.Request();
        user = await request.GetAsync();
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-data">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Data
    </NavLink>
</div>

Tips/Råd

Information om hur du lägger till användare i en app finns i avsnittet Tilldela användare till en appregistrering med eller utan approller .

När du testar med Graph SDK lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testerna. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Anpassa användaranspråk med hjälp av Graph SDK

I följande exempel skapar appen mobiltelefonnummer och kontorsplatsanspråk av en användare baserat på data från deras ME-ID-användarprofil. Appen måste ha User.Read Graph API-omfånget konfigurerat i ME-ID. Alla testanvändare för det här scenariot måste ha ett mobiltelefonnummer och en kontorsplats i sin ME-ID profil, som kan läggas till via Azure-portalen.

I följande anpassade användarkontofabrik:

  • En ILogger (logger) ingår för enkelhetens skull om du vill logga information eller fel i CreateUserAsync metoden.
  • Om en AccessTokenNotAvailableException utlöses omdirigeras användaren till identitetsprovidern för att logga in på sitt konto. Ytterligare eller olika åtgärder kan vidtas när begäran om en åtkomsttoken misslyckas. Appen kan till exempel logga AccessTokenNotAvailableException och skapa ett supportärende för ytterligare undersökning.
  • Ramverket RemoteUserAccount representerar användarens konto. Om appen kräver en anpassad användarkontoklass som utökar RemoteUserAccountbyter du din anpassade användarkontoklass mot RemoteUserAccount i följande kod.

CustomAccountFactory.cs:

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

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

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        RemoteUserAccount 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)
            {
                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"));
                    }
                }
                catch (AccessTokenNotAvailableException exception)
                {
                    exception.Redirect();
                }
            }
        }

        return initialUser;
    }
}

Konfigurera MSAL-autentiseringen så att den använder den anpassade användarkontofabriken.

Bekräfta att Program-filen använder namnområdet Microsoft.AspNetCore.Components.WebAssembly.Authentication:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Exemplet i det här avsnittet bygger på metoden att läsa bas-URL:en med version och omfång från appkonfiguration via MicrosoftGraph avsnittet i wwwroot/appsettings.json filen. Följande rader bör redan finnas i Program filen från att följa riktlinjerna tidigare i den här artikeln:

var baseUrl = string.Join("/",
    builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
        "https://graph.microsoft.com",
    builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
        "v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
    .Get<List<string>>() ?? [ "user.read" ];

builder.Services.AddGraphClient(baseUrl, scopes);

I Program-filen, hitta anropet till AddMsalAuthentication-tilläggsmetoden. Uppdatera koden till följande, vilket inkluderar ett anrop till AddAccountClaimsPrincipalFactory som lägger till en huvudfabrik för kontoanspråk med CustomAccountFactory.

Om appen använder en anpassad användarkontoklass som utökar RemoteUserAccountbyter du den anpassade användarkontoklassen mot RemoteUserAccount i följande kod.

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

Du kan använda följande UserClaims komponent för att studera användarens anspråk när användaren har autentiserats med ME-ID:

UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}
else
{
    <p>No claims found.</p>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        claims = user.Claims;
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-claims">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Claims
    </NavLink>
</div>

När du testar med Graph SDK lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testerna. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

I följande exempel används ett namn HttpClient för Graph API-anrop för att hämta en användares mobiltelefonnummer för att bearbeta ett samtal eller för att anpassa en användares anspråk för att inkludera ett mobiltelefonnummeranspråk och ett anspråk på kontorsplats.

Exemplen kräver en paketreferens för Microsoft.Extensions.Http, den fristående Blazor WebAssembly-appen.

Exemplen kräver en paketreferens för Microsoft.Extensions.Http den fristående Blazor WebAssembly appen eller appen för Client en värdbaserad Blazor WebAssembly lösning.

Anmärkning

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

I Azure-portalen beviljar du delegerade behörigheter (omfång)† för Microsoft Graph-data som appen ska kunna komma åt för en användares räkning. I exemplet i den här artikeln bör appens registrering innehålla delegerad behörighet att läsa användardata (Microsoft.Graph>User.Read omfång i API-behörigheter, Typ: Delegerad). Omfånget User.Read gör det möjligt för användare att logga in på appen och gör att appen kan läsa profil- och företagsinformation för inloggade användare. Mer information finns i Översikt över behörigheter och medgivande i Microsofts identitetsplattform och Översikt över Microsoft Graph-behörigheter.

Behörigheter och omfång betyder samma sak och används på samma sätt i säkerhetsdokumentationen och Azure-portalen. Om inte texten refererar till Azure-portalen använder den här artikeln omfången / när den refererar till Graph-behörigheter.

Scopes är okänsliga för skiftläget, så User.Read är samma som user.read. Använd gärna något av formaten, men vi rekommenderar ett konsekvent val i programkoden.

När du har lagt till Microsoft Graph API-omfång i appens registrering i Azure-portalen lägger du till följande konfiguration av appinställningar i wwwroot/appsettings.json filen i appen, som innehåller Graph-bas-URL:en med Microsoft Graph-versionen och omfången. I följande exempel anges omfånget User.Read för exemplen i senare avsnitt i den här artikeln. Omfång är inte skiftlägeskänsliga.

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

I föregående exempel {VERSION} är platshållaren versionen av Microsoft Graph API (till exempel: v1.0).

Följande är ett exempel på en fullständig wwwroot/appsettings.json konfigurationsfil för en app som använder ME-ID som identitetsprovider, där läsning av användardata (user.read omfång) anges för Microsoft Graph:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/{TENANT ID}",
    "ClientId": "{CLIENT ID}",
    "ValidateAuthority": true
  },
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com",
    "Version": "v1.0",
    "Scopes": [
      "user.read"
    ]
  }
}

I det föregående exemplet är {TENANT ID}-platshållaren den katalogens (hyresgäst) ID och {CLIENT ID}-platshållaren är applikationens (klient) ID. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Skapa följande GraphAuthorizationMessageHandler klass- och projektkonfiguration i Program filen för att arbeta med Graph API. Bas-URL:en och omfången tillhandahålls till hanteraren från konfigurationen.

GraphAuthorizationMessageHandler.cs:

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

namespace BlazorSample;

public class GraphAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public GraphAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigation, IConfiguration config)
        : base(provider, navigation)
    {
        ConfigureHandler(
            authorizedUrls: [ 
                string.Join("/",
                    config.GetSection("MicrosoftGraph")["BaseUrl"] ??
                        "https://graph.microsoft.com",
                    config.GetSection("MicrosoftGraph")["Version"] ??
                        "v1.0")
            ],
            scopes: config.GetSection("MicrosoftGraph:Scopes")
                        .Get<List<string>>() ?? [ "user.read" ]);
    }
}

Det avslutande snedstrecket (/) för den auktoriserade URL:en krävs. Föregående kod skapar följande auktoriserade URL från konfigurationen av appinställningar eller så används standardinställningen till följande auktoriserade URL om konfigurationen av appinställningarna saknas: https://graph.microsoft.com/v1.0/.

Program I filen konfigurerar du det namngivna HttpClient för Graph API:

builder.Services.AddTransient<GraphAuthorizationMessageHandler>();

builder.Services.AddHttpClient("GraphAPI",
        client => client.BaseAddress = new Uri(
            string.Join("/",
                builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
                    "https://graph.microsoft.com",
                builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
                    "v1.0",
                string.Empty)))
    .AddHttpMessageHandler<GraphAuthorizationMessageHandler>();

I föregående exempel GraphAuthorizationMessageHandlerDelegatingHandler registreras som en tillfällig tjänst för AddHttpMessageHandler. Tillfällig registrering rekommenderas för IHttpClientFactory, som hanterar sina egna DI-omfång. Mer information finns i följande resurser:

Ett avslutande snedstreck (/) på basadressen krävs. I föregående kod är det tredje argumentet till string.Joinstring.Empty för att säkerställa att det avslutande snedstrecket finns: https://graph.microsoft.com/v1.0/.

Anropa Graph API från en komponent med hjälp av en namngiven HttpClient

Klassen UserInfo.cs anger de nödvändiga egenskaperna för användarprofilen JsonPropertyNameAttribute med attributet och det JSON-namn som används av ME-ID. I följande exempel konfigureras egenskaper för användarens mobiltelefonnummer och kontorsplats.

UserInfo.cs:

using System.Text.Json.Serialization;

namespace BlazorSample;

public class UserInfo
{
    [JsonPropertyName("mobilePhone")]
    public string? MobilePhone { get; set; }

    [JsonPropertyName("officeLocation")]
    public string? OfficeLocation { get; set; }
}

I följande UserData komponent skapas en HttpClient för Graph API för att utfärda en begäran om användarens profildata. Resursen me (me) läggs till i bas-URL:en med version för Graph API-begäran. JSON-data som returneras av Graph deserialiseras till klassegenskaperna UserInfo . I följande exempel hämtas mobiltelefonnumret. Du kan lägga till liknande kod för att inkludera användarens ME-ID profilkontorsplats om du vill (userInfo.OfficeLocation). Om begäran om åtkomsttoken misslyckas omdirigeras användaren för att logga in på appen för en ny åtkomsttoken.

UserData.razor:

@page "/user-data"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@attribute [Authorize]
@inject IConfiguration Config
@inject IHttpClientFactory ClientFactory

<PageTitle>User Data</PageTitle>

<h1>Microsoft Graph User Data</h1>

@if (!string.IsNullOrEmpty(userInfo?.MobilePhone))
{
    <p>Mobile Phone: @userInfo.MobilePhone</p>
}

@code {
    private UserInfo? userInfo;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            var client = ClientFactory.CreateClient("GraphAPI");

            userInfo = await client.GetFromJsonAsync<UserInfo>("me");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-data">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Data
    </NavLink>
</div>

Tips/Råd

Information om hur du lägger till användare i en app finns i avsnittet Tilldela användare till en appregistrering med eller utan approller .

I följande sekvens beskrivs det nya användarflödet för Graph API-omfång:

  1. Den nya användaren loggar in i appen för första gången.
  2. Användaren samtycker till att använda appen i Användargränssnittet för Azure-medgivande.
  3. Användaren kommer åt en komponentsida som begär Graph API-data för första gången.
  4. Användaren omdirigeras till användargränssnittet för Azure-medgivande för att samtycka till Graph API-omfång.
  5. Användardata från Graph API returneras.

Om du föredrar att omfångsetablering (medgivande för Graph API-omfång) sker vid den första inloggningen anger du omfången för MSAL-autentisering som standardomfattningar för åtkomsttoken i Program filen:

+ var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
+     .Get<List<string>>() ?? [ "user.read" ];

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);

+   foreach (var scope in scopes)
+   {
+       options.ProviderOptions.DefaultAccessTokenScopes.Add(scope);
+   }
});

Viktigt!

Se avsnittet DefaultAccessTokenScopes kontra AdditionalScopesToConsent för en förklaring av varför den tidigare koden använder DefaultAccessTokenScopes för att lägga till omfattningarna i stället för AdditionalScopesToConsent.

När föregående ändringar görs i appen antar användarflödet följande sekvens:

  1. Den nya användaren loggar in i appen för första gången.
  2. Användaren samtycker till att använda appens och Graph API-omfången i Azure-medgivandegränssnittet.
  3. Användaren kommer åt en komponentsida som begär Graph API-data för första gången.
  4. Användardata från Graph API returneras.

När du testar med Graph API lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testningen. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Anpassa användarkrav med ett namngivet HttpClient

I följande exempel skapar appen mobiltelefonnummer och kontorsplatsanspråk för användaren från deras ME-ID-användarprofils data. Appen måste ha User.Read Graph API-omfånget konfigurerat i ME-ID. Testanvändarkonton i ME-ID kräver en inmatning för mobiltelefonnumret och kontorsplatsen, vilka kan läggas till i användarprofilerna via Azure-portalen.

Om du inte redan har lagt UserInfo till klassen i appen genom att följa riktlinjerna tidigare i den här artikeln lägger du till följande klass och anger de nödvändiga användarprofilegenskaperna med JsonPropertyNameAttribute attributet och JSON-namnet som används av ME-ID. I följande exempel konfigureras egenskaper för användarens mobiltelefonnummer och kontorsplats.

UserInfo.cs:

using System.Text.Json.Serialization;

namespace BlazorSample;

public class UserInfo
{
    [JsonPropertyName("mobilePhone")]
    public string? MobilePhone { get; set; }

    [JsonPropertyName("officeLocation")]
    public string? OfficeLocation { get; set; }
}

I följande anpassade användarkontofabrik:

  • En ILogger (logger) ingår för enkelhetens skull om du vill logga information eller fel i CreateUserAsync metoden.
  • Om en AccessTokenNotAvailableException utlöses omdirigeras användaren till identitetsprovidern för att logga in på sitt konto. Ytterligare eller olika åtgärder kan vidtas när begäran om en åtkomsttoken misslyckas. Appen kan till exempel logga AccessTokenNotAvailableException och skapa ett supportärende för ytterligare undersökning.
  • Ramverket RemoteUserAccount representerar användarens konto. Om appen kräver en anpassad användarkontoklass som utökar RemoteUserAccountbyter du den anpassade användarkontoklassen mot RemoteUserAccount i följande kod.

CustomAccountFactory.cs:

using System.Net.Http.Json;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;

public class CustomAccountFactory(IAccessTokenProviderAccessor accessor,
        IHttpClientFactory clientFactory,
        ILogger<CustomAccountFactory> logger)
    : AccountClaimsPrincipalFactory<RemoteUserAccount>(accessor)
{
    private readonly ILogger<CustomAccountFactory> logger = logger;
    private readonly IHttpClientFactory clientFactory = clientFactory;

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        RemoteUserAccount 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)
            {
                try
                {
                    var client = clientFactory.CreateClient("GraphAPI");

                    var userInfo = await client.GetFromJsonAsync<UserInfo>("me");

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

        return initialUser;
    }
}

MSAL-autentiseringen är konfigurerad för att använda en anpassad användarkontofabrik. Börja med att bekräfta att Program filen använder Microsoft.AspNetCore.Components.WebAssembly.Authentication namnområdet:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

I Program-filen, hitta anropet till AddMsalAuthentication-tilläggsmetoden. Uppdatera koden till följande, vilket inkluderar ett anrop till AddAccountClaimsPrincipalFactory som lägger till en huvudfabrik för kontoanspråk med CustomAccountFactory.

Om appen använder en anpassad användarkontoklass som utökar RemoteUserAccountbyter du appens anpassade användarkontoklass mot RemoteUserAccount i följande kod.

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

Föregående exempel är för en app som använder ME-ID autentisering med MSAL. Liknande mönster finns för OIDC- och API-autentisering. Mer information finns i exemplen i avsnittet Anpassa användaren med nyttolastanspråk i artikeln ASP.NET Core Blazor WebAssembly ytterligare säkerhetsscenarier .

Du kan använda följande UserClaims komponent för att studera användarens anspråk när användaren har autentiserats med ME-ID:

UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}
else
{
    <p>No claims found.</p>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        claims = user.Claims;
    }
}

Lägg till en länk till komponentens sida i komponenten NavMenu (Layout/NavMenu.razor):

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user-claims">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Claims
    </NavLink>
</div>

När du testar med Graph API lokalt rekommenderar vi att du använder en ny InPrivate/incognito-webbläsarsession för varje test för att förhindra att kvardröjande cookies stör testningen. Mer information finns i Secure an ASP.NET Core Blazor WebAssembly standalone app with Microsoft Entra ID.

Tilldela användare till en appregistrering med eller utan app-roller

Du kan lägga till användare i en appregistrering och tilldela roller till användare med följande steg i Azure-portalen.

Om du vill lägga till en användare väljer du Användare från det ME-ID området i Azure-portalen:

  1. Välj Ny användare>Skapa ny användare.
  2. Använd mallen Skapa användare .
  3. Ange användarens information i området Identity .
  4. Du kan generera ett första lösenord eller tilldela ett första lösenord som användaren ändrar när de loggar in för första gången. Om du använder lösenordet som genererats av portalen ska du anteckna det nu.
  5. Välj Skapa för att skapa användaren. När Skapa nytt användargränssnitt stängs väljer du Uppdatera för att uppdatera användarlistan och visa den nya användaren.
  6. I exemplen i den här artikeln tilldelar du ett mobiltelefonnummer till den nya användaren genom att välja deras namn i användarlistan, välja Egenskaper och redigera kontaktinformationen för att ange ett mobiltelefonnummer.

Så här tilldelar du användare till appen utan approller:

  1. I det ME-ID området i Azure-portalen öppnar du Företagsprogram.
  2. Välj appen i listan.
  3. Välj Användare och grupper.
  4. Välj Lägg till användare/grupp.
  5. Välj en användare.
  6. Välj Tilldela knappen.

Så här tilldelar du användare till appen med roller för appen:

  1. Lägg till roller i appens registrering i Azure-portalen enligt vägledningen i ASP.NET Core Blazor WebAssembly med Microsoft Entra ID-grupper och roller.
  2. I det ME-ID området i Azure-portalen öppnar du Företagsprogram.
  3. Välj appen i listan.
  4. Välj Användare och grupper.
  5. Välj Lägg till användare/grupp.
  6. Välj en användare och välj deras roll för åtkomst till appen. Flera roller tilldelas en användare genom att upprepa processen med att lägga till användaren i appen tills alla roller för en användare har tilldelats. Användare med flera roller visas en gång för varje tilldelad roll i listan Användare och grupper med användare för appen.
  7. Välj Tilldela knappen.

DefaultAccessTokenScopes jämfört med AdditionalScopesToConsent

Exemplen i den här artikeln etablerar Graph API-omfång med DefaultAccessTokenScopes, inte AdditionalScopesToConsent.

AdditionalScopesToConsent används inte eftersom det inte går att etablera Graph API-omfång för användare när de loggar in på appen för första gången med MSAL via azure-medgivandegränssnittet. När användaren försöker komma åt Graph API för första gången med Graph SDK konfronteras de med ett undantag:

Microsoft.Graph.Models.ODataErrors.ODataError: Access token is empty.

När en användare etablerar Graph API-omfång som tillhandahålls via DefaultAccessTokenScopeskan appen använda AdditionalScopesToConsent för en efterföljande användarinloggning. Att ändra appkod innebär dock inte någon mening för en produktionsapp som kräver regelbundet tillägg av nya användare med delegerade åtkomstomfång eller tillägg av nya delegerade Graph API-åtkomstomfång i appen.

Föregående diskussion om hur du etablerar omfång för Graph API-åtkomst när användaren först loggar in i appen gäller endast för:

  • Appar som använder Graph SDK.
  • Appar som använder ett namn HttpClient för Graph API-åtkomst som ber användarna att samtycka till Graph-omfång vid den första inloggningen till appen.

När du använder ett namngivet HttpClient som inte ber användarna att godkänna omfattningar för Graph vid den första inloggningen omdirigeras användarna till Azure-samtyckesgränssnittet för omfattningar i Graph API när de först begär åtkomst till Graph API via den förkonfigurerade DelegatingHandler med namnet HttpClient. När Graph-omfång inte godkänns från början med den namngivna HttpClient-metoden, anropas varken DefaultAccessTokenScopes eller AdditionalScopesToConsent av appen. Mer information finns i den namngivna HttpClient täckningen i den här artikeln.

Värdbaserade Blazor WebAssembly lösningar

Exemplen i den här artikeln gäller användning av Graph SDK eller ett namngivet HttpClient med Graph API direkt från en fristående Blazor WebAssembly app eller direkt från Client appen för en värdbaserad Blazor WebAssemblylösning. Ett annat scenario som inte omfattas av den här artikeln är att en Client app av en värdbaserad lösning anropar Server lösningens app via webb-API:et Server , och sedan använder appen Graph SDK/API för att anropa Microsoft Graph och returnera data till Client appen. Även om det här är en metod som stöds omfattas den inte av den här artikeln. Om du vill använda den här metoden:

  • Följ vägledningen i Anropa ett webb-API från en ASP.NET Core-app Blazor för webb-API-aspekterna för att utfärda begäranden till Server appen från Client appen och returnera data till Client appen.
  • Följ riktlinjerna i den primära Microsoft Graph-dokumentationen för att använda Graph SDK med en typisk ASP.NET Core-app, som i det här scenariot är Server lösningens app. Om du använder Blazor WebAssembly projektmallen för att skapa den värdbaserade Blazor WebAssembly lösningen (ASP.NET Core Hosted/-h|--hosted) med organisationsauktorisering (enskild organisation/SingleOrg eller flera organisationer/MultiOrg) och Microsoft Graph-alternativet (Microsofts identitetsplattform>Anslutna tjänster>Lägg till Microsoft Graph-behörigheter i Visual Studio eller --calls-graph alternativet med .NET CLI-kommandot dotnet new ), Server appen för lösningen är konfigurerad för att använda Graph SDK när lösningen skapas från projektmallen.

Ytterligare resurser

Allmän vägledning

  • Microsoft Graph-dokumentation
  • Microsoft Graph-exempelappBlazor WebAssembly: Det här exemplet visar hur du använder Microsoft Graph .NET SDK för att komma åt data i Office 365 från Blazor WebAssembly appar.
  • Skapa .NET-appar med Microsoft Graph-handledning och Exempel på Microsoft Graph ASP.NET Core-app: Dessa resurser är mest lämpliga för värdbaseradeBlazor WebAssembly lösningar, där Server appen är konfigurerad för att få åtkomst till Microsoft Graph som en typisk ASP.NET Core-app på uppdrag av appen. Appen Client använder webb-API för att göra begäranden till Server appen för Graph-data. Även om dessa resurser inte gäller direkt för att anropa Graph från appar på klientsidanBlazor WebAssembly , är ME-ID appkonfiguration och Microsoft Graph-kodningsmetoder i de länkade resurserna relevanta för fristående Blazor WebAssembly appar och bör konsulteras för allmänna metodtips.

Säkerhetsvägledning