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 .NET 8 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 8 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'ın istemci tarafı Blazor WebAssembly bir uygulamayla ve AAD B2C kimlik sağlayıcısıyla kullanılması şu anda desteklenmemektedir çünkü uygulama istemci tarafı Blazor uygulamasında güvenli hale getirilmeyecek bir istemci gizli dizisi gerektirebilir. AAD B2C tek başına Blazor WebAssembly uygulaması için Graph API'sini kullanın, kullanıcılar adına Graph API'sine erişmek için bir arka uç sunucusu (web) API'sini oluşturun. İstemci tarafı uygulaması, microsoft Graph'a güvenli bir şekilde erişmek ve verileri istemci tarafı Blazor uygulamasına döndürmek için kullanıcıların kimliğini doğrular ve web API'sini çağırma yetkisi verir. İstemci gizli dizisi, istemcideki uygulamada değil sunucu tabanlı web API'sinde Blazor güvenli bir şekilde korunur. İstemci gizli dizisini hiçbir zaman istemci tarafı uygulamasında depolamayın Blazor .

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. Uygulama MSAL kimlik doğrulaması için etkinleştirildiyse, örneğin Microsoft Entra ID ile bir ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama başlığındaki yönergeleri izleyerek uygulamayı oluştururken ilk iki pakete zaten başvurulur.

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada veya barındırılan Blazor WebAssembly bir çözümün Client uygulamasında aşağıdaki paket başvurularını gerektirir. Uygulama MSAL kimlik doğrulaması için etkinleştirildiyse, örneğin Microsoft Entra ID ile bir ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama başlığındaki yönergeleri izleyerek uygulamayı oluştururken ilk iki pakete zaten başvurulur.

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ında, uygulamanın bir kullanıcı adına erişebilmesi gereken Microsoft Graph verileri için temsilci izinleri (kapsamlar) † verin. Bu makaledeki örnekte, uygulamanın kaydı kullanıcı verilerini okumak için temsilci izni içermelidir (Microsoft.Graph>User.ReadAPI izinlerindeki kapsam, Tür: Temsilcili). Kapsam User.Read , kullanıcıların uygulamada oturum açmasına olanak tanır ve uygulamanın oturum açmış kullanıcıların profil ve şirket bilgilerini okumasına olanak tanır. Daha fazla bilgi için bkz. Microsoft kimlik platformu izinlere ve Microsoft Graph izinlerine genel bakış bölümünde izinlere ve onaylara genel bakış.

Not

†Etkiler ve kapsamlar aynı anlama gelir ve güvenlik belgelerinde ve Azure portalında birbirinin yerine kullanılır. Bu makalede Graph API izinlerine başvururken kapsam/kapsamları kullanılmaktadır.

Azure portalında uygulamanın kaydına Microsoft Graph API kapsamlarını ekledikten sonra, uygulamadaki dosyaya wwwroot/appsettings.json , Microsoft Graph sürümü ve kapsamları ile Graph temel URL'sini içeren aşağıdaki uygulama ayarları yapılandırmasını ekleyin. Aşağıdaki örnekte, bu makalenin User.Read sonraki bölümlerinde yer alan örnekler için kapsam belirtilmiştir. Kapsamlar büyük/küçük harfe duyarlı değildir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} Microsoft Graph API'sinin sürümüdür (örneğin: v1.0). Sondaki eğik çizgi gereklidir.

Aşağıda, kimlik sağlayıcısı olarak ME-ID kullanan ve Microsoft Graph için kullanıcı verilerinin (user.readkapsam) okunduğu eksiksiz wwwroot/appsettings.json bir yapılandırma dosyası örneği verilmiştir:

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

Yukarıdaki örnekte yer {TENANT ID} tutucu Dizin (kiracı) kimliği, {CLIENT ID} yer tutucu ise Uygulama (istemci) kimliğidir. 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 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}");
            }
        }
    }
}

Önemli

Yukarıdaki kodun DefaultAccessTokenScopes kapsamları AdditionalScopesToConsenteklemek için yerine neden kullandığını DefaultAccessTokenScopes gösteren bir açıklama için versus AdditionalScopesToConsent bölümüne bakın.

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 UserData 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.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

İpucu

Bir uygulamaya kullanıcı eklemek için, Uygulama rolleri ile veya uygulama rolleri olmadan uygulama kaydına kullanıcı atama bölümüne bakın.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

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. Uygulama MSAL kimlik doğrulaması için etkinleştirildiyse, örneğin Microsoft Entra ID ile bir ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama başlığındaki yönergeleri izleyerek uygulamayı oluştururken ilk iki pakete zaten başvurulur.

Graph SDK örnekleri, tek başına Blazor WebAssembly uygulamada veya barındırılan Blazor WebAssembly bir çözümün Client uygulamasında aşağıdaki paket başvurularını gerektirir. Uygulama MSAL kimlik doğrulaması için etkinleştirildiyse, örneğin Microsoft Entra ID ile bir ASP.NET Core Blazor WebAssembly tek başına uygulamasının güvenliğini sağlama başlığındaki yönergeleri izleyerek uygulamayı oluştururken ilk iki pakete zaten başvurulur.

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ında, uygulamanın bir kullanıcı adına erişebilmesi gereken Microsoft Graph verileri için temsilci izinleri (kapsamlar) † verin. Bu makaledeki örnekte, uygulamanın kaydı kullanıcı verilerini okumak için temsilci izni içermelidir (Microsoft.Graph>User.ReadAPI izinlerindeki kapsam, Tür: Temsilcili). Kapsam User.Read , kullanıcıların uygulamada oturum açmasına olanak tanır ve uygulamanın oturum açmış kullanıcıların profil ve şirket bilgilerini okumasına olanak tanır. Daha fazla bilgi için bkz. Microsoft kimlik platformu izinlere ve Microsoft Graph izinlerine genel bakış bölümünde izinlere ve onaylara genel bakış.

Not

†Etkiler ve kapsamlar aynı anlama gelir ve güvenlik belgelerinde ve Azure portalında birbirinin yerine kullanılır. Bu makalede Graph API izinlerine başvururken kapsam/kapsamları kullanılmaktadır.

Azure portalında uygulamanın kaydına Microsoft Graph API kapsamlarını ekledikten sonra, uygulamadaki dosyaya wwwroot/appsettings.json , Microsoft Graph sürümü ve kapsamları ile Graph temel URL'sini içeren aşağıdaki uygulama ayarları yapılandırmasını ekleyin. Aşağıdaki örnekte, bu makalenin User.Read sonraki bölümlerinde yer alan örnekler için kapsam belirtilmiştir. Kapsamlar büyük/küçük harfe duyarlı değildir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} Microsoft Graph API'sinin sürümüdür (örneğin: v1.0). Sondaki eğik çizgi gereklidir.

Aşağıda, kimlik sağlayıcısı olarak ME-ID kullanan ve Microsoft Graph için kullanıcı verilerinin (user.readkapsam) okunduğu eksiksiz wwwroot/appsettings.json bir yapılandırma dosyası örneği verilmiştir:

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

Yukarıdaki örnekte yer {TENANT ID} tutucu Dizin (kiracı) kimliği, {CLIENT ID} yer tutucu ise Uygulama (istemci) kimliğidir. 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 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()
        {
        }
    }
}

Önemli

Yukarıdaki kodun DefaultAccessTokenScopes kapsamları AdditionalScopesToConsenteklemek için yerine neden kullandığını DefaultAccessTokenScopes gösteren bir açıklama için versus AdditionalScopesToConsent bölümüne bakın.

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 UserData 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.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

İpucu

Bir uygulamaya kullanıcı eklemek için, Uygulama rolleri ile veya uygulama rolleri olmadan uygulama kaydına kullanıcı atama bölümüne bakın.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

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ında, uygulamanın bir kullanıcı adına erişebilmesi gereken Microsoft Graph verileri için temsilci izinleri (kapsamlar) † verin. Bu makaledeki örnekte, uygulamanın kaydı kullanıcı verilerini okumak için temsilci izni içermelidir (Microsoft.Graph>User.ReadAPI izinlerindeki kapsam, Tür: Temsilcili). Kapsam User.Read , kullanıcıların uygulamada oturum açmasına olanak tanır ve uygulamanın oturum açmış kullanıcıların profil ve şirket bilgilerini okumasına olanak tanır. Daha fazla bilgi için bkz. Microsoft kimlik platformu izinlere ve Microsoft Graph izinlerine genel bakış bölümünde izinlere ve onaylara genel bakış.

