Para configurar o código para sua API Web protegida, saiba:
O que define as APIs como protegidas.
Como configurar um token de portador.
Como validar um token.
O que define as APIs ASP.NET e ASP.NET Core como protegidas?
Assim como os aplicativos Web, as APIs Web do ASP.NET e ASP.NET Core são protegidas porque suas ações de controlador são prefixadas com o atributo [Authorize]. As ações do controlador poderão ser chamadas somente se a API for chamada com uma identidade autorizada.
Considere as seguintes perguntas:
Somente um aplicativo pode chamar uma API da Web. Como a API sabe a identidade do aplicativo que a chama?
Se o aplicativo chamar a API em nome de um usuário, qual é a identidade do usuário?
Token de portador
O token de portador definido no cabeçalho quando o aplicativo é chamado contém informações sobre a identidade do aplicativo. Ele também contém informações sobre o usuário, a menos que o aplicativo Web aceite chamadas de serviço a serviço de um aplicativo daemon.
Aqui está um exemplo de código em C# que mostra um cliente que chama a API depois de adquirir um token com a biblioteca de autenticação da Microsoft para .NET (MSAL.NET):
var scopes = new[] {$"api://.../access_as_user"};
var result = await app.AcquireToken(scopes)
.ExecuteAsync();
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the web API.
HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
Importante
Um aplicativo cliente solicita o token de portador para a plataforma de identidade da Microsoft para a API Web. A API é o único aplicativo que deve verificar o token e exibir as declarações que ele contém. Os aplicativos cliente nunca devem tentar inspecionar as declarações em tokens.
No futuro, a API Web pode exigir que o token seja criptografado. Esse requisito impediria o acesso para aplicativos cliente que podem exibir tokens de acesso.
Configuração do JwtBearer
Esta seção descreve como configurar um token de portador.
Arquivo de configuração
Você precisa especificar o TenantId único se quiser aceitar tokens de acesso de um único locatário (aplicativo de linha de negócios). Caso contrário, ele poderá ser deixado como common. Os valores diferentes podem ser:
Uma GUID (ID do locatário = ID do diretório)
common pode ser qualquer organização e contas pessoais
Usando um URI de ID do Aplicativo personalizado para uma API Web
Se você aceitou o URI da ID do aplicativo padrão proposto pelo portal do Azure, não é necessário especificar o público. Confira Escopos e URI da ID do aplicativo. Caso contrário, adicione uma propriedade Audience cujo valor seja o URI da ID do aplicativo para a sua API Web. Normalmente, isso começa com api://.
Quando um aplicativo é chamado em uma ação do controlador que contém um atributo [Authorize] , ASP.NET e ASP.NET Core extraem o token de acesso do token de portador do cabeçalho de autorização. O token de acesso é encaminhado para o middleware JwtBearer, que chama as extensões Microsoft IdentityModel para .NET.
A Microsoft recomenda que você use o pacote NuGet Microsoft.Identity.Web ao desenvolver uma API Web com ASP.NET Core.
O Microsoft.Identity.Web fornece a cola entre ASP.NET Core, o middleware de autenticação e a MSAL (biblioteca de autenticação da Microsoft) para .NET. Ele permite uma experiência de desenvolvedor mais clara e robusta e aproveita o poder da plataforma de identidade da Microsoft e do Azure AD B2C.
ASP.NET para .NET 6.0
Para criar um projeto da API Web que usa o Microsoft.Identity.Web, use um modelo de projeto na CLI do .NET 6.0 ou no Visual Studio.
CLI do Dotnet core
# Create new web API that uses Microsoft.Identity.Web
dotnet new webapi --auth SingleOrg
Visual Studio – Para criar um projeto de API Web no Visual Studio, selecione Arquivo>Novo>Projeto>ASP.NET Core Web API.
Os modelos de projeto da CLI do .NET e do Visual Studio criam um arquivo Program.cs semelhante para este snippet de código. Observe a diretiva usando Microsoft.Identity.Web e as linhas que contêm autenticação e autorização.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
A Microsoft recomenda que você use o pacote NuGet Microsoft.Identity.Web ao desenvolver uma API Web com ASP.NET Core.
OMicrosoft.Identity.Web.OWIN fornece a cola entre ASP.NET Core, o middleware de autenticação ASP.NET e a Biblioteca de autenticação da Microsoft (MSAL) para .NET. Ele permite uma experiência de desenvolvedor mais clara e robusta e aproveita o poder da plataforma de identidade da Microsoft e do Azure AD B2C.
Ele usa o mesmo arquivo de configuração que ASP.NET Core (appsettings.json) e você precisa garantir que esse arquivo seja copiado com a saída do projeto (cópia de propriedade sempre nas propriedades do arquivo no Visual Studio ou no .csproj)
O Microsoft.Identity.Web.OWIN adiciona um método de extensão ao IAppBuilder chamado AddMicrosoftIdentityWebApi. Esse método usa como parâmetro uma instância do OwinTokenAcquirerFactory que você recebe chamando OwinTokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>() e que apresenta uma instância da IServiceCollection qual você pode adicionar muitos serviços para chamar APIs de downstream ou configurar o cache de token.
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web.OWIN;
using System.Web.Services.Description;
namespace OwinWebApp
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
OwinTokenAcquirerFactory factory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
app.AddMicrosoftIdentityWebApp(factory);
factory.Services
.Configure<ConfidentialClientApplicationOptions>(options => { options.RedirectUri = "https://localhost:44386/"; })
.AddMicrosoftGraph()
.AddDownstreamApi("DownstreamAPI1", factory.Configuration.GetSection("DownstreamAPI"))
.AddInMemoryTokenCaches();
factory.Build();
}
}
}
--
Validação de token
No trecho anterior, o middleware JwtBearer, como o middleware OpenID Connect em aplicativos Web, valida o token com base no valor de TokenValidationParameters. O token é descriptografado conforme necessário. As declarações são extraídas e a assinatura é verificada. Em seguida, o middleware valida o token, verificando os dados:
Público-alvo: o token é direcionado para a API Web.
Sub: ele foi emitido para um aplicativo que tem permissão para chamar a API da Web.
Emissor: ele foi emitido por um serviço de token de segurança (STS) confiável.
Expiração: seu tempo de vida está no intervalo.
Assinatura: ela não foi violada.
Também podem haver validações especiais. Por exemplo, é possível validar que as chaves de assinatura, quando inseridas em um token, sejam confiáveis, e que o token não esteja sendo repetido. Por fim, alguns protocolos exigem validações específicas.
Garante que o token seja para o aplicativo que valida o token para você.
ValidateIssuer
Garante que o token foi emitido por um STS confiável, o que significa que ele é de alguém em quem você confia.
ValidateIssuerSigningKey
Garante que o aplicativo que valida o token confie na chave que foi usada para assinar o token. Há um caso especial em que a chave é inserida no token. Mas esse caso não costuma ocorrer.
ValidateLifetime
Garante que o token ainda seja válido ou já seja válido. O validador verifica se o tempo de vida do token está no intervalo especificado pelas declarações nobefore e expires.
ValidateSignature
Garante que o token não tenha sido adulterado.
ValidateTokenReplay
Garante que o token não seja reproduzido. Há um caso especial para alguns protocolos de uso único.
Personalizando a validação de token
Os validadores são associados às propriedades da classe TokenValidationParameters. As propriedades são inicializadas a partir da configuração do ASP.NET e do ASP.NET Core.
Na maioria dos casos, não é preciso mudar os parâmetros. Aplicativos que não são locatários únicos são exceções. Esses aplicativos Web aceitam usuários de qualquer organização ou de contas pessoais da Microsoft. Os emissores, nesse caso, devem ser validados. O Microsoft.Identity.Web cuida da validação do emissor também.
No ASP.NET Core, se você quiser personalizar os parâmetros de validação de token, use o trecho a seguir em seu Startup.cs:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration);
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.ValidAudiences = new[] { /* list of valid audiences */};
});
Para o ASP.NET MVC, o exemplo de código a seguir mostra como fazer a validação de token personalizada:
Você também pode validar tokens de acesso de entrada no Azure Functions. Você pode encontrar exemplos de tal validação nos exemplos de código a seguir no GitHub: