9.3 Agregando seguridad a nuestros servicios

Para generar los tokens necesitamos una llave secreta, y los datos del Issuer (quien genera el token) y las urls de las cuales vamos a aceptar la conexión a nuestros servicios.

Vamos a agregar la configuración para generar los tokens en nuestro archivo appsettings.json, de esta forma si luego queremos cambiar los datos para generar los tokens solo debemos reiniciar el servicio y si lo agregamos en nuestro código por ejemplo en nuestro archivo de constantes debemos de generar la dll y luego reemplazarla en el servidor. Si usas devops para subir automáticamente los deploys, puedes agregar constantes en tu código para registrar estos datos. Yo por preferencia personal deseo solo cambiar el appsetings los valores en lugar de compilar y subir versión.

appsettings.json
{
"Tokens": {
"Key": "tullavesecreta",
"Issuer": "http://www.midominio.com/",
"Audience": "http://sistema.midominio.com/",
"AceptedURL": [ "http://www.midominio.com/",
"http://midominio.com/" ]
}
}

En nuestro archivo startup.cs en el método ConfigureServices indicamos que ahora nuestros servicios requieren de seguridad (services.AddAuthentication), en nuestra variable Configuration tenemos acceso a los valores de nuestro archivo appsettings, entre [] indicamos cuál nodo deseamos y con : nos vamos al siguiente nivel de cada nodo, así si deseamos obtener el valor del valor key, sería Tokens:Key.

Con la opción TokenValidationParameters, indicamos cuales validaciones queremos realizar a nuestros tokens, en este caso validamos que el Issuer y la audiencia sean los valores que escribamos en nuestro archivo appsettings, validamos que la llave de cifrado sea la misma de nuestro archivo appsettings y validamos la fecha de caducidad del token.

startup.cs
public void ConfigureServices(IServiceCollection services)
{
//Codigo
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(cfg =>
{
cfg.Audience = Configuration["Tokens:Issuer"];
cfg.Authority = Configuration["Tokens:Audience"];
cfg.TokenValidationParameters = new
TokenValidationParameters()
{
//Se va a validar el issuer (Quien genera el token)
ValidIssuer = Configuration["Tokens:Issuer"],
ValidateAudience = true,
//Se va a validar la audicencia que puede usar el token
ValidAudience = Configuration["Tokens:Audience"],
//Se valida la llave de cifrado
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(
Configuration["Tokens:Key"]));
//Se validara el tiempo de vida del token
ValidateLifetime = true
});
}

Indicamos a swagger que nuestros servicios requieren token

startup.cs
public void ConfigureServices(IServiceCollection services)
{
//Codigo
services.AddSwaggerGen(c =>
{
//Código de swagger
//Incluimos que vamos a utilizar tokens
c.AddSecurityDefinition("Bearer",
new OpenApiSecurityScheme
{
Description = "JWT Authorization (bearer)",
Type = SecuritySchemeType.Http,
Scheme = "bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme{
Reference = new OpenApiReference{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
}
},new List<string>()
}
});
});

En el servicio de MVC indicaremos que todos nuestros servicios no se van a poder accesar si el usuario no ha iniciado sesión

startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options=>
{
//Agregamos una politica para indicar que todos nuestros servicios
//requieren que los usuarios hayan iniciado sesióm
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));

En el método configure agregamos la autenticación y la autorización

startup.cs
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseAuthorization();
//Codigo
}

Si queremos consultar cualquiera de nuestros servicios recibiremos el estatus 401 Unauthorized