Not

†Etkiler ve kapsamlar aynı anlama gelir ve güvenlik belgelerinde ve Azure portalında birbirinin yerine kullanılır. Bu makalede Graph API izinlerine başvururken kapsam/kapsamları kullanılmaktadır.

Azure portalında uygulamanın kaydına Microsoft Graph API kapsamlarını ekledikten sonra, uygulamadaki dosyaya wwwroot/appsettings.json , Microsoft Graph sürümü ve kapsamları ile Graph temel URL'sini içeren aşağıdaki uygulama ayarları yapılandırmasını ekleyin. Aşağıdaki örnekte, bu makalenin User.Read sonraki bölümlerinde yer alan örnekler için kapsam belirtilmiştir. Kapsamlar büyük/küçük harfe duyarlı değildir.

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

Yukarıdaki örnekte yer tutucu, {VERSION} Microsoft Graph API'sinin sürümüdür (örneğin: v1.0). Sondaki eğik çizgi gereklidir.

Aşağıda, kimlik sağlayıcısı olarak ME-ID kullanan ve Microsoft Graph için kullanıcı verilerinin (user.readkapsam) okunduğu eksiksiz wwwroot/appsettings.json bir yapılandırma dosyası örneği verilmiştir:

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

Yukarıdaki örnekte yer {TENANT ID} tutucu Dizin (kiracı) kimliği, {CLIENT ID} yer tutucu ise Uygulama (istemci) kimliğidir. 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 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: [ 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"] ?? 
                string.Empty))
    .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 UserData 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.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

İpucu

Bir uygulamaya kullanıcı eklemek için, Uygulama rolleri ile veya uygulama rolleri olmadan uygulama kaydına kullanıcı atama bölümüne bakın.

Aşağıdaki dizi, Graph API kapsamları için yeni kullanıcı akışını açıklar:

  1. Yeni kullanıcı uygulamada ilk kez oturum açar.
  2. Kullanıcı, Uygulamayı Azure onayı kullanıcı arabiriminde kullanmayı kabul eder.
  3. Kullanıcı, Graph API verilerini ilk kez isteyen bir bileşen sayfasına erişir.
  4. Kullanıcı, Graph API kapsamlarına onay vermek için Azure onay kullanıcı arabirimine yönlendirilir.
  5. Graph API kullanıcı verileri döndürülür.

İlk oturum açmada kapsam sağlamanın (Graph API kapsamları için onay) gerçekleşmesini tercih ediyorsanız, MSAL kimlik doğrulaması kapsamlarını dosyada varsayılan erişim belirteci kapsamları olarak sağlayın Program :

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

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

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

Önemli

Yukarıdaki kodun DefaultAccessTokenScopes kapsamları AdditionalScopesToConsenteklemek için yerine neden kullandığını DefaultAccessTokenScopes gösteren bir açıklama için versus AdditionalScopesToConsent bölümüne bakın.

Uygulamada önceki değişiklikler yapıldığında, kullanıcı akışı aşağıdaki sırayı benimser:

  1. Yeni kullanıcı uygulamada ilk kez oturum açar.
  2. Kullanıcı, Azure onayı kullanıcı arabiriminde uygulamayı ve Graph API kapsamlarını kullanmayı kabul eder.
  3. Kullanıcı, Graph API verilerini ilk kez isteyen bir bileşen sayfasına erişir.
  4. Graph API kullanıcı verileri döndürülür.

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

Bileşendeki bileşenin sayfasına NavMenu bir bağlantı ekleyin (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>

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.

Uygulama rolleri olan veya olmayan bir uygulama kaydına kullanıcı atama

Azure portalında aşağıdaki adımlarla bir uygulama kaydına kullanıcı ekleyebilir ve kullanıcılara roller atayabilirsiniz.

Kullanıcı eklemek için Azure portalının ME-ID alanından Kullanıcılar'ı seçin:

  1. Yeni kullanıcı Yeni kullanıcı> oluştur'u seçin.
  2. Kullanıcı oluştur şablonunu kullanın.
  3. Kullanıcının bilgilerini bölgede sağlayın Identity .
  4. İlk parolayı oluşturabilir veya kullanıcının ilk kez oturum açarken değiştirebileceği bir başlangıç parolası atayabilirsiniz. Portal tarafından oluşturulan parolayı kullanıyorsanız, bunu şimdi not edin.
  5. Kullanıcıyı oluşturmak için Oluştur'u seçin. Yeni kullanıcı arabirimi oluştur kapatıldığında Yenile'yi seçerek kullanıcı listesini güncelleştirin ve yeni kullanıcıyı gösterin.
  6. Bu makaledeki örnekler için, kullanıcı listesinden adını seçerek, Özellikler'i seçerek ve iletişim bilgilerini düzenleyerek yeni kullanıcıya bir cep telefonu numarası atayın.

Uygulama rolleri olmadan uygulamaya kullanıcı atamak için:

  1. Azure portalının ME-ID alanında Kurumsal uygulamalar'ı açın.
  2. Listeden uygulamayı seçin.
  3. Kullanıcı ve gruplar'ı seçin.
  4. Kullanıcı/grup ekle'yi seçin.
  5. Bir kullanıcı seçin.
  6. Ata düğmesini seçin.

Uygulamaya uygulama rolleri ile kullanıcı atamak için:

  1. Microsoft Entra Id grupları ve rolleri ile ASP.NET Core'daki Blazor WebAssembly yönergeleri izleyerek Azure portalında uygulamanın kaydına roller ekleyin.
  2. Azure portalının ME-ID alanında Kurumsal uygulamalar'ı açın.
  3. Listeden uygulamayı seçin.
  4. Kullanıcı ve gruplar'ı seçin.
  5. Kullanıcı/grup ekle'yi seçin.
  6. Bir kullanıcı seçin ve uygulamaya erişmek için kendi rolünü seçin. Bir kullanıcının tüm rolleri atanana kadar kullanıcıyı uygulamaya ekleme işlemi yinelenerek kullanıcıya birden çok rol atanır. Birden çok rolü olan kullanıcılar, uygulamanın Kullanıcılar ve gruplar listesinde atanan her rol için bir kez listelenir.
  7. Ata düğmesini seçin.

DefaultAccessTokenScopes ile AdditionalScopesToConsent

Bu makaledeki örnekler Graph API kapsamlarını yerine ile DefaultAccessTokenScopesAdditionalScopesToConsentsağlar.

AdditionalScopesToConsent , Azure onayı kullanıcı arabirimi aracılığıyla MSAL ile uygulamada ilk kez oturum açtıklarında kullanıcılar için Graph API kapsamları sağlayamadığı için kullanılmaz. Kullanıcı Graph SDK'sı ile Graph API'sine ilk kez erişmeye çalıştığında, bir özel durumla karşılaşır:

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

Kullanıcı aracılığıyla DefaultAccessTokenScopessağlanan Graph API kapsamlarını sağladıktan sonra, uygulama sonraki bir kullanıcı oturumu açmak için kullanabilir AdditionalScopesToConsent . Ancak, uygulama kodunu değiştirmek, temsilci Graph kapsamlarına sahip yeni kullanıcıların düzenli aralıklarla eklenmesini veya uygulamaya yeni temsilci Graph API kapsamları eklenmesini gerektiren bir üretim uygulaması için anlamlı değildir.

Kullanıcı uygulamada ilk kez oturum açtığında Graph API erişimi için kapsam sağlamanın önceki tartışması yalnızca şunlar için geçerlidir:

  • Graph SDK'sını benimseyen uygulamalar.
  • Kullanıcılardan uygulamada ilk kez oturum açmalarında Graph kapsamlarına onay vermelerini isteyen Graph API erişimi için adlandırılmış bir ad HttpClient kullanan uygulamalar.

Kullanıcılardan ilk oturum açmalarında Graph kapsamlarına onay vermelerini istemeyen bir ad HttpClient kullanırken, kullanıcılar önceden yapılandırılmış olan adlı HttpClientaracılığıyla Graph API'sine ilk kez erişim istediklerinde Graph APIDelegatingHandler kapsamları için Azure onay kullanıcı arabirimine yönlendirilir. Graph kapsamları başlangıçta adlandırılmış HttpClient yaklaşımla onaylanmamışsa veya DefaultAccessTokenScopesAdditionalScopesToConsent uygulama tarafından çağrılmadığında. Daha fazla bilgi için bu makaledeki adlandırılmış HttpClient kapsam bölümüne bakın.

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