Zabezpečení back-end webového rozhraní API pro vícetenantové aplikace
Aplikace Tailspin Surveys používá back-endové webové rozhraní API ke správě operací CRUD na průzkumech. Když například uživatel klikne na My Surveys (Moje průzkumy), webová aplikace odešle do webového rozhraní API požadavek HTTP:
GET /users/{userId}/surveys
Webové rozhraní API vrátí objekt JSON:
{
"Published":[],
"Own":[
{"Id":1,"Title":"Survey 1"},
{"Id":3,"Title":"Survey 3"},
],
"Contribute": [{"Id":8,"Title":"My survey"}]
}
Webové rozhraní API neumožňuje anonymní požadavky, takže se webová aplikace musí ověřit pomocí nosné tokeny OAuth 2.
Poznámka
Jedná se o scénář mezi serverem. Aplikace neprovolá žádná volání AJAX do rozhraní API z klienta prohlížeče.
Existují dva hlavní přístupy, které můžete použít:
- Delegovaná identita uživatele. Webová aplikace se ověřuje pomocí identity uživatele.
- Identita aplikace. Webová aplikace se ověřuje pomocí ID klienta pomocí toku přihlašovacích údajů klienta OAuth 2.
Aplikace Tailspin implementuje delegovanou identitu uživatele. Tady jsou hlavní rozdíly:
Delegovaná identita uživatele:
- Bearer token odeslaný do webového rozhraní API obsahuje identitu uživatele.
- Webové rozhraní API provádí rozhodnutí o autorizaci na základě identity uživatele.
- Pokud uživatel nemá oprávnění k provedení akce, musí webová aplikace zpracovat chyby 403 (Zakázáno) z webového rozhraní API.
- Webová aplikace obvykle stále provádí nějaká autorizační rozhodnutí, která ovlivňují uživatelské rozhraní, jako je například zobrazení nebo skrytí prvků uživatelského rozhraní).
- Webové rozhraní API mohou potenciálně používat nedůvěryhodní klienti, jako je například javascriptová aplikace nebo nativní klientská aplikace.
Identita aplikace:
- Webové rozhraní API nezískauje informace o uživateli.
- Webové rozhraní API nemůže provádět žádnou autorizaci na základě identity uživatele. Veškerá autorizační rozhodnutí provádí webová aplikace.
- Webové rozhraní API nemůže používat nedůvěryhodný klient (JavaScript ani nativní klientská aplikace).
- Implementace tohoto přístupu může být poněkud jednodušší, protože ve webovém rozhraní API není žádná logika autorizace.
V obou přístupech musí webová aplikace získat přístupový token, což jsou přihlašovací údaje potřebné k volání webového rozhraní API.
- Pro delegovanou identitu uživatele musí token posouvatel identity (IDP), například Azure Active Directory, který může token vydat jménem uživatele.
- V případě přihlašovacích údajů klienta může aplikace získat token z zdůvěřování nebo hostovat vlastní server tokenů. (Ale nepište tokenový server od nuly; použijte dobře otestované rozhraní, jako je [IdentityServer4].) Pokud se ověřujete pomocí Azure AD, důrazně doporučujeme získat přístupový token z Azure AD, a to i pomocí toku přihlašovacích údajů klienta.
Zbývající část tohoto článku předpokládá, že se aplikace ověřuje ve službě Azure AD.
Diagram znázorňuje webovou aplikaci, která požaduje přístupový token z Azure AD a odesílá token do webového rozhraní API.
Registrace webového rozhraní API v Azure AD
Aby služba Azure AD pro webové rozhraní API vyděsí bearer token, musíte v Azure AD nakonfigurovat některé věci.
Zaregistrujte webové rozhraní API v Azure AD.
Přidejte ID klienta webové aplikace do manifestu aplikace webového rozhraní API ve
knownClientApplicationsvlastnosti . Další informace GitHub v souboru Readme.Udejte webové aplikaci oprávnění k volání webového rozhraní API. V Azure Portal můžete nastavit dva typy oprávnění: Oprávnění aplikace pro identitu aplikace (tok přihlašovacích údajů klienta) nebo Delegovaná oprávnění pro delegovanou identitu uživatele.
Snímek obrazovky s Azure Portal, který zobrazuje oprávnění aplikace a delegovaná oprávnění
Získání přístupového tokenu
Před voláním webového rozhraní API získá webová aplikace přístupový token z Azure AD. V aplikaci .NET použijte knihovnu Microsoft Authentication Library for .NET (MSAL.NET). Přidejte .EnableTokenAcquisitionToCallDownstreamApi() do souboru Startup.cs aplikace.
Po získání tokenu ho MSAL ukládá do mezipaměti. Proto budete také muset zvolit implementaci mezipaměti tokenů, která je součástí MSAL. Tento příklad používá distribuovanou mezipaměť. Podrobnosti najdete v tématu Ukládání tokenů do mezipaměti.
Použití přístupového tokenu k volání webového rozhraní API
Jakmile budete mít token, zavolejte podřízené webové rozhraní API. Tento proces je popsaný v části Volání podřízeného webového rozhraní API pomocí třídy pomocná metoda.
Ověřování ve webovém rozhraní API
Webové rozhraní API musí ověřit bearer token. V ASP.NET Core můžete použít balíček Microsoft.AspNet.Authentication.JwtBearer. Tento balíček poskytuje middleware, který aplikaci umožňuje přijímat OpenID Připojení tokeny.
Zaregistrujte middleware ve třídě webového Startup rozhraní API.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(jtwOptions =>
{
jtwOptions.Events = new SurveysJwtBearerEvents(loggerFactory.CreateLogger<SurveysJwtBearerEvents>());
},
msIdentityOptions => {
Configuration.GetSection("AzureAd").Bind(msIdentityOptions);
});
Events je třída odvozená od jwtBearerEvents.
Ověření vystavitele
Ověřte vystavitele tokenu v události JwtBearerEvents.TokenValidated. Vystavitel se odesílá v deklaraci identity "iss".
Webové rozhraní API v aplikaci Surveys nezvládá [zaregistrovat tenanta.] Proto jenom kontroluje, jestli vystavitel už je v databázi aplikace. Pokud ne, vyvolá výjimku, která způsobí selhání ověřování.
public override async Task TokenValidated(TokenValidatedContext context)
{
var principal = context.Ticket.Principal;
var tenantManager = context.HttpContext.RequestServices.GetService<TenantManager>();
var userManager = context.HttpContext.RequestServices.GetService<UserManager>();
var issuerValue = principal.GetIssuerValue();
var tenant = await tenantManager.FindByIssuerValueAsync(issuerValue);
if (tenant == null)
{
// The caller was not from a trusted issuer. Throw to block the authentication flow.
throw new SecurityTokenValidationException();
}
var identity = principal.Identities.First();
// Add new claim for survey_userid
var registeredUser = await userManager.FindByObjectIdentifier(principal.GetObjectIdentifierValue());
identity.AddClaim(new Claim(SurveyClaimTypes.SurveyUserIdClaimType, registeredUser.Id.ToString()));
identity.AddClaim(new Claim(SurveyClaimTypes.SurveyTenantIdClaimType, registeredUser.TenantId.ToString()));
// Add new claim for Email
var email = principal.FindFirst(ClaimTypes.Upn)?.Value;
if (!string.IsNullOrWhiteSpace(email))
{
identity.AddClaim(new Claim(ClaimTypes.Email, email));
}
}
Jak ukazuje tento příklad, můžete k úpravě deklarací identity použít také událost TokenValidated. Nezapomeňte, že deklarace identity pocházejí přímo z Azure AD. Pokud webová aplikace upraví deklarace identity, které získá, tyto změny se v bearer tokenu, který obdrží webové rozhraní API, nezjistí. Další informace najdete v tématu Transformace deklarací identity.
Autorizace
Obecnou diskuzi o autorizaci najdete v tématu Autorizace na základě rolí a na základě prostředků.
Middleware JwtBearer zpracovává autorizační odpovědi. Pokud například chcete akci kontroleru omezit na ověřené uživatele, použijte atribut [Authorize] a jako schéma ověřování zadejte JwtBearerDefaults.AuthenticationScheme:
[Authorize(ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Pokud uživatel není ověřený, vrátí se stavový kód 401.
Pokud chcete akci kontroleru omezit pomocí zásad autorizace, zadejte název zásady v atributu [Authorize]:
[Authorize(Policy = PolicyNames.RequireSurveyCreator)]
Vrátí se stavový kód 401, pokud uživatel není ověřený, a 403, pokud je uživatel ověřený, ale není autorizovaný. Zaregistrujte zásadu při spuštění:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy(PolicyNames.RequireSurveyCreator,
policy =>
{
policy.AddRequirements(new SurveyCreatorRequirement());
policy.RequireAuthenticatedUser(); // Adds DenyAnonymousAuthorizationRequirement
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
});
options.AddPolicy(PolicyNames.RequireSurveyAdmin,
policy =>
{
policy.AddRequirements(new SurveyAdminRequirement());
policy.RequireAuthenticatedUser(); // Adds DenyAnonymousAuthorizationRequirement
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
});
});
// ...
}
Ochrana tajných kódů aplikací
Nastavení aplikace, která jsou citlivá a musí být chráněná, je běžné, například:
- Databázové připojovací řetězce
- Hesla
- Kryptografické klíče
Osvědčeným postupem zabezpečení je nikdy neukládejte tyto tajné kódy do správy zdrojového kódu. Prozrazení je příliš — snadné, i když je vaše úložiště zdrojového kódu soukromé. A ne jenom o uchovávání tajných kódů od veřejnosti. U větších projektů můžete chtít omezit, kteří vývojáři a operátoři mají přístup k produkčním tajným kódům. (Nastavení pro testovací nebo vývojová prostředí se liší.)
Bezpečnější možností je uložit tyto tajné kódy do Azure Key Vault. Key Vault je služba hostovaná v cloudu pro správu kryptografických klíčů a dalších tajných kódů. Tento článek popisuje, jak pomocí Key Vault k ukládání nastavení konfigurace pro vaši aplikaci.
V aplikaci Tailspin Surveys jsou následující nastavení tajná:
- Připojovací řetězec databáze.
- Připojovací řetězec Redis.
- Tajný klíč klienta pro webovou aplikaci.
Aplikace Surveys načítá nastavení konfigurace z následujících míst:
- Soubor appsettings.json
- Úložiště tajných kódů uživatelů (pouze vývojové prostředí; pro účely testování)
- Hostitelské prostředí (nastavení aplikace ve webových aplikacích Azure)
- Key Vault (pokud je povoleno)
Každá z těchto vlastností přepíše předchozí nastavení, takže jakákoli nastavení uložená Key Vault mají přednost.
Poznámka
Ve výchozím nastavení je Key Vault konfigurace zakázané. Není potřeba k místnímu spuštění aplikace. Povolíte ho v produkčním nasazení.
Při spuštění aplikace načte nastavení z každého registrovaného zprostředkovatele konfigurace a použije je k naplnění objektu možností silného typu. Další informace najdete v tématu Použití možností a objektů konfigurace.
Vzorek kódu