Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto článku implementujete autorizaci ve webových rozhraních API ASP.NET Core pomocí Microsoft. Identity.Web. Ověříte obory (delegovaná oprávnění) a oprávnění aplikace (oprávnění aplikace) k řízení přístupu k chráněným prostředkům. Příklady používají Microsoft Entra ID jako zprostředkovatele identity.
Vysvětlení konceptů autorizace
Tato část popisuje klíčové rozdíly mezi ověřováním a autorizací a popisuje, co Microsoft. Identity.Web ověřuje v přístupových tokenech.
Ověřování vs. autorizace
| Koncepce | Purpose | Výsledek |
|---|---|---|
| Autentizace | Ověření identity | 401 Neautorizovaný přístup v případě selhání |
| Authorization | Kontrola oprávnění | 403 Zakázáno, pokud je nedostatečné |
Co se ověří
Když webové rozhraní API obdrží přístupový token, Microsoft. Identity.Web ověřuje:
- Podpis tokenu – Pochází z důvěryhodné autority?
- Cílová skupina tokenů – Je určená pro toto rozhraní API?
- Vypršení platnosti tokenu – je stále platný?
- Rozsahy/Role – Mají klientská aplikace a subjekt (uživatel) potřebná oprávnění?
Tato příručka se zaměřuje na #4 – ověřování oborů a oprávnění aplikací.
Obory (delegovaná oprávnění)
Rozsahy platí, když uživatel deleguje oprávnění na aplikaci, aby jednal jejich jménem (například webové API volané na základě oprávnění přihlášeného uživatele).
| Podrobnost | Hodnota |
|---|---|
| Požadavek na token |
scp nebo scope (klientská aplikace); roles (uživatel) |
| Ukázkové hodnoty |
"access_as_user", "User.Read", "Files.ReadWrite" |
Oprávnění aplikací (přístupová práva aplikace)
Oprávnění aplikace se použijí, když aplikace volá webové rozhraní API sama o sobě bez kontextu uživatele, například jako démon nebo služba na pozadí používající přihlašovací údaje klienta.
| Podrobnost | Hodnota |
|---|---|
| Nárok tokenu | roles |
| Ukázkové hodnoty |
"Mail.Read.All", "User.Read.All" |
Ověření oborů pomocí RequiredScope
Atribut RequiredScope zkontroluje, že přístupový token obsahuje alespoň jeden ze zadaných oborů. Tento atribut použijte, když vaše rozhraní API obsluhuje pouze požadavky delegované uživatelem.
Nastavení ověřování oboru
Pokud chcete ve svém rozhraní API povolit ověřování oboru, postupujte podle těchto kroků.
1. Povolení autorizace v rozhraní API:
Přidání ověřovacích a autorizačních služeb do kanálu aplikace:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization(); // Required for authorization
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization(); // Must be after UseAuthentication
app.MapControllers();
app.Run();
2. Ochrana kontrolerů nebo akcí:
Aplikujte atributy [Authorize] a [RequiredScope] k vašemu kontroleru nebo jednotlivým akcím:
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web.Resource;
[Authorize]
[RequiredScope("access_as_user")]
public class TodoListController : ControllerBase
{
[HttpGet]
public IActionResult GetTodos()
{
// Only accessible if token has "access_as_user" scope
return Ok(new[] { "Todo 1", "Todo 2" });
}
}
Použijte vzory oboru
Zvolte vzor, který nejlépe vyhovuje způsobu správy oborů ve vaší aplikaci.
Vzor 1: Pevně zakódované obory
Tento vzor použijte, pokud jsou obory předem stanovené a známé během vývoje.
[Authorize]
[RequiredScope("access_as_user")]
public class TodoListController : ControllerBase
{
// All actions require "access_as_user" scope
}
Pokud chcete přijmout některý z více oborů, uveďte je jako parametry:
[Authorize]
[RequiredScope("read", "write", "admin")]
public class TodoListController : ControllerBase
{
// Token must have "read" OR "write" OR "admin"
}
Vzorec 2: Rozsahy z konfigurace
Tento vzor použijte, pokud mají být obory konfigurovatelné pro každé prostředí. Definujte obory v konfiguračním souboru:
appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-api-client-id",
"Scopes": "access_as_user read write"
}
}
Odkaz na konfigurační klíč v kontroleru:
[Authorize]
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
public class TodoListController : ControllerBase
{
// Scopes read from configuration
}
Tento přístup umožňuje změnit rozsahy bez rekompilování.
Vzor 3: Rozsahy na úrovni akce
Tento vzor použijte, když různé akce vyžadují různá oprávnění. Použijte [RequiredScope] na jednotlivé metody akcí:
[Authorize]
public class TodoListController : ControllerBase
{
[HttpGet]
[RequiredScope("read")]
public IActionResult GetTodos()
{
return Ok(todos);
}
[HttpPost]
[RequiredScope("write")]
public IActionResult CreateTodo([FromBody] Todo todo)
{
// Only tokens with "write" scope can create
return CreatedAtAction(nameof(GetTodos), todo);
}
[HttpDelete("{id}")]
[RequiredScope("admin")]
public IActionResult DeleteTodo(int id)
{
// Only tokens with "admin" scope can delete
return NoContent();
}
}
Vysvětlení toku ověřování
Jakmile požadavek dorazí, middleware ho zpracuje v následujícím pořadí:
- ASP.NET Core ověřovací middleware validuje token.
-
RequiredScopekontrola atributuscpneboscopenároku - Pokud token obsahuje alespoň jeden odpovídající obor, požadavek pokračuje.
- Pokud se nenajde žádný odpovídající obor, rozhraní API vrátí odpověď 403 Zakázáno.
Následující příklad ukazuje typickou chybovou odpověď:
{
"error": "insufficient_scope",
"error_description": "The token does not have the required scope 'access_as_user'."
}
Ověření oprávnění aplikace pomocí RequiredScopeOrAppPermission
Atribut RequiredScopeOrAppPermission ověří buď obory (delegované), nebo oprávnění aplikace (aplikace). Tento atribut použijte, když vaše rozhraní API obsluhuje aplikace delegované uživatelem i aplikace démona nebo služby ze stejného koncového bodu.
Pokud vaše rozhraní API obsluhuje pouze požadavky delegované uživatelem, použijte RequiredScope místo toho.
Nastavení ověření oboru nebo oprávnění aplikace
Pomocí atributu přijměte jeden typ tokenu:
using Microsoft.Identity.Web.Resource;
[Authorize]
[RequiredScopeOrAppPermission(
AcceptedScope = new[] { "access_as_user" },
AcceptedAppPermission = new[] { "TodoList.ReadWrite.All" }
)]
public class TodoListController : ControllerBase
{
[HttpGet]
public IActionResult GetTodos()
{
// Accessible with EITHER:
// - User-delegated token with "access_as_user" scope, OR
// - App-only token with "TodoList.ReadWrite.All" app permission
return Ok(todos);
}
}
Konfigurace oprávnění aplikace z nastavení
Ukládejte obory a oprávnění aplikace v konfiguraci, abyste je mohli změnit bez rekompilace.
appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-api-client-id",
"Scopes": "access_as_user",
"AppPermissions": "TodoList.ReadWrite.All TodoList.Admin"
}
}
Odkazujte na konfigurační klíče v kontroleru:
[Authorize]
[RequiredScopeOrAppPermission(
RequiredScopesConfigurationKey = "AzureAd:Scopes",
RequiredAppPermissionsConfigurationKey = "AzureAd:AppPermissions"
)]
public class TodoListController : ControllerBase
{
// Scopes and app permissions from configuration
}
Porovnání rozdílů v nárocích tokenů
Následující tabulka ukazuje, jak se nároky liší mezi tokeny delegovanými uživatelem a tokeny pouze pro aplikace.
| Typ tokenu | Požadavek | Příklad hodnoty |
|---|---|---|
| Delegované uživatelem |
scp nebo scope |
"access_as_user User.Read" |
| Pouze pro aplikaci | roles |
["TodoList.ReadWrite.All"] |
Následující příklad ukazuje token delegovaný uživatelem:
{
"aud": "api://your-api-client-id",
"iss": "https://login.microsoftonline.com/.../v2.0",
"scp": "access_as_user",
"sub": "user-object-id",
...
}
Následující příklad ukazuje token jen pro aplikaci:
{
"aud": "api://your-api-client-id",
"iss": "https://login.microsoftonline.com/.../v2.0",
"roles": ["TodoList.ReadWrite.All"],
"sub": "app-object-id",
...
}
Vytvoření zásad autorizace
V případě složitých scénářů autorizace použijte zásady autorizace ASP.NET Core. Zásady umožňují centralizovat pravidla, kombinovat více požadavků a zapisovat testovatelnou autorizační logiku.
| Benefit | Description |
|---|---|
| Centralizovaná logika | Definování autorizačních pravidel jednou, opakované použití všude |
| Skládatelný | Kombinování více požadavků (rozsahy + nároky + vlastní logika) |
| Testovatelné | Jednodušší logika autorizace pro testování jednotek |
| Ohebný | Vlastní požadavky nad rámec ověřování rozsahu |
Model 1: Definování zásad pomocí RequireScope
Definujte pojmenované zásady, které vyžadují konkrétní obory, a pak na ně odkazujte na kontrolery:
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("TodoReadPolicy", policyBuilder =>
{
policyBuilder.RequireScope("read", "access_as_user");
});
options.AddPolicy("TodoWritePolicy", policyBuilder =>
{
policyBuilder.RequireScope("write", "admin");
});
});
var app = builder.Build();
Použijte zásady na akce kontroleru:
[Authorize]
public class TodoListController : ControllerBase
{
[HttpGet]
[Authorize(Policy = "TodoReadPolicy")]
public IActionResult GetTodos()
{
return Ok(todos);
}
[HttpPost]
[Authorize(Policy = "TodoWritePolicy")]
public IActionResult CreateTodo([FromBody] Todo todo)
{
return CreatedAtAction(nameof(GetTodos), todo);
}
}
Model 2: Definování zásady pomocí ScopeAuthorizationRequirement
Použijte ScopeAuthorizationRequirement pro explicitnější požadavky na rozsah:
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.Resource;
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("CustomPolicy", policyBuilder =>
{
policyBuilder.AddRequirements(
new ScopeAuthorizationRequirement(new[] { "access_as_user" })
);
});
});
Model 3: Nastavení výchozí zásady
Nastavte výchozí zásadu, která se vztahuje na všechny [Authorize] atributy automaticky:
builder.Services.AddAuthorization(options =>
{
var defaultPolicy = new AuthorizationPolicyBuilder()
.RequireScope("access_as_user")
.Build();
options.DefaultPolicy = defaultPolicy;
});
Každý [Authorize] atribut teď vyžaduje access_as_user obor:
[Authorize] // Automatically requires "access_as_user" scope
public class TodoListController : ControllerBase
{
// All actions protected by default policy
}
Model 4: Kombinování více požadavků
Zkombinujte požadavky na obor, roli a ověřování v jedné zásadě:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminPolicy", policyBuilder =>
{
policyBuilder.RequireScope("admin");
policyBuilder.RequireRole("Admin"); // Also check role claim
policyBuilder.RequireAuthenticatedUser();
});
});
Model 5: Sestavení zásady z konfigurace
Rozsahy zatížení z konfigurace za účelem zachování zásad specifických pro prostředí:
var requiredScopes = builder.Configuration["AzureAd:Scopes"]?.Split(' ');
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("ApiAccessPolicy", policyBuilder =>
{
if (requiredScopes != null)
{
policyBuilder.RequireScope(requiredScopes);
}
});
});
Filtrování požadavků podle tenanta
Omezte přístup rozhraní API k tokenům z konkrétních Microsoft Entra tenantů. To je užitečné, když vaše víceklientské rozhraní API by mělo přijímat jenom žádosti od schválených tenantů zákazníků.
Omezení přístupu k povoleným tenantům
Definujte zásadu, která kontroluje deklaraci identity ID tenanta proti seznamu povolených:
builder.Services.AddAuthorization(options =>
{
string[] allowedTenants =
{
"14c2f153-90a7-4689-9db7-9543bf084dad", // Contoso tenant
"af8cc1a0-d2aa-4ca7-b829-00d361edb652", // Fabrikam tenant
"979f4440-75dc-4664-b2e1-2cafa0ac67d1" // Northwind tenant
};
options.AddPolicy("AllowedTenantsOnly", policyBuilder =>
{
policyBuilder.RequireClaim(
"http://schemas.microsoft.com/identity/claims/tenantid",
allowedTenants
);
});
// Apply to all endpoints by default
options.DefaultPolicy = options.GetPolicy("AllowedTenantsOnly");
});
Konfigurace filtrování nájemce v nastavení
Uložte povolené ID tenanta v konfiguraci, abyste je mohli spravovat beze změn kódu.
appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "your-api-client-id",
"AllowedTenants": [
"14c2f153-90a7-4689-9db7-9543bf084dad",
"af8cc1a0-d2aa-4ca7-b829-00d361edb652"
]
}
}
Přečtěte si seznam tenantů a vytvořte zásadu při spuštění:
var allowedTenants = builder.Configuration.GetSection("AzureAd:AllowedTenants")
.Get<string[]>();
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AllowedTenantsOnly", policyBuilder =>
{
policyBuilder.RequireClaim(
"http://schemas.microsoft.com/identity/claims/tenantid",
allowedTenants ?? Array.Empty<string>()
);
});
});
Kombinování oborů s filtrováním tenanta
Vytvořte zásadu, která vyžaduje platný obor i schváleného tenanta:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("SecureApiAccess", policyBuilder =>
{
// Require specific scope
policyBuilder.RequireScope("access_as_user");
// AND require specific tenant
policyBuilder.RequireClaim(
"http://schemas.microsoft.com/identity/claims/tenantid",
allowedTenants
);
});
});
Dodržujte osvědčené postupy.
Tato doporučení použijte k vytvoření zabezpečené a udržovatelné autorizační logiky.
Co dělat
1. Vždy spárujte [Authorize] s validací oboru:
[Authorize] // Authentication
[RequiredScope("access_as_user")] // Authorization
public class MyController : ControllerBase { }
2. Použijte konfiguraci pro obory specifické pro prostředí:
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
3. Použijte nejnižší oprávnění:
[HttpGet]
[RequiredScope("read")] // Only read permission needed
[HttpPost]
[RequiredScope("write")] // Write permission for modifications
4. Použijte zásady pro komplexní autorizaci:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
{
policy.RequireScope("admin");
policy.RequireClaim("department", "IT");
});
});
5. Povolte podrobné odpovědi na chyby ve vývoji:
if (builder.Environment.IsDevelopment())
{
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
}
Zakázané činnosti
1. Nevynechávejte [Authorize] při použití RequiredScope:
// Wrong - RequiredScope won't work without [Authorize]
[RequiredScope("access_as_user")]
public class MyController : ControllerBase { }
// Correct
[Authorize]
[RequiredScope("access_as_user")]
public class MyController : ControllerBase { }
2. Nezakódujte PEVNĚ ID tenanta v produkčním prostředí:
// Wrong
policyBuilder.RequireClaim("tid", "14c2f153-90a7-4689-9db7-9543bf084dad");
// Better - use configuration
var tenants = Configuration.GetSection("AllowedTenants").Get<string[]>();
policyBuilder.RequireClaim("tid", tenants);
3. Nezaměňujte obory s rolemi:
// Wrong - This checks roles claim, not scopes
[RequiredScope("Admin")] // "Admin" is typically a role, not a scope
// Correct
[RequiredScope("access_as_user")] // Scope
[Authorize(Roles = "Admin")] // Role
4. Nezpřístupňujte citlivé informace o rozsahu v chybových zprávách v produkčním prostředí:
Nakonfigurujte odpovídající úrovně protokolování a zpracování chyb pro produkční prostředí.
Řešení potíží s autorizací
Při diagnostice běžných problémů s autorizací využijte následující doprovodné materiály.
403 Zakázáno – chybějící obor
Chyba: API vrací kód 403, i když je použit platný token.
Diagnóza:
- Dekódujte token na jwt.ms.
- Zkontrolujte
scpneboscopenárok. - Ověřte, že hodnota odpovídá vašemu atributu
RequiredScope.
Solution:
- Ujistěte se, že klientská aplikace při získávání tokenu požaduje správný obor.
- Ověřte, že je rozsah zveřejněn v registraci API aplikace v Microsoft Entra.
- V případě potřeby udělte souhlas správce.
RequiredScope nefunguje
Příznakem: Atribut se zdá být ignorován.
Kontrola:
- Přidali jste
[Authorize]atribut? - Je
app.UseAuthorization()volána poapp.UseAuthentication()? - Je zaregistrovaný
services.AddAuthorization()?
Konfigurační klíč nebyl nalezen.
Chyba: Ověření oboru selže bezobslužně.
Kontrola:
{
"AzureAd": {
"Scopes": "access_as_user" // Matches RequiredScopesConfigurationKey
}
}
Zkontrolujte, že cesta konfigurace přesně odpovídá.