ASP.NET Core ile Graph API kullanma Blazor WebAssembly

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin ASP.NET Core 8.0 sürümüne bakın.

Bu makalede, uygulamaların Microsoft Bulut hizmeti kaynaklarına erişmesine olanak tanıyan, dolu bir RESTweb API'si olan uygulamalarda Microsoft Graph Blazor WebAssembly API'sini nasıl kullanacağınız açıklanmaktadır.

Uygulamalarda Microsoft Graph Blazor ile doğrudan etkileşimde bulunmaya yönelik iki yaklaşım vardır:

  • Graph SDK'sı: Microsoft Graph SDK'ları, Microsoft Graph'a erişen yüksek kaliteli, verimli ve dayanıklı uygulamalar derlemeyi basitleştirmek için tasarlanmıştır. Bu yaklaşımı benimsemek için bu makalenin üst kısmındaki Grafik SDK'sı düğmesini seçin.

  • Graph API ile HttpClient olarak adlandırılmış: Adlandırılmış bir , HttpClient doğrudan Graph API'sine web API'si istekleri gönderebilir. Bu yaklaşımı benimsemek için bu makalenin üst kısmındaki Named HttpClient with Graph API düğmesini seçin.

Bu makaledeki kılavuz, birincil Microsoft Graph belgelerinin ve diğer Microsoft belge kümelerindeki ek Azure güvenlik kılavuzunun yerini almak için tasarlanmamıştır. Microsoft Graph'i üretim ortamında uygulamadan önce bu makalenin Ek kaynaklar bölümündeki güvenlik kılavuzunu değerlendirin. Uygulamalarınızın saldırı yüzeyi alanını sınırlamak için Microsoft'un tüm en iyi uygulamalarını izleyin.

Önemli

Bu makalede açıklanan senaryolar, AAD B2C'yi değil Kimlik sağlayıcısı olarak Microsoft Entra'yı (ME-ID) kullanmak için geçerlidir. Microsoft Graph'ı bir istemci tarafı Blazor WebAssembly uygulaması ve AAD B2C kimlik sağlayıcısı ile kullanmak şu anda desteklenmiyor.

Barındırılan Blazor WebAssembly bir uygulamanın kullanılması desteklenir. Burada Server uygulama, web API'si aracılığıyla uygulamaya Graph verileri sağlamak için Graph SDK/API'sini Client kullanır. Daha fazla bilgi için bu makalenin Barındırılan Blazor WebAssembly çözümler bölümüne bakın.

Bu makaledeki örneklerde yeni .NET/C# özelliklerinden yararlanılmıştır. .NET 7 veya önceki sürümleriyle örnekleri kullanırken küçük değişiklikler yapılması gerekir. Ancak, Microsoft Graph ile etkileşime yönelik metin ve kod örnekleri, ASP.NET Core'un tüm sürümleri için aynıdır.

Aşağıdaki kılavuz Microsoft Graph v5 için geçerlidir.

Uygulamalarda kullanılmak üzere Microsoft Graph SDK'sı Blazor, Microsoft Graph .NET İstemci Kitaplığı olarak adlandırılır.

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada aşağıdaki paket başvurularını gerektirir:

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada veya barındırılan Blazor WebAssembly çözümün Client uygulamasında aşağıdaki paket başvurularını gerektirir:

Not

.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri)paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.

Azure portalının ME-ID alanına Microsoft Graph API kapsamlarını ekledikten sonra, Aşağıdaki uygulama ayarları yapılandırmasını dosyaya wwwroot/appsettings.json ekleyin. Bu yapılandırma, Graph sürümü ve kapsamları içeren Graph temel URL'sini içerir. Aşağıdaki örnekte, bu makalenin User.Read sonraki bölümlerinde yer alan örnekler için kapsam belirtilmiştir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} MS Graph API'sinin sürümüdür (örneğin: v1.0).

Aşağıdaki GraphClientExtensions sınıfı tek başına uygulamaya ekleyin. Kapsamlar yönteminde Scopes öğesinin AccessTokenRequestOptions özelliğine AuthenticateRequestAsync sağlanır.

Barındırılan çözümünBlazor WebAssembly tek başına uygulamasına veya Client uygulamasına aşağıdaki GraphClientExtensions sınıfı ekleyin. Kapsamlar yönteminde Scopes öğesinin AccessTokenRequestOptions özelliğine AuthenticateRequestAsync sağlanır.

Erişim belirteci alınmazsa, aşağıdaki kod Graph istekleri için taşıyıcı yetkilendirme üst bilgisi ayarlamaz.

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[]>()
                });

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

Program dosyasına Graph istemci hizmetlerini ve yapılandırmasını uzantı yöntemiyle AddGraphClient ekleyin:

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

builder.Services.AddGraphClient(baseUrl, scopes);

Graph SDK'sını kullanarak bir bileşenden Graph API'sini çağırma

Aşağıdaki GraphExample bileşen, kullanıcının ME-ID profil verilerini almak ve cep telefonu numarasını görüntülemek için eklenen GraphServiceClient öğesini kullanır. ME-ID'de oluşturduğunuz tüm test kullanıcıları için kullanıcının ME-ID profiline Azure portalında bir cep telefonu numarası verdiğinizden emin olun.

GraphExample.razor:

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

<h1>Microsoft Graph Component Example</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();
    }
}

Graph SDK'sı ile yerel olarak test yaparken, kalanların cookietestlere müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Graph SDK'sını kullanarak kullanıcı taleplerini özelleştirme

Aşağıdaki örnekte uygulama, ME-ID kullanıcı profili verilerinden bir kullanıcı için cep telefonu numarası ve ofis konumu talepleri oluşturur. Uygulamanın ME-ID'de yapılandırılmış Graph API kapsamı olmalıdır User.Read . Bu senaryoya yönelik tüm test kullanıcılarının ME-ID profilinde azure portalı aracılığıyla eklenebilen bir cep telefonu numarasına ve ofis konumuna sahip olması gerekir.

Aşağıdaki özel kullanıcı hesabı fabrikasında:

  • ILogger Yöntemdeki bilgileri veya hataları CreateUserAsync günlüğe kaydetmek istemeniz durumunda kolaylık sağlamak için bir (logger) eklenir.
  • bir AccessTokenNotAvailableException oluşturulursa, kullanıcı kendi hesabında oturum açmak için kimlik sağlayıcısına yönlendirilir. Erişim belirteci istendiğinde ek veya farklı eylemler yapılabilir. Örneğin, uygulama daha fazla araştırma için öğesini günlüğe AccessTokenNotAvailableException kaydedebilir ve bir destek bileti oluşturabilir.
  • Çerçeveler RemoteUserAccount kullanıcının hesabını temsil eder. Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı gerektiriyorsa, aşağıdaki kodda için özel kullanıcı hesabı sınıfınızı RemoteUserAccount değiştirin.

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;

namespace BlazorSample;

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 = 
        config.GetSection("MicrosoftGraph")["BaseUrl"];

    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;
    }
}

MSAL kimlik doğrulamasını özel kullanıcı hesabı fabrikasını kullanacak şekilde yapılandırın.

Program Dosyanın ad alanını Microsoft.AspNetCore.Components.WebAssembly.Authentication kullandığını onaylayın:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Bu bölümdeki örnek, dosyadaki bölüm aracılığıyla uygulama yapılandırmasından sürüm ve kapsamlarla temel URL'yi wwwroot/appsettings.json okuma yaklaşımını MicrosoftGraph temel alır. Bu makalenin Program önceki bölümlerinde yer alan yönergeleri izleyerek dosyada aşağıdaki satırların zaten mevcut olması gerekir:

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

builder.Services.AddGraphClient(baseUrl, scopes);

Program dosyasında uzantı yöntemine yapılan çağrıyı AddMsalAuthentication bulun. ile bir hesap talep sorumlusu fabrikası ekleyen bir çağrısı AddAccountClaimsPrincipalFactory içeren kodu aşağıdaki şekilde güncelleştirin CustomAccountFactory.

Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı kullanıyorsa, aşağıdaki kodda için özel kullanıcı hesabı sınıfını RemoteUserAccount değiştirin.

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

Kullanıcı ME-ID ile kimlik doğrulamasından geçtikten sonra kullanıcının taleplerini incelemek için aşağıdaki UserClaims bileşeni kullanabilirsiniz:

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;
    }
}

Graph SDK'sı ile yerel olarak test yaparken, kalanların cookietestlere müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Aşağıdaki kılavuz Microsoft Graph v4 için geçerlidir. Bir uygulamayı SDK v4'ten v5'e yükseltiyorsanız Microsoft Graph .NET SDK v5 değişiklik günlüğü ve yükseltme kılavuzuna bakın.

Uygulamalarda kullanılmak üzere Microsoft Graph SDK'sı Blazor, Microsoft Graph .NET İstemci Kitaplığı olarak adlandırılır.

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada aşağıdaki paket başvurularını gerektirir:

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada veya barındırılan Blazor WebAssembly çözümün Client uygulamasında aşağıdaki paket başvurularını gerektirir:

Not

.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri)paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.

Azure portalının ME-ID alanına Microsoft Graph API kapsamlarını ekledikten sonra, Aşağıdaki uygulama ayarları yapılandırmasını dosyaya wwwroot/appsettings.json ekleyin. Bu yapılandırma, Graph sürümü ve kapsamları içeren Graph temel URL'sini içerir. Aşağıdaki örnekte, bu makalenin User.Read sonraki bölümlerinde yer alan örnekler için kapsam belirtilmiştir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} MS Graph API'sinin sürümüdür (örneğin: v1.0).

Aşağıdaki GraphClientExtensions sınıfı tek başına uygulamaya ekleyin. Kapsamlar yönteminde Scopes öğesinin AccessTokenRequestOptions özelliğine AuthenticateRequestAsync sağlanır. , IHttpProvider.OverallTimeout Microsoft Graph'tan yanıt almak için daha fazla zaman tanımak için varsayılan 100 saniye değerinden HttpClient 300 saniyeye uzatılır.

Barındırılan çözümünBlazor WebAssembly tek başına uygulamasına veya Client uygulamasına aşağıdaki GraphClientExtensions sınıfı ekleyin. Kapsamlar yönteminde Scopes öğesinin AccessTokenRequestOptions özelliğine AuthenticateRequestAsync sağlanır. , IHttpProvider.OverallTimeout Microsoft Graph'tan yanıt almak için daha fazla zaman tanımak için varsayılan 100 saniye değerinden HttpClient 300 saniyeye uzatılır.

Erişim belirteci alınmazsa, aşağıdaki kod Graph istekleri için taşıyıcı yetkilendirme üst bilgisi ayarlamaz.

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()
        {
        }
    }
}

Program dosyasına Graph istemci hizmetlerini ve yapılandırmasını uzantı yöntemiyle AddGraphClient ekleyin:

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

builder.Services.AddGraphClient(baseUrl, scopes);

Graph SDK'sını kullanarak bir bileşenden Graph API'sini çağırma

Aşağıdaki GraphExample bileşen, kullanıcının ME-ID profil verilerini almak ve cep telefonu numarasını görüntülemek için eklenen GraphServiceClient öğesini kullanır. ME-ID'de oluşturduğunuz tüm test kullanıcıları için kullanıcının ME-ID profiline Azure portalında bir cep telefonu numarası verdiğinizden emin olun.

GraphExample.razor:

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

<h1>Microsoft Graph Component Example</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();
    }
}

Graph SDK'sı ile yerel olarak test yaparken, kalanların cookietestlere müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Graph SDK'sını kullanarak kullanıcı taleplerini özelleştirme

Aşağıdaki örnekte uygulama, ME-ID kullanıcı profili verilerinden bir kullanıcı için cep telefonu numarası ve ofis konumu talepleri oluşturur. Uygulamanın ME-ID'de yapılandırılmış Graph API kapsamı olmalıdır User.Read . Bu senaryoya yönelik tüm test kullanıcılarının ME-ID profilinde azure portalı aracılığıyla eklenebilen bir cep telefonu numarasına ve ofis konumuna sahip olması gerekir.

Aşağıdaki özel kullanıcı hesabı fabrikasında:

  • ILogger Yöntemdeki bilgileri veya hataları CreateUserAsync günlüğe kaydetmek istemeniz durumunda kolaylık sağlamak için bir (logger) eklenir.
  • bir AccessTokenNotAvailableException oluşturulursa, kullanıcı kendi hesabında oturum açmak için kimlik sağlayıcısına yönlendirilir. Erişim belirteci istendiğinde ek veya farklı eylemler yapılabilir. Örneğin, uygulama daha fazla araştırma için öğesini günlüğe AccessTokenNotAvailableException kaydedebilir ve bir destek bileti oluşturabilir.
  • Çerçeveler RemoteUserAccount kullanıcının hesabını temsil eder. Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı gerektiriyorsa, aşağıdaki kodda için özel kullanıcı hesabı sınıfınızı RemoteUserAccount değiştirin.

CustomAccountFactory.cs:

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<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;
    }
}

MSAL kimlik doğrulamasını özel kullanıcı hesabı fabrikasını kullanacak şekilde yapılandırın.

Program Dosyanın ad alanını Microsoft.AspNetCore.Components.WebAssembly.Authentication kullandığını onaylayın:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Bu bölümdeki örnek, dosyadaki bölüm aracılığıyla uygulama yapılandırmasından sürüm ve kapsamlarla temel URL'yi wwwroot/appsettings.json okuma yaklaşımını MicrosoftGraph temel alır. Bu makalenin Program önceki bölümlerinde yer alan yönergeleri izleyerek dosyada aşağıdaki satırların zaten mevcut olması gerekir:

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

builder.Services.AddGraphClient(baseUrl, scopes);

Program dosyasında uzantı yöntemine yapılan çağrıyı AddMsalAuthentication bulun. ile bir hesap talep sorumlusu fabrikası ekleyen bir çağrısı AddAccountClaimsPrincipalFactory içeren kodu aşağıdaki şekilde güncelleştirin CustomAccountFactory.

Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı kullanıyorsa, aşağıdaki kodda için özel kullanıcı hesabı sınıfını RemoteUserAccount değiştirin.

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

Kullanıcı ME-ID ile kimlik doğrulamasından geçtikten sonra kullanıcının taleplerini incelemek için aşağıdaki UserClaims bileşeni kullanabilirsiniz:

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;
    }
}

Graph SDK'sı ile yerel olarak test yaparken, kalanların cookietestlere müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Aşağıdaki örneklerde, bir aramayı işlemek üzere kullanıcının cep telefonu numarasını almak veya kullanıcının taleplerini bir cep telefonu numarası talebi ve bir ofis konumu talebi içerecek şekilde özelleştirmek için Graph API çağrıları için adlı HttpClient bir kullanılır.

Örnekler, tek başına Blazor WebAssembly uygulama için Microsoft.Extensions.Http paket başvurusu gerektirir.

Örnekler, tek başına Blazor WebAssembly uygulama veya barındırılan Blazor WebAssembly bir çözümün Client uygulaması için Microsoft.Extensions.Http paket başvurusu gerektirir.

Not

.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri)paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.

Azure portalının ME-ID alanına Microsoft Graph API kapsamlarını ekledikten sonra, dosyaya wwwroot/appsettings.json aşağıdaki uygulama ayarları yapılandırmasını ekleyin. Aşağıdaki örnekte kapsam, bu makalenin User.Read sonraki bölümlerindeki örneklerle eşleşecek şekilde belirtilmiştir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} MS Graph API'sinin sürümüdür (örneğin: v1.0).

Graph API ile çalışmak için dosyasında aşağıdaki GraphAuthorizationMessageHandler sınıf ve proje yapılandırmasını Program oluşturun. Temel URL ve kapsamlar yapılandırmadan işleyiciye sağlanır.

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: new[] { config.GetSection("MicrosoftGraph")["BaseUrl"] ?? 
                string.Empty },
            scopes: config.GetSection("MicrosoftGraph:Scopes").Get<List<string>>());
    }
}

Program Dosyasında, graph API'sinin adlandırılmış öğesini HttpClient yapılandırın:

builder.Services.AddTransient<GraphAuthorizationMessageHandler>();

builder.Services.AddHttpClient("GraphAPI",
        client => client.BaseAddress = new Uri(
            builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"]))
    .AddHttpMessageHandler<GraphAuthorizationMessageHandler>();

Yukarıdaki örnekte , GraphAuthorizationMessageHandlerDelegatingHandler için AddHttpMessageHandlergeçici bir hizmet olarak kaydedilir. kendi DI kapsamlarını yöneten için IHttpClientFactorygeçici kayıt önerilir. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Adlı bir bileşeni kullanarak bir bileşenden Graph API'lerini çağırma HttpClient

sınıfı, UserInfo.cs gerekli kullanıcı profili özelliklerini özniteliği ve JSME-ID tarafından kullanılan ON adıyla JsonPropertyNameAttribute belirler. Aşağıdaki örnek, kullanıcının cep telefonu numarası ve ofis konumu için özellikleri ayarlar.

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; }
}

Aşağıdaki GraphExample bileşende, graph API'sinin kullanıcının profil verilerine yönelik bir istek göndermesi için bir HttpClient oluşturulur. Kaynak me (/me), Graph API isteğinin sürümüyle temel URL'ye eklenir. JSGraph tarafından döndürülen ON verileri, sınıf özelliklerinde seri durumdan UserInfo çıkarılır. Aşağıdaki örnekte, cep telefonu numarası alınır. İsterseniz kullanıcının ME-ID profil ofisi konumunu eklemek için benzer kod ekleyebilirsiniz.userInfo.OfficeLocation Erişim belirteci isteği başarısız olursa, kullanıcı yeni bir erişim belirteci için uygulamada oturum açmak üzere yeniden yönlendirilir.

GraphExample.razor:

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


<h1>Microsoft Graph Component Example</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();
        }
    }
}

Graph API'siyle yerel olarak test yaparken, kalanların cookieteste müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Kullanıcı taleplerini adlandırılmış bir ad kullanarak özelleştirme HttpClient

Aşağıdaki örnekte uygulama, ME-ID kullanıcı profilinin verilerinden kullanıcı için cep telefonu numarası ve ofis konumu talepleri oluşturur. Uygulamanın ME-ID'de yapılandırılmış Graph API kapsamı olmalıdır User.Read . ME-ID'deki kullanıcı hesaplarını test etmek için cep telefonu numarası ve ofis konumu için azure portalı aracılığıyla kullanıcı profillerine eklenebilecek bir giriş gerekir.

Bu makalenin önceki bölümlerinde yer UserInfo alan yönergeleri izleyerek sınıfı uygulamaya eklemediyseniz, aşağıdaki sınıfı ekleyin ve gerekli kullanıcı profili özelliklerini ME-ID tarafından kullanılan özniteliği ve JSON adıyla JsonPropertyNameAttribute belirleyin. Aşağıdaki örnek, kullanıcının cep telefonu numarası ve ofis konumu için özellikleri ayarlar.

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; }
}

Aşağıdaki özel kullanıcı hesabı fabrikasında:

  • ILogger Yöntemdeki bilgileri veya hataları CreateUserAsync günlüğe kaydetmek istemeniz durumunda kolaylık sağlamak için bir (logger) eklenir.
  • bir AccessTokenNotAvailableException oluşturulursa, kullanıcı kendi hesabında oturum açmak için kimlik sağlayıcısına yönlendirilir. Erişim belirteci istendiğinde ek veya farklı eylemler yapılabilir. Örneğin, uygulama daha fazla araştırma için öğesini günlüğe AccessTokenNotAvailableException kaydedebilir ve bir destek bileti oluşturabilir.
  • Çerçeveler RemoteUserAccount kullanıcının hesabını temsil eder. Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı gerektiriyorsa, aşağıdaki kodda için özel kullanıcı hesabı sınıfını RemoteUserAccount değiştirin.

CustomAccountFactory.cs:

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

namespace BlazorSample;

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 kimlik doğrulaması, özel kullanıcı hesabı fabrikasını kullanacak şekilde yapılandırılmıştır. Dosyanın ad alanını kullandığını Microsoft.AspNetCore.Components.WebAssembly.Authentication onaylayarak Program başlayın:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

Program dosyasında uzantı yöntemine yapılan çağrıyı AddMsalAuthentication bulun. ile bir hesap talep sorumlusu fabrikası ekleyen bir çağrısı AddAccountClaimsPrincipalFactory içeren kodu aşağıdaki şekilde güncelleştirin CustomAccountFactory.

Uygulama genişleten RemoteUserAccountbir özel kullanıcı hesabı sınıfı kullanıyorsa, aşağıdaki kodda uygulamanızın özel kullanıcı hesabı sınıfını ile RemoteUserAccount değiştirin.

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

Yukarıdaki örnek, MSAL ile ME-ID kimlik doğrulaması kullanan bir uygulamaya yöneliktir. OIDC ve API kimlik doğrulaması için benzer desenler vardır. Daha fazla bilgi için, ASP.NET Core Blazor WebAssembly ek güvenlik senaryoları makalesinin Yük talebiyle kullanıcıyı özelleştirme bölümündeki örneklere bakın.

Kullanıcı ME-ID ile kimlik doğrulamasından geçtikten sonra kullanıcının taleplerini incelemek için aşağıdaki UserClaims bileşeni kullanabilirsiniz:

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;
    }
}

Graph API'siyle yerel olarak test yaparken, kalanların cookieteste müdahale etmesini önlemek için her test için yeni bir InPrivate/Gizli tarayıcı oturumu kullanmanızı öneririz. Daha fazla bilgi için bkz. Microsoft Entra ID ile ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama.

Barındırılan Blazor WebAssembly çözümler

Bu makaledeki örnekler, Doğrudan tek başına Blazor WebAssembly bir uygulamadan veya doğrudan barındırılanBlazor WebAssembly bir çözümün uygulamasından Graph SDK'sını veya graph API'siyle Client adlandırılmış HttpClient bir uygulamayı kullanmayla ilgilidir. Bu makalenin kapsamında yer almayan ek bir senaryo, barındırılan bir Client çözüm uygulamasının web API'si aracılığıyla çözümün uygulamasını çağırmasına Server yöneliktir ve ardından Server uygulama Microsoft Graph'ı çağırmak ve uygulamaya veri döndürmek için Graph SDK'sını/API'sini Client kullanır. Bu desteklenen bir yaklaşım olsa da, bu makalede ele alınmıyor. Bu yaklaşımı benimsemek istiyorsanız:

  • Uygulamadan uygulamaya istek gönderme ve uygulamaya veri Client döndürme konusunda web API'sinin özellikleri için ASP.NET Core Blazor uygulamasındanServer web API'sini Client çağırma sayfasındaki yönergeleri izleyin.
  • Graph SDK'sını bu senaryoda Server çözümün uygulaması olan tipik bir ASP.NET Core uygulamasıyla kullanmak için birincil Microsoft Graph belgelerindeki yönergeleri izleyin. Kuruluş yetkilendirmesi (tek kuruluş/ veya birden çok kuruluşMultiOrg/) ile barındırılan Blazor WebAssembly çözümü (ASP.NET Temel Barındırılan/-h|--hosted) ve Microsoft Graph seçeneğini (Microsoft kimlik platformu> Bağlan ed Services>Visual Studio'da Microsoft Graph izinleri eklemek için proje şablonunu kullanırsanız veya --calls-graphBlazor WebAssemblySingleOrg seçeneğine dotnet new tıklayın. Server Çözüm uygulaması, proje şablonundan oluşturulduğunda Graph SDK'sını kullanacak şekilde yapılandırılır.

Ek kaynaklar

Genel kılavuz

Güvenlik kılavuzu