Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aplica-se a:
Locatários da força de trabalho
Inquilinos externos (saiba mais)
Esta série de tutoriais demonstra como proteger uma API Web ASP.NET Core com a plataforma de identidade da Microsoft para limitar seu acesso apenas a usuários autorizados e aplicativos cliente. A API da Web que você cria usa permissões delegadas (escopos) e permissões de aplicativo (funções de aplicativo).
Neste tutorial, você:
- Crie uma API Web ASP.NET Core
- Configurar a API web para usar os detalhes de registo da aplicação Microsoft Entra
- Proteja os seus endpoints da API da web
- Execute a API da Web para garantir que ela esteja ouvindo solicitações HTTP
Pré-requisitos
- Se ainda não o fez, conclua as etapas em Guia de início rápido: chamar uma API da Web protegida pela plataforma de identidade da Microsoft. Não é necessário clonar e executar o exemplo de código, mas certifique-se de ter o seguinte:
- Os detalhes de registo do aplicativo da API web no centro de administração Microsoft Entra, incluindo a ID do cliente e a ID do locatário.
- ToDoList.Read e ToDoList.ReadWrite como as permissões delegadas (escopos) expostas pela API da Web
- ToDoList.Read.All e ToDoList.ReadWrite.All como as permissões do aplicativo (funções do aplicativo) expostas pela API da Web
- SDK do .NET 8.0 ou posterior.
- Visual Studio Code ou outro editor de código.
Criar um novo projeto de API Web ASP.NET Core
Para criar um projeto mínimo de API Web ASP.NET Core, siga estas etapas:
Abra seu terminal no Visual Studio Code ou em qualquer outro editor de código e navegue até o diretório onde você deseja criar seu projeto.
Execute os seguintes comandos na CLI do .NET ou em qualquer outra ferramenta de linha de comando.
dotnet new web -o TodoListApi cd TodoListApiSelecione Sim quando uma caixa de diálogo perguntar se você deseja confiar nos autores.
Selecione Sim Quando uma caixa de diálogo perguntar se você deseja adicionar os ativos necessários ao projeto.
Instalar pacotes necessários
Para criar, proteger e testar a API Web ASP.NET Core, você precisa instalar os seguintes pacotes:
-
Microsoft.EntityFrameworkCore.InMemory- Um pacote que permite usar o Entity Framework Core com um banco de dados na memória. É útil para fins de teste, mas não foi projetado para uso em produção. -
Microsoft.Identity.Web- um conjunto de bibliotecas ASP.NET Core que simplificam a adição de suporte de autenticação e autorização a aplicações Web e APIs Web que se integram com a plataforma de identidade da Microsoft.
Para instalar o pacote, use:
dotnet add package Microsoft.EntityFrameworkCore.InMemory
dotnet add package Microsoft.Identity.Web
Configurar detalhes de registro do aplicativo
Abra o arquivo appsettings.json na pasta do aplicativo e adicione os detalhes de registro do aplicativo que você gravou depois de registrar a API da Web.
{
"AzureAd": {
"Instance": "Enter_the_Authority_URL_Here",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here"
},
"Logging": {...},
"AllowedHosts": "*"
}
Substitua os seguintes marcadores de posição, conforme mostrado:
- Substitua
Enter_the_Application_Id_Herepelo ID do aplicativo (cliente). - Substitua
Enter_the_Tenant_Id_Herepelo ID do diretório (tenant). - Substitua
Enter_the_Authority_URL_Herepelo URL da Authority, conforme explicado na próxima seção.
URL de autoridade para seu aplicativo
A URL de autoridade especifica o diretório do qual a Biblioteca de Autenticação da Microsoft (MSAL) pode solicitar tokens. Você o constrói de forma diferente tanto na força de trabalho quanto nos locatários externos, conforme mostrado:
//Instance for workforce tenant
Instance: "https://login.microsoftonline.com/"
Usar domínio de URL personalizado (opcional)
Domínios de URL personalizados não são suportados em locatários da força de trabalho.
Adicionar permissões
Todas as APIs devem publicar um mínimo de um escopo, também chamado de permissão delegada, para que os aplicativos cliente obtenham um token de acesso para um usuário com êxito. As APIs também devem publicar pelo menos uma função de aplicativo, também chamadas de permissões de aplicativo, para que as aplicações cliente possam obter um token de acesso por si mesmas, ou seja, quando um utilizador não está a iniciar sessão.
Especificamos essas permissões no arquivo appsettings.json. Neste tutorial, você registrou as seguintes permissões delegadas e de aplicativo:
- Permissões delegadas:ToDoList.Read e ToDoList.ReadWrite.
- Permissões de aplicativos:ToDoList.Read.All e ToDoList.ReadWrite.All.
Quando um usuário ou aplicativo cliente chama a API da Web, somente os clientes com esses escopos ou permissões são autorizados a acessar o ponto de extremidade protegido.
{
"AzureAd": {
"Instance": "Enter_the_Authority_URL_Here",
"TenantId": "Enter_the_Tenant_Id_Here",
"ClientId": "Enter_the_Application_Id_Here",
"Scopes": {
"Read": ["ToDoList.Read", "ToDoList.ReadWrite"],
"Write": ["ToDoList.ReadWrite"]
},
"AppPermissions": {
"Read": ["ToDoList.Read.All", "ToDoList.ReadWrite.All"],
"Write": ["ToDoList.ReadWrite.All"]
}
},
"Logging": {...},
"AllowedHosts": "*"
}
Implementar autenticação e autorização na API
Para configurar a autenticação e autorização, abra o arquivo program.cs e substitua seu conteúdo os seguintes trechos de código:
Adicionar um esquema de autenticação
Nesta API, usamos o esquema JSON Web Token (JWT) Bearer como o mecanismo de autenticação padrão. Use o método AddAuthentication para registrar o esquema de portador JWT.
// Add required packages to your imports
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add an authentication scheme
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration);
Crie o modelo do seu aplicativo
Na pasta raiz do projeto, crie uma pasta chamada Modelos. Navegue até a pasta Modelos e crie um arquivo chamado ToDo.cs e adicione o código a seguir.
using System;
namespace ToDoListAPI.Models;
public class ToDo
{
public int Id { get; set; }
public Guid Owner { get; set; }
public string Description { get; set; } = string.Empty;
}
O código anterior cria um modelo chamado ToDo. Esse modelo representa os dados gerenciados pelo aplicativo.
Adicionar um contexto de banco de dados
Em seguida, definimos uma classe de contexto de banco de dados, que coordena a funcionalidade do Entity Framework para um modelo de dados. Essa classe herda da classe Microsoft.EntityFrameworkCore.DbContext que gerencia interações entre o aplicativo e o banco de dados. Para adicionar o contexto do banco de dados, execute estas etapas:
Crie uma pasta chamada DbContext na pasta raiz do seu projeto.
Navegue até a pasta DbContext e crie um arquivo chamado
ToDoContext.cse adicione o seguinte código:using Microsoft.EntityFrameworkCore; using ToDoListAPI.Models; namespace ToDoListAPI.Context; public class ToDoContext : DbContext { public ToDoContext(DbContextOptions<ToDoContext> options) : base(options) { } public DbSet<ToDo> ToDos { get; set; } }Abra o arquivo Program.cs na pasta raiz do seu projeto e atualize-o com o seguinte código:
// Add the following to your imports using ToDoListAPI.Context; using Microsoft.EntityFrameworkCore; //Register ToDoContext as a service in the application builder.Services.AddDbContext<ToDoContext>(opt => opt.UseInMemoryDatabase("ToDos"));
No trecho de código anterior, registramos o Contexto de Banco de Dados como um serviço com escopo no provedor de serviços de aplicativo ASP.NET Core (também conhecido como contêiner de injeção de dependência). Você também configura a ToDoContext classe para usar um banco de dados na memória para a API de lista de tarefas.
Configurar um controlador
Os controladores normalmente implementam ações de Criar, Ler, Atualizar e Excluir (CRUD) para gerenciar recursos. Como este tutorial se concentra mais na proteção dos pontos de extremidade da API, implementamos apenas dois itens de ação no controlador. Uma ação de leitura total para recuperar todos os itens To-Do e uma ação de criação para adicionar um novo item To-Do. Siga estas etapas para adicionar um controlador ao seu projeto:
Navegue até a pasta raiz do seu projeto e crie uma pasta chamada Controllers.
Crie um ficheiro chamado
ToDoListController.csdentro da pasta Controllers e adicione o seguinte código padrão:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.Resource;
using ToDoListAPI.Models;
using ToDoListAPI.Context;
namespace ToDoListAPI.Controllers;
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ToDoListController : ControllerBase
{
private readonly ToDoContext _toDoContext;
public ToDoListController(ToDoContext toDoContext)
{
_toDoContext = toDoContext;
}
[HttpGet()]
[RequiredScopeOrAppPermission()]
public async Task<IActionResult> GetAsync(){...}
[HttpPost]
[RequiredScopeOrAppPermission()]
public async Task<IActionResult> PostAsync([FromBody] ToDo toDo){...}
private bool RequestCanAccessToDo(Guid userId){...}
private Guid GetUserId(){...}
private bool IsAppMakingRequest(){...}
}
Adicionar código ao controlador
Esta seção explica como adicionar código ao controlador estruturado na seção anterior. O foco aqui é proteger a API, não criá-la.
Importe os pacotes necessários: O
Microsoft.Identity.Webpacote é um wrapper em torno MSAL.NET que nos ajuda a lidar facilmente com a lógica de autenticação, como lidar com a validação de token. Para garantir que nossos endpoints exijam autorização, usamos o pacote embutidoMicrosoft.AspNetCore.Authorization.Como concedemos permissões para que essa API seja chamada usando permissões delegadas em nome do usuário ou permissões de aplicativo em que o cliente chama como ele mesmo e não em nome do usuário, é importante saber se a chamada está sendo feita pelo aplicativo em seu próprio nome. A maneira mais fácil de fazer isso é descobrir se o token de acesso contém a
idtypdeclaração opcional. Essaidtypdeclaração é a maneira mais fácil para a API determinar se um token é um token de aplicativo ou um token de aplicativo + de usuário. Recomendamos ativar aidtypdeclaração opcional.Se a
idtypdeclaração não estiver habilitada, você poderá usar asrolesdeclarações escppara determinar se o token de acesso é um token de aplicativo ou um token de aplicativo + de usuário. Um token de acesso emitido pelo Microsoft Entra ID tem pelo menos uma das duas declarações. Os tokens de acesso emitidos para um utilizador têm ascpdeclaração. Os tokens de acesso emitidos para um aplicativo têm arolesreivindicação. Os tokens de acesso que contêm ambas as declarações são emitidos apenas para usuários, onde ascpdeclaração designa as permissões delegadas, enquanto arolesdeclaração designa a função do usuário. Tokens de acesso que não têm nenhum dos dois atributos não devem ser aceites.private bool IsAppMakingRequest() { if (HttpContext.User.Claims.Any(c => c.Type == "idtyp")) { return HttpContext.User.Claims.Any(c => c.Type == "idtyp" && c.Value == "app"); } else { return HttpContext.User.Claims.Any(c => c.Type == "roles") && !HttpContext.User.Claims.Any(c => c.Type == "scp"); } }Adicione uma função auxiliar que determine se a solicitação que está sendo feita contém permissões suficientes para executar a ação pretendida. Verifique se é o aplicativo que está fazendo a solicitação em seu próprio nome ou se o aplicativo está fazendo a chamada em nome de um usuário que possui o recurso determinado, validando o ID do usuário.
private bool RequestCanAccessToDo(Guid userId) { return IsAppMakingRequest() || (userId == GetUserId()); } private Guid GetUserId() { Guid userId; if (!Guid.TryParse(HttpContext.User.GetObjectId(), out userId)) { throw new Exception("User ID is not valid."); } return userId; }Insira as suas definições de permissão para proteger as rotas. Proteja sua API adicionando o
[Authorize]atributo à classe do controlador. Isso garante que as ações do controlador possam ser chamadas somente se a API for chamada com uma identidade autorizada. As definições de permissão definem quais tipos de permissões são necessários para executar essas ações.[Authorize] [Route("api/[controller]")] [ApiController] public class ToDoListController: ControllerBase{...}Adicione permissões aos endpoints GET e POST. Faça isso usando o método RequiredScopeOrAppPermission que faz parte do namespace Microsoft.Identity.Web.Resource . Em seguida, você passa escopos e permissões para esse método por meio dos atributos RequiredScopesConfigurationKey e RequiredAppPermissionsConfigurationKey .
[HttpGet] [RequiredScopeOrAppPermission( RequiredScopesConfigurationKey = "AzureAD:Scopes:Read", RequiredAppPermissionsConfigurationKey = "AzureAD:AppPermissions:Read" )] public async Task<IActionResult> GetAsync() { var toDos = await _toDoContext.ToDos! .Where(td => RequestCanAccessToDo(td.Owner)) .ToListAsync(); return Ok(toDos); } [HttpPost] [RequiredScopeOrAppPermission( RequiredScopesConfigurationKey = "AzureAD:Scopes:Write", RequiredAppPermissionsConfigurationKey = "AzureAD:AppPermissions:Write" )] public async Task<IActionResult> PostAsync([FromBody] ToDo toDo) { // Only let applications with global to-do access set the user ID or to-do's var ownerIdOfTodo = IsAppMakingRequest() ? toDo.Owner : GetUserId(); var newToDo = new ToDo() { Owner = ownerIdOfTodo, Description = toDo.Description }; await _toDoContext.ToDos!.AddAsync(newToDo); await _toDoContext.SaveChangesAsync(); return Created($"/todo/{newToDo!.Id}", newToDo); }
Configurar o middleware da API para usar o controlador
Em seguida, configuramos o aplicativo para reconhecer e usar controladores para lidar com solicitações HTTP. Abra o program.cs arquivo e adicione o código a seguir para registrar os serviços do controlador no contêiner de injeção de dependência.
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
No trecho de código anterior, o AddControllers() método prepara o aplicativo para usar controladores registrando os serviços necessários enquanto MapControllers() mapeia as rotas do controlador para lidar com solicitações HTTP de entrada.
Executa a tua API
Execute sua API para garantir que ela esteja sendo executada sem erros usando o comando dotnet run. Se pretender usar o protocolo HTTPS mesmo durante o teste, precisa confiar no certificado de desenvolvimento do .NET.
Inicie o aplicativo digitando o seguinte no terminal:
dotnet runUma saída semelhante à seguinte deve ser exibida no terminal, confirmando que a aplicação está a ser executada em
http://localhost:{port}e a aguardar solicitações.Building... info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:{port} info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. ...
A página da Web http://localhost:{host} exibe uma saída semelhante à imagem a seguir. Isso ocorre porque a API está sendo chamada sem autenticação. Para fazer uma chamada autorizada, consulte Próximas etapas para obter orientação sobre como acessar uma API da Web protegida.
Para obter um exemplo completo do código desta API, consulte o arquivo de exemplos .