Este artigo é parte da série:

Na maior parte das vezes, a melhor forma de garantir a segurança da nossa API será através da tramitação de um token gerado dinamicamente para identificar o usuário que está a está chamando e os direitos que ele possui. No caso do C#, a Microsoft tem até uma biblioteca inteira destinada a isso, que é o Identity Framework, mas não iremos falar dele neste momento e sim como tratar esses tokens.
O token poderia ser apenas mais um parâmetro da função a ser chamada, por exemplo:
public function int Soma (int ValorA, int ValorB, string Token) {...}
Os motivos pelos quais não se deve fazer desta forma serão descrirtos em outro artigo mas, por hora, vamos nos atentar ao fato de que o token deve ser transmitido dentro do HTTP header na diretiva “Authorization”. No exemplo abaixo, os HTTP headers de uma requisição tipo POST e conteúdo JSON, que é a grande maioria dos casos. Ainda a título de exemplo, vamos usar o token “123456”.
authorization: bearer <seu token>
accept: text/plain
content-type: application/json
Como Ler o HTTP Header no C#
É bem simples: basta colar a linha abaixo:
string token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
Exemplo aplicado dentro de uma função cujo token tem que ser “123456”:
/// <summary> /// Soma dois números /// </summary> /// <param name="ValorA">Primeiro valor a ser somado</param> /// <param name="ValorB">Segundo valor a ser somado</param> /// <returns>A soma do primeiro valor com o segundo valor</returns> [HttpPost("Soma")] public ActionResult<int> Soma(int ValorA, int ValorB) { string token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); if (token != "123456") { return Unauthorized($"Acesso não autorizado. Token: [{token}]"); } int ret = ValorA + ValorB; return Ok(ret); }
Dessa forma, conseguimos com muita facilidade validar um token manualmente dentro de cada uma das funções, embora haja muitas formas bem mais sofisticadas de fazer isso.
Como Configurar o Swagger para Enviar o Token
Efetuando o procedimento acima, não mais será possível testar a função “Soma” no Swagger, uma vez que não teremos como enviar o token no HTTP header. Para que isso seja possível, faça a seguinte modificação no método AddSwaggerGen() em Program.cs:
using Microsoft.OpenApi.Models; using System.Reflection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Minha API", Description = "Descrição da minha API", }); options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "Digite o token.", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, Array.Empty<string>() } }); });
Como Fazer a Autenticação a Nível Global
Até o momento estamos fazendo a autenticação manualmente dentro de cada função, porém podemos configurar a REST API para fazer a autenticação a nível global, desta forma não será necessário realizar este processo dentro de cada função.
A título de exemplo, farei aqui uma autenticação manual bem simples. Tudo o que faremos é verificar se o bearer token é igual a “123456”. Com este exemplo fica fácil de você implementar a sua própria lógica para cada programa.
app.UseRouting(); // Autenticação app.Use(async (context, next) => { var endpoint = context.GetEndpoint(); if (endpoint != null && endpoint.Metadata.GetMetadata<Microsoft.AspNetCore.Authorization.AuthorizeAttribute>() != null) { if (!context.Request.Headers.TryGetValue("Authorization", out var authHeader)) { context.Response.StatusCode = 401; await context.Response.WriteAsync("Missing Authorization Header"); return; } var token = authHeader.ToString().Split(' ').Last(); if (token != "123456") { context.Response.StatusCode = 401; await context.Response.WriteAsync("Invalid Token"); return; } var claims = new[] { new Claim(ClaimTypes.Name, "AuthenticatedUser") }; var identity = new ClaimsIdentity(claims, "Bearer"); var principal = new ClaimsPrincipal(identity); context.User = principal; } await next(); }); app.UseAuthentication(); app.UseAuthorization();
Feito isso, vai bastar adicionar a diretiva [Authorize] às funções que necessitam autenticação, no caso da rotina “Soma” que fizemos acima, ela ficaria assim:
/// <summary> /// Soma dois números /// </summary> /// <param name="ValorA">Primeiro valor a ser somado</param> /// <param name="ValorB">Segundo valor a ser somado</param> /// <returns>A soma do primeiro valor com o segundo valor</returns> [HttpPost("Soma")] [Authorize] public ActionResult<int> Soma(int ValorA, int ValorB) { string token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); if (token != "123456") { return Unauthorized($"Acesso não autorizado. Token: [{token}]"); } int ret = ValorA + ValorB; return Ok(ret); }
Os métodos que não tiverem a diretiva [Authorize] funcionarão de qualquer forma, sem validação do token de autenticação.
Exemplo Completo
Se você está acompanhando a série de artigos explicando como construir uma REST API do zero, nosso “Program.cs” ficou da seguinte forma:
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using System.Reflection; using System.Security.Claims; using System.Text; using System.Text.Encodings.Web; using Treino_REST_02.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Swagger // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(opts => { opts.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Treino REST API", Description = "Como desenvolver um REST API utilizando C# e .NET Core", TermsOfService = new Uri("https://www.larsoft.com.br/autenticacao-em-2-fatores-2fa-nos-sistemas-larsoft/"), Contact = new OpenApiContact { Name = "Entre em contato com a Larsoft", Url = new Uri("https://www.larsoft.com.br/institucional/contato/") }, License = new OpenApiLicense { Name = "Como a Larsoft trata a segurança de dados", Url = new Uri("https://www.larsoft.com.br/institucional/seguranca/") } }); opts.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Name = "Authorization", Description = "Digite o token.", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); opts.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, Array.Empty<string>() } }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); opts.IncludeXmlComments(xmlPath, true); }); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); app.UseHttpsRedirection(); app.UseRouting(); // Autenticação app.Use(async (context, next) => { if (!context.Request.Headers.TryGetValue("Authorization", out var authHeader)) { context.Response.StatusCode = 401; await context.Response.WriteAsync("Missing Authorization Header"); return; } var token = authHeader.ToString().Split(' ').Last(); if (token != "123456") { context.Response.StatusCode = 401; await context.Response.WriteAsync("Token inválido"); return; } var claims = new[] { new Claim(ClaimTypes.Name, "AuthenticatedUser") }; var identity = new ClaimsIdentity(claims, "Bearer"); var principal = new ClaimsPrincipal(identity); context.User = principal; await next(); }); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List<string> { "index.html" } }); app.UseStaticFiles(); app.Run();
Agora, ao executar o Swagger, haverá um botão “Authorize” para que você possa entrar com o token.

Uma vez que tenha entrado com o token, todas as requisições feitas no Swagger daqui para frente, vão carregar o HTTP header “Authorization: Bearer <Token que você digitou>”.
Próxima etapa: