Alura > Cursos de Programação > Cursos de .NET > Conteúdos de .NET > Primeiras aulas do curso Segurança com ASP.NET Core: proteja suas Web APIs

Segurança com ASP.NET Core: proteja suas Web APIs

Registro e Login com ASP.NET Identity - Introdução

Apresentando o curso e o instrutor

Você sabe como garantir a segurança das suas APIs? Neste curso, vamos aprender a proteger nossos projetos ASP.NET Core Web API utilizando autenticação, autorização, papéis de usuário e proteção contra ataques.

Meu nome é Marcelo Oliveira, faço parte da Escola de Programação da Alura, e para fins de acessibilidade, vou me autodescrever.

Audiodescrição: Marcelo é um homem branco, com cabelos e barba pretos, olhos escuros e usa óculos. Ele veste uma camiseta cinza e azul e está em um ambiente com fundo branco, iluminado por uma luz verde azulada.

Explorando autenticação e autorização em APIs

Na primeira aula, vamos aprender sobre autenticação e autorização em APIs. Vamos apresentar um novo projeto ASP.NET Core, desta vez uma Web API da clínica Vomad, para gravar e ler informações da clínica. Nós vamos explorar as diferenças entre autenticação e autorização, passando por todo o fluxo, desde o login do usuário até o momento em que ele terá o acesso concedido ou negado à nossa API, de acordo com as políticas de segurança.

Na primeira aula, aprenderemos a adicionar um controlador novo para realizar a autenticação. Vamos aprender a registrar um usuário, cadastrar um novo usuário e realizar o login.

Gerando e configurando tokens JWT

Na Aula 2, vamos aprender sobre a geração de token JWT. Aprenderemos a definir um serviço de geração de token.

Vamos configurar o Swagger para criar um botão de autorização, onde preencheremos o token da pessoa usuária. Configuraremos a aplicação para que os endpoints validem esse token, verificando se ele é válido.

Implementando o Refresh Token

Na Aula 3, aprenderemos sobre o Refresh Token. O Refresh Token servirá para a renovação do nosso token, ajudando a prolongar o uso da API pela pessoa usuária, evitando a necessidade de novas autenticações frequentes. Também aprenderemos a armazenar esse token de renovação no banco de dados.

Gerenciando papéis e políticas de segurança

Na Aula 4, aprenderemos a trabalhar com políticas. Criaremos um novo controlador para gerenciar os papéis, registrando novos papéis, como financeiro, e atribuindo papéis às pessoas usuárias.

Implementando boas práticas de segurança

Na última aula, aprenderemos a implementar boas práticas de segurança em um projeto AspNet Core Web API. Por exemplo, aprenderemos a proteger nossa API contra ataques utilizando HTTPS e HSTS. Também aprenderemos a incluir papéis no token JWT, para que essas informações estejam gravadas no token, eliminando a necessidade de acessar o banco de dados constantemente. Além disso, aprenderemos a implementar uma política de CORS, permitindo que outras aplicações, como a aplicação MVC que estamos utilizando, possam acessar nossa API para obter informações ou gravar dados.

Concluindo o curso e incentivando o aprendizado contínuo

No final, o conhecimento adquirido no curso de segurança com AspNet Core parte 2 proporcionará a base necessária para construir APIs mais seguras. Aproveitemos os recursos da plataforma Alura, que além dos vídeos, oferece atividades, apoio no fórum e na comunidade do Discord. Vamos estudar?

Registro e Login com ASP.NET Identity - Adicionando Autorização e Autenticação

Preparando o ambiente e introduzindo o Swagger

Na atividade "Preparando o Ambiente", trabalhamos com um novo tipo de projeto, a AspNet Core Web API. Agora, vamos adicionar uma camada de segurança a esse projeto. Já aprendemos a baixar o código inicial, e temos na tela o Visual Studio com esse código. Vamos executar o código utilizando a tecla F5, o que abrirá a página medivol.webapi. Essa página é fornecida pelo Swagger, uma biblioteca que oferece uma interface gráfica para realizar requisições na aplicação Web API sem a necessidade de utilizar programas como Postman ou Curl, ou implementar um código para fazer a requisição. Nosso projeto já vem configurado com o Swagger, permitindo interagir diretamente com a API.

Vamos realizar um teste. Após baixar o código inicial, podemos listar, por exemplo, as consultas médicas. Na seção de consultas, acessamos o endpoint de listagem de consultas médicas na API clicando no botão Get. Em seguida, clicamos em Try it out e, mais abaixo, no botão Execute. Isso executa a requisição para a listagem de consultas da API, que fornecerá uma resposta em formato JSON contendo todas as consultas médicas.

Testando a listagem de dados e identificando problemas de segurança

Se quisermos listar os dados de médicos, descemos na página até a seção de médicos, correspondente ao controller de médicos. Lá, encontramos o endpoint API/médico/listar e clicamos no botão Get. Novamente, clicamos em Try it out e, mais abaixo, em Execute. Isso executa a requisição para a listagem de médicos, e a resposta da API será uma listagem JSON com todas as informações de médicos.

Percebemos que a API está fornecendo informações sensíveis e confidenciais de médicos, consultas e pacientes, mesmo sem saber quem está acessando. Isso é um problema significativo. Ao longo do curso, implementaremos autenticação e autorização no projeto AspNet Core Web API para resolver esses problemas de segurança.

Explicando o fluxo de autenticação e autorização

O fluxo básico de autenticação e autorização na API funciona da seguinte forma: o usuário faz login com suas credenciais, obtendo um token de autenticação. Com esse token, ele acessa a API uma ou mais vezes, sempre passando o token. A API verifica a permissão, analisando o token, que não contém usuário nem senha, mas indica se o usuário tem permissão para o recurso requisitado. A partir daí, a API concede ou nega acesso ao recurso protegido, implementando a segurança.

Implementando segurança nos controllers

Voltando ao projeto, vamos abrir o arquivo program.cs. Nas linhas 38 e 40, encontramos as linhas app.useAuthentication e app.useAuthorization. Essas linhas vieram do projeto anterior, o AspNetCore MVC, no qual implementamos segurança no primeiro curso desta formação. Herdamos essas linhas, mas elas são apenas um ponto de partida e não garantem segurança por si só. Precisamos implementar, nos controllers, uma forma de proteger os endpoints para evitar o acesso de usuários não autenticados.

Vamos localizar na pasta "controllers" o arquivo consultacontroller.cs. Na linha 11, encontramos a declaração da classe public class consultacontroller. Queremos proteger todos os endpoints do controller de consultas. Para isso, na linha 11, adicionaremos uma nova linha com um atributo entre colchetes, que é o atributo Authorize.

[Authorize]

No arquivo medicocontroller.cs, na linha 12, temos a declaração da classe medicocontroller. Também desejamos proteger todos os endpoints desse controller, colocando na linha 11 um atributo Authorize.

[Authorize]

Esse atributo restringirá o acesso aos endpoints, exigindo que as pessoas usuárias estejam autenticadas e autorizadas com base em papéis ou políticas definidas. Caso esses papéis e políticas não estejam configurados, ele verificará apenas se a pessoa usuária está autenticada, o que já representa um primeiro nível de segurança que aplicaremos.

Configurando a autenticação com JWT

Agora, abriremos o arquivo program.cs novamente e configuraremos a autenticação através do token. Localizaremos a linha 28, quebraremos algumas linhas e colocaremos na linha 29 o código que será extraído da transcrição deste vídeo. Para facilitar, podemos copiar e colar. Ao copiar e colar, como estamos fazendo na linha 28, adicionamos o middleware com o método AddAuthentication. Esse método adiciona uma forma de autenticação através do token, utilizando o que chamamos de JWTBearer, que é um token ao portador.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();

No entanto, não basta apenas inserir essa linha; também precisamos configurar o arquivo appsettings.json. Vamos abrir o appsettings.json e, na linha 11, encontraremos a configuração allowed hosts. No final da linha, colocaremos uma vírgula e a configuração que também será copiada da transcrição deste vídeo.

"AllowedHosts": "*",

Essa configuração, na linha 12, possui o nome JWTTokenConfiguration, que é a configuração do token JWT, pois JWT é o tipo de token que utilizaremos neste curso. Aqui, temos algumas propriedades interessantes: a audiência, que é o público, ou seja, VOMED, pois não aceitaremos qualquer token de qualquer lugar ou sistema. Esse token precisa ser destinado para VOMED. Na linha 14, temos o emissor, que em inglês é issuer, e esse emissor é a Alura. Portanto, o token deve vir da Alura e ser destinado para VOMED. Nas linhas 15 e 16, temos a expiração desse token em minutos: 30 minutos para expiração e 120 minutos para renovação do token. Assim, cada vez que o token expira, ele precisa ser renovado, controlado por essas configurações.

"JWTTokenConfiguration": {
    "Audience": "vollmed",
    "Issuer": "alura",
    "ExpireInMinutes": 30,
    "RefreshExpireInMinutes": 120
}

Testando a proteção dos endpoints

Agora, vamos rodar o código novamente, executando nossa aplicação com a tecla F5. Tentaremos acessar a API para listar os dados de médicos da nossa aplicação. Após a execução, iremos para o endpoint de listagem de médicos, clicando no botão get ao lado de api-médico-listar, e em seguida no botão try it out e no botão execute. Desta vez, recebemos um código 401, em vez do código 200 ok, que trazia toda a lista de médicos. Isso significa que conseguimos proteger com sucesso os recursos da nossa API, pois o status code 401 indica que ainda não temos permissão para acessar o endpoint, já que não estamos passando o token obrigatório.

Concluindo a implementação inicial de segurança

O próximo passo é descobrir como obter esse token para liberar o acesso. Assim, sempre que fizermos uma requisição para nossa API, será obrigatório passar esse token. Neste vídeo, iniciamos a implementação da autenticação e autorização, configurando o middleware de token, de autenticação, e também adicionando o atributo Authorize nos nossos controladores. Ao testar nossa aplicação, encontramos um erro 401, indicando que o recurso existe, mas não foi concedido, pois não estamos emitindo o token necessário para realizar a requisição. Com isso, encerramos este primeiro vídeo e, na sequência, configuraremos o Swagger para que possamos informar esse token nas nossas requisições na API.

Registro e Login com ASP.NET Identity - Adicionando Controlador de Autenticação

Introduzindo a necessidade de autenticação de usuários

No último vídeo, configuramos nossa API com autenticação e autorização, mas a configuração ainda não está completa. Nossos endpoints estão protegidos, porém, ainda não temos uma maneira de permitir que nossos usuários se autentiquem na plataforma. Vamos abordar isso agora.

Para autenticar um usuário, precisamos primeiro criar uma classe que armazenará os dados desse usuário, como e-mail e senha. Vamos criar essa classe no projeto, dentro da pasta "DTOs". Clique com o botão direito, selecione o menu "Adicionar", "Classe", e escolha o nome da classe, que será UsuarioDTO. Após adicionar a classe, vamos definir as duas propriedades: e-mail e senha. Assim, temos a classe UsuarioDTO com as propriedades necessárias para o usuário se autenticar.

Criando a classe UsuarioDTO

Primeiro, criamos a estrutura básica da classe UsuarioDTO:

namespace MedVoll.WebAPI.Dtos
{
    public class UsuarioDto
    {
    }
}

Agora, vamos adicionar as propriedades de e-mail e senha à classe UsuarioDTO:

public string? Email { get; set; }
public string? Senha { get; set; }

Implementando o AuthController

Após criar a classe UsuarioDTO, precisamos de uma forma de autenticar o usuário. Em um projeto ASP.NET Core Web API, devemos criar um controller com endpoints para cadastro e login do usuário. Vamos criar uma nova classe para o controlador de autenticação. Na pasta "Controllers", clique com o botão direito e adicione uma nova classe. Nomeie-a como AuthController, com "C" maiúsculo, e pressione "Enter" para criar uma classe vazia.

A estrutura inicial do AuthController é a seguinte:

namespace MedVoll.WebAPI.Controllers
{
    public class AuthController
    {
    }
}

Agora, precisamos implementar essa classe. Podemos observar que a classe AuthController possui dois objetos injetados através do construtor: UserManager e SignInManager. Esses objetos gerenciam os dados de usuário e credenciais, além de outras informações pertinentes à autenticação. Isso faz parte da biblioteca ASP.NET Core Identity, declarada na linha 2 como microsoft.aspnetcore.identity. O Identity fornece ferramentas para manipular usuários, realizar cadastro, login, autenticação, gerenciar papéis de usuário, entre outras funcionalidades relacionadas à autenticação e autorização. Embora seja possível utilizar outra biblioteca, o ASP.NET Core Identity é mais prático e integrado ao ASP.NET Core.

Configurando os endpoints de autenticação

Vamos agora adicionar a implementação completa do AuthController com os objetos injetados e a configuração dos endpoints:

using MedVoll.Web.Dtos;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace MedVoll.Web.Controllers;

[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly UserManager<IdentityUser> userManager;
    private readonly SignInManager<IdentityUser> signInManager;
    public AuthController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
    {
        this.userManager = userManager;
        this.signInManager = signInManager;
    }

    //Endpoints
}

Agora que temos a classe AuthController, precisamos criar os endpoints para cadastro e login de usuário.

Adicionando métodos de registro e login

Para isso, vamos adicionar os métodos para registrar e autenticar o usuário:

[HttpPost("registrar-usuario")]
public async Task<IActionResult> RegistrarUsuarioAsync([FromBody] UsuarioDto usuarioDto)
{
    var usuarioReg = await userManager.FindByEmailAsync(usuarioDto.Email);
    if (usuarioReg is not null)
    {
        return BadRequest("Usuário já foi registrado na base de dados.");
    }

    var usuario = new IdentityUser
    {
        UserName = usuarioDto.Email,
        Email = usuarioDto.Email,
        EmailConfirmed = true
    };

    var result = await userManager.CreateAsync(usuario, usuarioDto.Senha);
    if (!result.Succeeded)
    {
        return BadRequest($"Falha ao registrar usuário : {result.Errors}");
    }
    await signInManager.SignInAsync(usuario, isPersistent: false);

    return Ok("Usuário Criado com sucesso!");
}

[HttpPost("login")]
public async Task<IActionResult> LoginAsync([FromBody] UsuarioDto usuarioDto)
{
    var result = await signInManager.PasswordSignInAsync(usuarioDto.Email, usuarioDto.Senha, isPersistent: false, lockoutOnFailure: false);
    if (!result.Succeeded)
    {
        return BadRequest("Falha no login do usuário.");
    }
    return Ok("Logado com sucesso!");
}

Testando a aplicação com Swagger

Agora que já temos as classes UsuarioDTO e AuthController, vamos testar a aplicação pressionando a tecla F5. Vamos esperar a aplicação iniciar com a página do Swagger, onde podemos encontrar o controle de autenticação com os novos endpoints que cadastramos. A primeira seção já aparece com Auth, que é o nosso controlador AuthController. Temos duas formas de fazer a requisição: o primeiro é registrar usuário, o endpoint para cadastrar o usuário, e o segundo é o endpoint login. Vamos clicar para fazer o login, clicando em post para realizar o login do usuário. No campo preto, temos os valores para a requisição. Vamos clicar em try it out, o que transforma o quadro preto em branco, permitindo editar os dados da requisição. No corpo da requisição, temos e-mail e senha. O Swagger transformou essas duas propriedades em um objeto no formato JSON, facilitando o teste das aplicações Web API.

No campo de e-mail, vamos inserir o e-mail já cadastrado no projeto, que é Alice, com C, alice@smith.com. Para a senha, substituímos "string" por "Password@123", que é a senha cadastrada para Alice. Em seguida, clicamos no botão azul execute, que chama a API do endpoint de login cadastrado neste vídeo. No final, obtemos o resultado com HTTP 200, indicando sucesso, com a mensagem "logado com sucesso", confirmando que o login foi realizado sem problemas e que o usuário foi reconhecido com a senha de Alice.

Concluindo a implementação de autenticação

Além disso, não temos mais informações no momento, mas veremos na sequência como obter mais dados no resultado. Por enquanto, já temos uma forma de autenticar o usuário e cadastrar novos usuários conforme necessário. Neste vídeo, aprendemos a criar um novo controlador de autenticação, um novo endpoint para login de usuário e outro para cadastro de usuário. Existem várias formas de realizar autenticação em .NET, e o ASP.NET Core Identity foi escolhido por ser uma solução completa, flexível, integrada ao ecossistema .NET e fácil de trabalhar no projeto. O Identity oferece suporte nativo a registro, login, redefinição de senha e controle de acesso baseado em papéis.

Para concluir, este vídeo mostrou como realizar a autenticação e login de usuários. Na sequência, vamos definir o serviço de token para a nossa API.

Sobre o curso Segurança com ASP.NET Core: proteja suas Web APIs

O curso Segurança com ASP.NET Core: proteja suas Web APIs possui 169 minutos de vídeos, em um total de 37 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas