API de autenticação JWT com refresh token, modelagem segura e boas práticas em .NET
- jwtWebApi
- 🌐 Mensagens de Erro e Validação com Tradução Automática
Esta API demonstra autenticação baseada em JWT (JSON Web Token) com suporte a refresh token, controle de usuários, roles e boas práticas de modelagem e segurança.
Ideal para estudos, portfólio e como base para aplicações reais.
- .NET 9
- ASP.NET Core Web API
- Entity Framework Core
- JWT Bearer Authentication
- User Secrets (para configuração segura)
- Swagger (para documentação e testes)
-
Clone o repositório
git clone https://github.com/seuusuario/jwtWebApi.git cd jwtWebApi -
Configure o banco de dados
- Altere a connection string no
appsettings.jsonou use User Secrets.
- Altere a connection string no
-
Configure os secrets do JWT
dotnet user-secrets set "JWT:Secret_Key" "sua-chave-secreta" dotnet user-secrets set "JWT:Audience" "www.seuapp.com"
-
Rode as migrations
dotnet ef database update
-
Execute a aplicação
dotnet run
-
Acesse o Swagger
- Normalmente em: https://localhost:5001/swagger
- appsettings.json: configure connection string e outras opções.
- User Secrets: use para armazenar chaves sensíveis (JWT, etc).
POST /api/v1/auth/register
Content-Type: application/json
{
"login": "edy",
"username": "Edy",
"password": "Senha123!",
"confirmePassword": "Senha123!",
"email": "[email protected]",
"roles": ["Admin"]
}POST /api/v1/auth/login
Content-Type: application/json
{
"login": "edy",
"password": "Senha123!"
}Resposta:
{
"accessToken": "<jwt_token>",
"refreshToken": "<refresh_token>"
}GET /api/v1/user/profile
Authorization: Bearer <jwt_token>POST /api/v1/auth/refresh
Content-Type: application/json
{
"refreshToken": "<refresh_token>"
}Resposta:
{
"accessToken": "<novo_jwt_token>",
"refreshToken": "<novo_refresh_token>"
}Migrations e EF Core
dotnet restore
dotnet ef database update
dotnet run- Usuário faz login e recebe um JWT e um refresh token.
- Usa o JWT para acessar endpoints protegidos.
- Quando o JWT expira, usa o refresh token para obter um novo JWT.
- O refresh token antigo é invalidado e um novo é emitido.
- Refresh tokens são salvos no banco, relacionados ao usuário.
- JWTs são assinados com chave secreta segura.
- Roles são usadas para autorização de endpoints.
- Dados sensíveis nunca ficam hardcoded no código.
- Validação de entrada e tratamento de erros implementados.
Esta API possui suporte completo a localização (i18n) para mensagens de validação de dados, retornando os erros automaticamente no idioma apropriado com base na cultura definida na requisição.
- A API utiliza Data Annotations em conjunto com arquivos
.resxde tradução. - A cultura (
CultureInfo) é detectada automaticamente via header HTTPAccept-Language. - Atualmente são suportados os idiomas:
pt-BR(Português do Brasil)en-US(Inglês Americano)
Ao fazer uma requisição HTTP para a API, basta definir o cabeçalho:
Accept-Language: en-USOu:
Accept-Language: pt-BRA resposta de erro de validação será retornada automaticamente no idioma solicitado.
{
"errors": {
"Password": [
"Password must be at least 6 characters long."
]
}
}Os arquivos de tradução estão localizados na pasta:
/Resources/JwtWebApi.Dto.UserDto.[cultura].resx
/Resources/Outros..
Por exemplo:
JwtWebApi.Dto.UserDto.en-US.resxJwtWebApi.Dto.UserDto.pt-BR.resx
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddControllers()
.AddDataAnnotationsLocalization();
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("pt-BR"),
SupportedCultures = new[] { new CultureInfo("pt-BR"), new CultureInfo("en-US") },
SupportedUICultures = new[] { new CultureInfo("pt-BR"), new CultureInfo("en-US") }
});Como substituir values em tempo de execução.
/Resoures/OrderMessages.resx
<data name="OrderNotification" xml:space="preserve">
<value>Your order ("{0}") has been shipped and is on its way to "{1}".</value>
</data>
app.MapGet("/{orderId}/{address}", (IStringLocalizerFactory factory, string orderId, string address) =>
{
var localizer = factory.Create("OrderMessages", typeof(Program).Assembly.GetName().Name!);
//logica para obter a mensagem de notificação do pedido
// Substituindo os placeholders {0} e {1}
string message = string.Format(localizer["OrderNotification"], orderId, address);
return message;
});
Dúvidas ou sugestões?
Abra uma issue ou entre em contato!
- Faça um fork do projeto
- Crie uma branch (
git checkout -b feature/nova-feature) - Commit suas alterações (
git commit -am 'Adiciona nova feature') - Push para a branch (
git push origin feature/nova-feature) - Abra um Pull Request