Sitemap

Criando uma api para autenticação de frontends com .NET — parte 1

7 min readOct 14, 2025

Desenvolvedores frontend sempre se deparam com desafios na hora de fazer login em aplicações Angular, React, Vue, ou simplesmente javascript, pois isso depende do backend, muitas vezes não tem nenhuma ferramenta destas disponível para utilizar.

Numa aula que ministrei desenvolvi uma aplicação básica em .NET para ajudar aos alunos a realizarem os processos necessários para integrarem as aplicações que fizeram na aula de outro professor responsável pelo frontend.

Então resolvi colocar aqui o exemplo e disponibilizar no github seu fonte, caso mais alguém tenha a necessidade de utilizar nas suas aplicações, já serve como base para começar….

O Projeto

Para estas funcionalidades, precisaremos de uma Web Api, que será feita no .NET 9 e iremos utilizar algumas bibliotecas para incluir as funcionalidades de autenticação.

Então para começar, vamos abrir o Visual Studio e criar um novo projeto:

Press enter or click to view image in full size

Depois de escolhido o modelo, dê o nome do projeto e escolha uma pasta

Depois defina as configurações da api na próxima tela

Press enter or click to view image in full size

Feito isso, agora o Visual Studio abrirá com o seu projeto seguindo o template padrão do .NET 9.

Press enter or click to view image in full size

O template do projeto possui um exemplo que nós não vamos utilizar, portanto podemos marcar estes itens no program.cs e excluir, ficando seu projeto deste jeito agora:

Press enter or click to view image in full size

Primeiramente, teremos que incluir algumas bibliotecas que não estão presentes na aplicação, podemos fazer via linha de comando ou através do Nuget Package Manager.

São elas:

Microsoft.AspNetCore.Authentication.JwtBearer

Microsoft.AspNetCore.Identity.EntityFrameworkCore

Microsoft.AspNetCore.Identity.UI

Microsoft.AspNetCore.OpenApi

Microsoft.EntityFrameworkCore.Design

Microsoft.EntityFrameworkCore.SqlServer

O código .NET

Feita a preparação da base da aplicação, vamos montar os endpoints base para o processo de gestão de usuários e permissões:

Criando as pastas

Criação de pastas: crie as pastas “Models”, “Data” e “Endpoints”.

Criando as classes

Precisamos criar algumas classes, para poder realizar as requisições para a api, elas devem ser criadas dentro da pasta “Models” criada no passo anterior:

RegisterRequestModel — classe utilizada para registrar um novo usuário

public class RegisterRequestModel
{
[Required]
public string Username { get; set; }

[Required]
[EmailAddress]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "As senhas não coincidem.")]
public string ConfirmPassword { get; set; }

[Required]
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; } = string.Empty;
}

LoginRequestModel — classe utilizada no envio do login

public class LoginRequestModel
{
public required string Email { get; set; }
public required string Password { get; set; }
}

UserResponseModel — classe para retorno de informações do usuário, notem que o construtor está recebendo um “Identity User” que é a classe utilizada na gestão de usuários pelo Asp Net Identity, mas por que? para facilitar a criação da entidade que será uma resposta, para não enviar a classe “IdentityUser” que possui outras informações que não deverão ser compartilhadas fora da aplicação.

public class UserResponseModel
{
public UserResponseModel(IdentityUser user)
{
this.Id = user.Id;
this.Email = user.Email;
this.UserName = user.UserName;
}
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Phone { get; set; } = string.Empty;
}

Criando o Contexto

Para que possamos utilizar Entity Framework para armazenar nossos dados, será preciso criar uma classe de contexto, esta classe é responsável pelo acesso ao banco de dados.

Ela é utilizada para gerar também as migrations do banco de dados

Na pasta “Data”, insira uma nova classe com o nome “AppDbContext” e complemente seu código deixando assim:

namespace UserManagement_Api.Data;

public class AppDbContext : IdentityDbContext<IdentityUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}

O que está acontecendo? Ela herda o modelo de “IdentityDbContext” que é uma implementação utilizada pelo Identity Server (gerenciador de identidades) do .NET, e que fará com que ele já possua métodos prontos para instanciar e manter no banco de dados as entidades de identificação, que serão utilizadas para gerenciar os usuários e acessos.

Criando os Endpoints

Crie uma classe dentro de “Endpoints” chamada “UserEndpoints” esta classe irá conter os endpoints da api, que seguirão o conceito “Minimal Api” do .NET conforme a listagem abaixo:

public static class UserEndpoints
{
public static void MapUserEndpoints(this IEndpointRouteBuilder routes)
{
var group = routes.MapGroup("/api/user").WithTags("User");

group.MapPost("/register", async ([FromServices] UserManager<IdentityUser> userManager, [FromBody] RegisterRequestModel model) =>
{
var user = new IdentityUser { UserName = model.Username, Email = model.Email };
var result = await userManager.CreateAsync(user, model.Password);

return result.Succeeded
? Results.Ok(new { Message = "Usuário registrado com sucesso!" })
: Results.BadRequest(result.Errors);
});

group.MapPost("/login", async ([FromServices] UserManager<IdentityUser> userManager,
[FromServices] IConfiguration config, LoginRequestModel model) =>
{
var user = await userManager.FindByEmailAsync(model.Email);
if (user == null || !await userManager.CheckPasswordAsync(user, model.Password))
return Results.Unauthorized();

// Obtém as roles do usuário
var userRoles = await userManager.GetRolesAsync(user);

// Cria as claims (incluindo roles)
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};

// Adiciona as roles como claims
foreach (var role in userRoles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"]!));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
issuer: config["Jwt:Issuer"],
audience: config["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);

return Results.Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
});

group.MapGet("/users", async ([FromServices] UserManager<IdentityUser> userManager) =>
{
var users = await userManager.Users.ToListAsync();

List<UserResponseModel> userList = MapUserListResponse(users);

return Results.Ok(userList);
});

group.MapGet("/users/{id}", async ([FromServices] UserManager<IdentityUser> userManager, [FromQuery] string id) =>
{
var user = await userManager.FindByIdAsync(id);
return user != null ? Results.Ok(new UserResponseModel(user)) : Results.NotFound();
});

group.MapPut("/users/{id}", async ([FromServices] UserManager<IdentityUser> userManager,
[FromQuery] string id, [FromBody] UpdateUserRequestModel model) =>
{
var user = await userManager.FindByIdAsync(id);
if (user == null)
return Results.NotFound();

user.Email = model.Email;
user.UserName = model.Username;

var result = await userManager.UpdateAsync(user);
return result.Succeeded ? Results.Ok(user) : Results.BadRequest(result.Errors);
});

group.MapDelete("/users/{id}", async ([FromServices] UserManager<IdentityUser> userManager,
[FromQuery] string id) =>
{
var user = await userManager.FindByIdAsync(id);
if (user == null)
return Results.NotFound();

var result = await userManager.DeleteAsync(user);
return result.Succeeded
? Results.Ok(new { Message = "Usuário deletado com sucesso." })
: Results.BadRequest(result.Errors);
});
}

private static List<UserResponseModel> MapUserListResponse(List<IdentityUser> users)
{
var userList = new List<UserResponseModel>();
foreach (var item in users)
{
userList.Add(new UserResponseModel(item));
}

return userList;
}
}

Criada esta classe, veja alguns detalhes dela:

  • temos vários endpoints que permitem interagir com a entidade do usuário, desde o seu cadastramento até a sua listagem ou consulta.

Observe a figura abaixo, ela mostra um trecho de código da classe UserEndpoints, no item A, ela define o grupo da rota como “api/user”, desta forma, todos os endpoints declarados internamente terão como seu sufixo “api/user”.

O Item B, cria um endpoint “register” que ficará na rota “api/user/register” o qual será responsável pela inclusão de novos usuários, através do método Post da api, enviando um objeto do tipo “RegisterRequestModel” e devolvendo uma mensagem de sucesso em caso de salvamento bem sucedido ou de erro em caso de não conseguir gravar.

Não há neste momento inicial nenhum tipo de validação, já que o propósito é criar um endpoint mais simples possível para permitir a inclusão de novos usuários.

Press enter or click to view image in full size

Para que tudo isso funcione, teremos que incluir mais coisas no nosso program.cs

Passo 1 — Criar usuário

Primeiramente vamos criar um usuário, utilizando a chamada de criação do usuário através da api

Press enter or click to view image in full size

fazendo esta chamada criamos o novo usuário que utilizaremos nos testes!

Depois disso, precisamos testar o login !

Passo 2 — Login

Ao realizar o login temos a seguinte resposta:

Press enter or click to view image in full size

O que tem dentro do Jwt

Press enter or click to view image in full size

Mas daí, o que isso quer dizer? ele diz que foi feita uma autorização do usuário e qual é o e-mail dele, mas não sabemos se qual é o perfil do usuário! Se ele é um admin ou um usuário, e como fazer isso agora?

Bom, para definir o que ele pode ou não acessar, precisaremos utilizar Papéis (Roles) e Declarações (Claims).

Até aqui já temos bastante coisa, aguarde a publicação da parte II onde continuaremos com mais configurações e testes!

Gostou do artigo? clique no ícone👏e também me siga nosso perfil no medium para ver as próximas publicações !! Quer ver mais conteúdos, acesse minhas redes através do Linktree: https://linktree.com/nizzola

--

--

Marcio Nizzola
Marcio Nizzola

Written by Marcio Nizzola

Microsoft MVP | Master Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.

No responses yet