Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Microsoft. Identity.Web, Microsoft Entra ID ile tümleşen ASP.NET Core uygulamalarda kimlik doğrulaması ve yetkilendirme için güvenli varsayılanlar sağlar. Kitaplığın yerleşik güvenlik özelliklerini korurken kimlik doğrulama davranışının birçok yönünü özelleştirebilirsiniz.
Özelleştirilebilir alanları belirleme
| Alan | Özelleştirme Seçenekleri |
|---|---|
| Configuration | Tüm MicrosoftIdentityOptions, OpenIdConnectOptions, JwtBearerOptions özellikleri |
| Etkinlikler | OpenID Connect olayları (OnTokenValidated, OnRedirectToIdentityProvider, vb.) |
| Belirteç Alma | Bağıntı kimlikleri, ek sorgu parametreleri |
| Claims | Özel talepleri ClaimsPrincipal öğesine ekle |
| Kullanıcı Arabirimi | Oturumu kapatma sayfaları ve yeniden yönlendirme davranışı |
| Oturum Açma | Oturum açma ipuçları, domain ipuçları |
Özelleştirme yöntemi seçme
Aşağıdaki tabloda özelleştirebileceğiniz alanlar ve her alanın desteklediği alanlar özetlemektedir.
Seçenekleri özelleştirmek için iki yaklaşımdan birini kullanın:
-
Configure<TOptions>- Seçenekleri kullanılmadan önce yapılandırıyor -
PostConfigure<TOptions>- TümConfigureçağrılardan sonra seçenekleri yapılandırıyor
Yürütme sırası:
Configure → Configure → ... → PostConfigure → PostConfigure → ... → Options used
Kimlik doğrulama seçeneklerini yapılandırma
Bu bölüm, Microsoft.Identity.Web tarafından kullanılan çeşitli kimlik doğrulama seçeneği sınıflarının nasıl yapılandırıldığını gösterir.
Yapılandırma eşlemesini anlama
içindeki "AzureAd" bölüm appsettings.json birden çok sınıfla eşler:
Yapılandırmanızda bu sınıflardan herhangi bir özelliği kullanabilirsiniz.
Desen 1: MicrosoftIdentityOptions'ı yapılandırma
Aşağıdaki kod, MicrosoftIdentityOptions, PII günlüğünü etkinleştirmek, istemci özelliklerini ayarlamak ve token doğrulama parametrelerini ayarlamak için özelleştirilir:
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
// Customize Microsoft Identity options
builder.Services.Configure<MicrosoftIdentityOptions>(options =>
{
// Enable PII logging (development only!)
options.EnablePiiLogging = true;
// Custom client capabilities
options.ClientCapabilities = new[] { "CP1", "CP2" };
// Override token validation parameters
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(5);
});
var app = builder.Build();
Desen 2: OpenIdConnectOptions'ı yapılandırma (Web uygulamaları)
Aşağıdaki kod, yanıt türünü ayarlamak, kapsamlar eklemek ve tanımlama bilgisi ile belirteç doğrulama ayarlarını yapılandırmak üzere bir web uygulaması için özelleştirilir OpenIdConnectOptions :
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
// Customize OpenIdConnect options
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
// Override response type
options.ResponseType = "code id_token";
// Add extra scopes
options.Scope.Add("offline_access");
options.Scope.Add("profile");
// Customize token validation
options.TokenValidationParameters.NameClaimType = "preferred_username";
options.TokenValidationParameters.RoleClaimType = "roles";
// Set redirect URI
options.CallbackPath = "/signin-oidc";
// Configure cookie options
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
});
Desen 3: JwtBearerOptions'ı (Web API'leri) yapılandırma
tr-TR: Aşağıdaki kod, bir web API'si için JwtBearerOptions'yi geçerli kullanıcıları, talep eşlemelerini ve jeton süresi doğrulamasını ayarlamak üzere özelleştirir.
using Microsoft.AspNetCore.Authentication.JwtBearer;
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
// Customize JWT Bearer options
builder.Services.Configure<JwtBearerOptions>(
JwtBearerDefaults.AuthenticationScheme,
options =>
{
// Customize audience validation
options.TokenValidationParameters.ValidAudiences = new[]
{
"api://your-api-client-id",
"https://your-api.com"
};
// Set custom claim mappings
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "roles";
// Customize token validation
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero; // No tolerance
});
Desen 4: Tanımlama Bilgisi seçeneklerini yapılandırma
Aşağıdaki kod, güvenlik ayarları ve son kullanma davranışı dahil olmak üzere uygulamanız için çerez politikası ve kimlik doğrulama seçeneklerini yapılandırıyor.
using Microsoft.AspNetCore.Authentication.Cookies;
// Configure cookie policy
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Lax;
options.Secure = CookieSecurePolicy.Always;
options.HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always;
});
// Configure cookie authentication options
builder.Services.Configure<CookieAuthenticationOptions>(
CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.Cookie.Name = "MyApp.Auth";
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.SlidingExpiration = true;
});
Olay işleyicilerini özelleştirme
OpenID Connect ve JWT Taşıyıcı kimlik doğrulaması, bağlanabileceğiniz olayları kullanıma sunar. Microsoft. Identity.Web kendi olay işleyicilerini ayarlar, bu nedenle yerleşik işlevselliği korumak için özel işleyicilerinizi mevcut işleyicilerle zincirlemeniz gerekir.
Mevcut işleyicileri koruyun
Özel olay işleyicileri eklediğinizde, her zaman önce mevcut işleyiciyi kaydedin ve çağırın. Aşağıdaki örnekte yanlış ve doğru yaklaşımlar gösterilmektedir.
Aşağıdaki kod yanlış bir şekilde Microsoft.Identity.Web işleyicisini üzerine yazar.
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Events.OnTokenValidated = async context =>
{
// Your code - but you LOST the built-in validation!
await Task.CompletedTask;
};
});
Aşağıdaki kod, mevcut işleyiciyle doğru şekilde zincirler:
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
var existingOnTokenValidatedHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
// Call Microsoft.Identity.Web's handler FIRST
await existingOnTokenValidatedHandler(context);
// Then your custom code
// (executes AFTER built-in security checks)
var identity = context.Principal.Identity as ClaimsIdentity;
identity?.AddClaim(new Claim("custom_claim", "custom_value"));
};
});
Yaygın olay senaryolarını uygulama
Belirteç doğrulaması sonrasında özel talepler ekleme
Aşağıdaki kod, bir web API'sinde belirteç doğrulamasından sonra öğesine ClaimsPrincipal özel talepler ekler. Veritabanından kullanıcının bölümünü arar ve e-posta etki alanına göre uygulamaya özgü bir rol atar:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Security.Claims;
builder.Services.Configure<JwtBearerOptions>(
JwtBearerDefaults.AuthenticationScheme,
options =>
{
var existingHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
// Preserve built-in validation
await existingHandler(context);
// Add custom claims
var identity = context.Principal.Identity as ClaimsIdentity;
// Example: Add department claim from database
var userObjectId = context.Principal.FindFirst("oid")?.Value;
if (!string.IsNullOrEmpty(userObjectId))
{
var department = await GetUserDepartment(userObjectId);
identity?.AddClaim(new Claim("department", department));
}
// Example: Add application-specific role
var email = context.Principal.FindFirst("email")?.Value;
if (email?.EndsWith("@admin.com") == true)
{
identity?.AddClaim(new Claim(ClaimTypes.Role, "SuperAdmin"));
}
};
});
Aşağıdaki kod, belirteç doğrulamasından sonra ek kullanıcı profili verilerini almak için Microsoft Graph çağırarak bir web uygulamasına özel talepler ekler:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
var existingHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
// Preserve built-in processing
await existingHandler(context);
// Call Microsoft Graph to get additional user data
var graphClient = context.HttpContext.RequestServices
.GetRequiredService<GraphServiceClient>();
var user = await graphClient.Me.GetAsync();
var identity = context.Principal.Identity as ClaimsIdentity;
identity?.AddClaim(new Claim("jobTitle", user?.JobTitle ?? ""));
identity?.AddClaim(new Claim("department", user?.Department ?? ""));
};
});
Yetkilendirme isteğine sorgu parametreleri ekleme
Aşağıdaki kod, Microsoft Entra kimlik sağlayıcısına gönderilen yetkilendirme isteğine özel sorgu parametreleri ekler:
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
var existingHandler = options.Events.OnRedirectToIdentityProvider;
options.Events.OnRedirectToIdentityProvider = async context =>
{
// Preserve existing behavior
if (existingHandler != null)
{
await existingHandler(context);
}
// Add custom query parameters
context.ProtocolMessage.Parameters.Add("slice", "testslice");
context.ProtocolMessage.Parameters.Add("custom_param", "custom_value");
// Conditional parameters based on request
if (context.HttpContext.Request.Query.ContainsKey("prompt"))
{
context.ProtocolMessage.Prompt = context.HttpContext.Request.Query["prompt"];
}
};
});
Kimlik doğrulama hatasını işlemeyi özelleştirme
Aşağıdaki kod, hatayı günlüğe kaydetme ve özel bir JSON hata yanıtı döndürme yoluyla kimlik doğrulama hatalarını işler:
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
options.Events.OnAuthenticationFailed = async context =>
{
// Log the error
var logger = context.HttpContext.RequestServices
.GetRequiredService<ILogger<Program>>();
logger.LogError(context.Exception, "Authentication failed");
// Customize error response
context.Response.StatusCode = 401;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync($$"""
{
"error": "authentication_failed",
"error_description": "{{context.Exception.Message}}"
}
""");
context.HandleResponse(); // Suppress default error handling
};
});
Erişim reddedildi durumunu yönet
Aşağıdaki kod, onay vermediğinde kullanıcıları özel bir sayfaya yönlendirir:
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
options.Events.OnAccessDenied = async context =>
{
// User denied consent
context.Response.Redirect("/Home/AccessDenied");
context.HandleResponse();
await Task.CompletedTask;
};
});
Jeton alımını özelleştir
C0 /> içine seçenekleri geçirerek aşağı akış API'leri çağrılırken belirteçlerin nasıl alınacağını özelleştirebilirsiniz.
Özel seçeneklerle IDownstreamApi kullanma
Token alırken ilişkili kimlik ve ek sorgu parametrelerini IDownstreamApi üzerinden geçiren aşağıdaki kod:
using Microsoft.Identity.Abstractions;
public class TodoListController : ControllerBase
{
private readonly IDownstreamApi _downstreamApi;
public TodoListController(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
[HttpGet("{id}")]
public async Task<ActionResult> GetTodo(int id, Guid correlationId)
{
var result = await _downstreamApi.GetForUserAsync<Todo>(
"TodoListService",
options =>
{
options.RelativePath = $"api/todolist/{id}";
// Customize token acquisition
options.TokenAcquisitionOptions = new TokenAcquisitionOptions
{
CorrelationId = correlationId,
ExtraQueryParameters = new Dictionary<string, string>
{
{ "slice", "test_slice" }
}
};
});
return Ok(result);
}
}
Kullanıcı arabirimini özelleştirme
Kullanıcıların oturum açma ve oturum kapatma sonrasında nereye inebileceğini denetleyebilir ve oturum kapatma deneyimini özelleştirebilirsiniz.
Oturum açmadan sonra belirli bir sayfaya yeniden yönlendirme
redirectUri Oturum açtıktan sonra kullanıcıları belirli bir sayfaya göndermek için parametresini kullanın:
<!-- Razor view -->
<a href="/MicrosoftIdentity/Account/SignIn?redirectUri=/Dashboard">Sign In</a>
<!-- Or in controller -->
[HttpGet]
public IActionResult SignInToDashboard()
{
return RedirectToAction("SignIn", "Account", new
{
area = "MicrosoftIdentity",
redirectUri = "/Dashboard"
});
}
Oturum kapatma sayfasını özelleştirme
1. Seçenek: Razor Sayfasını Geçersiz Kılma
Özel içeriğiniz ile adresinde Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml bir dosya oluşturun:
@page
@model Microsoft.Identity.Web.UI.Areas.MicrosoftIdentity.Pages.Account.SignedOutModel
@{
ViewData["Title"] = "Signed out";
}
<div class="container text-center mt-5">
<h1>You have been signed out</h1>
<p>Thank you for using our application.</p>
<a asp-area="" asp-controller="Home" asp-action="Index" class="btn btn-primary">
Return to Home
</a>
</div>
2. Seçenek: Özel bir sayfaya yeniden yönlendirme
Aşağıdaki kod, kullanıcıları varsayılan yerine özel bir oturum kapatma sayfasına yönlendirir:
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
options.Events.OnSignedOutCallbackRedirect = context =>
{
context.Response.Redirect("/Home/SignedOut");
context.HandleResponse();
return Task.CompletedTask;
};
});
Oturum açma deneyimini özelleştirme
Oturum açma ipuçlarını ve alan ipuçlarını kullan
Kullanıcı adlarını önceden doldurarak ve kullanıcıları belirli Microsoft Entra kiracılara yönlendirerek oturum açma deneyimini kolaylaştırın.
İpuçlarını anlama
| İpucu | Amaç | Example |
|---|---|---|
| loginHint | Kullanıcı adı/e-posta alanını önceden doldurma | "user@contoso.com" |
| domainHint | Belirli bir kiracı oturum açma sayfasına doğrudan | "contoso.com" |
İpucu desenlerini uygulama
Desen 1: Denetleyici tabanlı
Aşağıdaki kod, standart oturum açma, oturum açma ipucu veya etki alanı ipucu ya da her ikisini kullanarak oturum açma için denetleyicinin eylemlerini gösterir.
using Microsoft.AspNetCore.Mvc;
public class AuthController : Controller
{
[HttpGet]
public IActionResult SignIn()
{
// Standard sign-in
return RedirectToAction("SignIn", "Account", new
{
area = "MicrosoftIdentity",
redirectUri = "/Dashboard"
});
}
[HttpGet]
public IActionResult SignInWithLoginHint()
{
// Pre-populate username
return RedirectToAction("SignIn", "Account", new
{
area = "MicrosoftIdentity",
redirectUri = "/Dashboard",
loginHint = "user@contoso.com"
});
}
[HttpGet]
public IActionResult SignInWithDomainHint()
{
// Direct to Contoso tenant
return RedirectToAction("SignIn", "Account", new
{
area = "MicrosoftIdentity",
redirectUri = "/Dashboard",
domainHint = "contoso.com"
});
}
[HttpGet]
public IActionResult SignInWithBothHints()
{
// Pre-populate AND direct to tenant
return RedirectToAction("SignIn", "Account", new
{
area = "MicrosoftIdentity",
redirectUri = "/Dashboard",
loginHint = "user@contoso.com",
domainHint = "contoso.com"
});
}
}
Desen 2: Görünüm tabanlı
Aşağıdaki HTML, farklı ipucu yapılandırmalarına sahip oturum açma bağlantılarını gösterir:
<div class="sign-in-options">
<h2>Sign In Options</h2>
<!-- Standard sign-in -->
<a href="/MicrosoftIdentity/Account/SignIn?redirectUri=/Dashboard"
class="btn btn-primary">
Sign In
</a>
<!-- With login hint -->
<a href="/MicrosoftIdentity/Account/SignIn?redirectUri=/Dashboard&loginHint=user@contoso.com"
class="btn btn-secondary">
Sign In as user@contoso.com
</a>
<!-- With domain hint -->
<a href="/MicrosoftIdentity/Account/SignIn?redirectUri=/Dashboard&domainHint=contoso.com"
class="btn btn-secondary">
Sign In (Contoso)
</a>
</div>
Desen 3: OnRedirectToIdentityProvider ile Programlama
Aşağıdaki kod, kimlik sağlayıcısına yeniden yönlendirme sırasında sorgu parametrelerine ve tanımlama bilgilerine göre ipuçlarını dinamik olarak ayarlar:
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
var existingHandler = options.Events.OnRedirectToIdentityProvider;
options.Events.OnRedirectToIdentityProvider = async context =>
{
if (existingHandler != null)
{
await existingHandler(context);
}
// Add hints based on application logic
if (context.HttpContext.Request.Query.TryGetValue("tenant", out var tenant))
{
context.ProtocolMessage.DomainHint = tenant;
}
// Get suggested user from cookie or session
var suggestedUser = context.HttpContext.Request.Cookies["LastSignedInUser"];
if (!string.IsNullOrEmpty(suggestedUser))
{
context.ProtocolMessage.LoginHint = suggestedUser;
}
};
});
Kullanım örnekleri
E-ticaret Platformu:
// Pre-fill returning customer email
loginHint = customerEmail
B2B Uygulaması:
// Direct to customer's tenant
domainHint = customerDomain
Çok Kiracılı SaaS:
// Route based on subdomain
domainHint = GetTenantFromSubdomain(Request.Host)
En iyi yöntemleri izleyin
Yapılması Gerekenler
1. Mevcut olay işleyicilerini her zaman koruyun. Özel mantığınızı çalıştırmadan önce mevcut işleyiciyi kaydedin ve çağırın:
var existingHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await existingHandler(context); // Call Microsoft.Identity.Web's handler
// Your custom code
};
2. İzleme için ilişkilendirme kimliklerini kullanın. Tanılama için belirteç edinme isteklerine bir korelasyon kimliği ekleyin.
var tokenOptions = new TokenAcquisitionOptions
{
CorrelationId = Activity.Current?.Id ?? Guid.NewGuid()
};
3. Özel talepleri doğrulayın. Erişim vermeden önce özel taleplerin beklenen değerleri içerdiğini doğrulayın:
var department = context.Principal.FindFirst("department")?.Value;
if (!IsValidDepartment(department))
{
throw new UnauthorizedAccessException("Invalid department");
}
4. Günlük özelleştirme hataları. Özel logiği try-catch bloklarına sarın ve hataları kaydedin.
try
{
// Custom logic
}
catch (Exception ex)
{
logger.LogError(ex, "Custom authentication logic failed");
throw;
}
5. Hem başarı hem de başarısızlık yollarını test edin. Testlerinizdeki tüm kimlik doğrulama senaryolarını kapsar:
// Test with valid tokens
// Test with missing claims
// Test with expired tokens
// Test with wrong audience
Yapılmaması Gerekenler
1. Microsoft.Identity.Web'in olay işleyicilerini atlamayın:
// Wrong - loses built-in security checks
options.Events.OnTokenValidated = async context => { /* your code */ };
// Correct - preserves security
var existing = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await existing(context);
/* your code */
};
2. Üretimde PII günlüğünü etkinleştirmeyin:
// Wrong
options.EnablePiiLogging = true; // In production!
// Correct
if (builder.Environment.IsDevelopment())
{
options.EnablePiiLogging = true;
}
3. Belirteç doğrulamasını atlamayın:
// Wrong - insecure!
options.TokenValidationParameters.ValidateLifetime = false;
options.TokenValidationParameters.ValidateAudience = false;
// Correct - maintain security
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(5);
4. Hassas değerleri sabit kodlamayın:
// Wrong
options.ClientSecret = "mysecret123";
// Correct
options.ClientSecret = builder.Configuration["AzureAd:ClientSecret"];
5. Ara yazılımda kimlik doğrulamayı değiştirmeyin:
// Wrong - configure in Startup, not middleware
app.Use(async (context, next) =>
{
// Modifying auth options here is too late!
});
Yaygın sorunları giderme
Özelleştirmenin etkili olmamasını çözme
Yürütme sırasını denetleyin:
-
AddMicrosoftIdentityWebApp/AddMicrosoftIdentityWebApivarsayılanları ayarlar -
Configurearamalarınız çalışıyor -
PostConfigureçağrıları çalıştır (varsa) - Seçenekler kullanılır
Çözüm:Configure çağrınız etkili olmuyorsa kullanın PostConfigure, çünkü PostConfigure tüm Configure çağrılarının ardından çalışır.
services.PostConfigure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme,
options => { /* your changes */ }
);
Eksik özel istemleri düzelt
Özel talepler görünmüyorsa aşağıdakileri doğrulayın:
- Mevcut işleyiciyle
OnTokenValidatedişleyicisi doğru şekilde zincirlenmiştir. - Kodunuz talepleri eklemeden önce kimlik doğrulama başarılı olur.
- Talepler doğru
ClaimsIdentityöğesine eklenir.
Aşağıdaki kod hata ayıklama için tüm talepleri günlüğe kaydeder:
var claims = context.Principal.Claims.ToList();
logger.LogInformation($"Claims count: {claims.Count}");
foreach (var claim in claims)
{
logger.LogInformation($"{claim.Type}: {claim.Value}");
}
Çalışmayan olayları düzeltme
Olaylar tetiklenmiyorsa, kimlik doğrulama ve yetkilendirme ara yazılımının doğru sırada kaydedildiğini doğrulayın:
app.UseAuthentication(); // Must be first
app.UseAuthorization(); // Must be second
app.MapControllers(); // Then endpoints