La .NET CONF 2024 acaba de terminar. Descubre las NOVEDADES de .NET 9 junto a los CAMBIOS que trae C# 13.
Puedes ver el contenido de este vídeo junto con su curso en el modo vídeo (similar a Udemy) si pulsas aquí.

Explicación API Key

En este post vamos a ver cómo podemos incluir seguridad a nuestros servicios que se comunican máquina a máquina, ya que cuando tenemos este escenario no utilizamos JWT u otras formas de autenticación.





1 - Qué es una API Key?

Una API Key es un identificador único que sirve para identificar y autenticar a una aplicación o usuario.

 

Como su nombre indica, esta key se utiliza para permitir el acceso a una API.  y la Api Key se limita a dar acceso a la aplicación o usuario, pero a diferencia de los JWT la API key no expira y utilizamos siempre la misma. Por este motivo, tanto el que realiza la llamada como el que recibe dicha llamada tienen conocimiento de la key en cuestión.

 

A pesar de que he  dicho que la api key puede identificar quién hace la llamada, la realidad es que ese “quién” en verdad es “qué sistema” ya que la api key se utiliza en el 99.9% de casos para hacer llamadas entre sistemas, ya bien sea de una api externa o interna, suelen ser utilizadas cuando la acción sucede de forma automática. 

Además, las keys suelen ser 1 a 1, osea tienes una app, tienes una key y esa key te permite identificarte en la aplicación a la que estás consultando. 

 

Personalmente pienso que la API key no es suficiente para identificar y dar permisos, para mí una API key te debería dar acceso a todo (identificar), y luego limitar el uso pero una api key no te da el mismo control que te da un token a la hora por ejemplo de permitir acceso a X o Y. Obviamente, la aplicación dueña de esa API puede almacenar esa información en una base de datos, pero para hacer eso, utiliza JWT o un API Token.

Por ejemplo la API de youtube sigue este mecanismo, te da una key para tu aplicación en concreto, no tienes un usuario y contraseña como tal. 

 

1.1 - Que pasa con una API key comprometida?

hay que cambiarla, esa api identifica a tu maquina, por lo tanto la máquina a la que realizas las llamadas no va a tener ni idea de si es tu maquina de verdad o de si es un tercero intentando sacar información.

 

Esto sobre todo pasa en apis públicas, que puedes llamar desde cualquier parte, en la empresa privada lo más normal es que tengan limitado el acceso desde cierta IP, por ejemplo empresa A está ubicada en la ip 25 y la empresa B creadora de la API tiene configurado que solo desde la ip25 puede recibir llamadas.

Por norma general, las empresas lo hacen así, obviamente por seguridad, de todas formas, si la key ha sido comprometida, deberías generar una. 

 

 

2 - Cuándo utilizar una API key 

Como he explicado hace un momento se hace para controlar quien y cuanto utilizan la API, para comprobar que nadie hace un uso abusivo de nuestra API ni nadie intenta hacer nada malicioso.

 

Además nos permite bloquear el tráfico anónimo.



3 - Cuando No utilizar una API key 

Debemos evitar su uso para identificar al usuario en cuestión que realiza la llamada, para eso tenemos los JWT mencionados anteriormente.

Además recordamos que la API key es por aplicación no usuario.



4 - Implementación de una API key en .NET

Ahora vamos a ver un ejemplo sencillo de cómo implementar una API Key dentro de un entorno de microservicios con .NET

 

Para este ejemplo, voy a reducir el ejemplo a lo absurdo, un solo cliente con un solo token, por lo que ni lo almacenamos en memoria ni nada, simplemente lo tenemos configurado en nuestro appsettings.json. así simplificamos el asunto. 

Este código está dentro del proyecto de Distribt el cual puedes encontrar en GitHub al cual le vamos a añadir dentro de la arquitectura el uso de API Keys, dentro de nuestra API a la que tiene acceso el cliente final.

 

Aquí podemos ver una imagen de la arquitectura completa del sistema, pero en este post nos vamos a centrar únicamente en el cuadradito verde.

arquitectura sistema distribt

Si no estas familiarizado con los sistemas distribuidos te recomiendo que sigas el siguiente curso:

 

Lo que la API hace es a través de YARP (proxy inverso) enruta la llamada de ese microservicio al interno, de esta forma, el cliente únicamente tiene acceso a dicho microservicio.

 

en nuestro caso vamos a probar con el endpoint de los health checks https://localhost:7022/reports/health 

arquitectura acceso privado

Bueno vamos al lío, lo que tenemos que hacer es en nuestro appsettings crear el valor de la API Key, en un entorno de producción esta API Key la generarías de forma semi-automática para cada cliente, caducando las anteriores, etc.

{
  ...
  "ApiKey": {
    "clientId": "1",
    "value": "b92b0bdf-da95-42a8-a2b1-780ca461aaf3"
  }
}

 

Con esto únicamente tenemos que leer el valor, ya bien sea utilizando options pattern  o directamente de IConfiguration, y compararlo con el que nos llega del usuario.

Para ello cogemos la información:

public class ApiKeyConfiguration
{
    public string? ClientId { get; init; }
    public string? Value { get; init; }
}

// en la clase startup.cs
services.Configure<ApiTokenConfiguration>(configuration.GetSection("ApiKey"));

 

Y el siguiente paso es crear un middleware o un FilterAttribute que compruebe si ese token viene en la request.

En nuestro caso vamos a crear un middleware. Pero la lógica para un filterAttribute es la misma, únicamente que tendrás que habilitarlo donde quieras utilizarlo, mientras que en un middleware irá en todos endpoints por defecto.

 

como nota decir que la API key vendrá como parte de los headers en concreto como parte del HTTP Authorization header (spec), pero opcionalmente puedes ponerlo como parte de la query string, ya que muchos servicios lo hacen así.

public class ApiKeyMiddleware
{
    private readonly RequestDelegate _next;
   

    public ApiKeyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context, IOptions<ApiKeyConfiguration> apiToken)
    {

        if (context.Request.Headers.TryGetValue("apiKey", out StringValues apiKey))
        {
            if (apiKey == apiToken.Value.Value)
                await _next(context);
            else
                ReturnApKeyNotfound(); 
        }
        else
        {
            ReturnApKeyNotfound();
        }

        void ReturnApKeyNotfound()
        {
            throw new UnauthorizedAccessException("The API Key is missing");
        }
    }
}

 

Y ahora solo tenemos que añadir el middleware; una cosa a tener en cuenta es que el middleware no se va a ejecutar cuando llamemos al endpoint health o health-ui del microservicio, pero si lo hará cuando llamemos al del microservicio que hace referencia: 

//Do not act on /health or /health-ui
webApp.UseWhen(context => !context.Request.Path.StartsWithSegments("/health"),
    appBuilder => appBuilder.UseMiddleware<ApiKeyMiddleware>()
);

Y ahora solo nos queda probarlo.

 

Si desde postman hacemos la request con un api key erróneo, o sin api key vemos que nos devuelve un error:

Missing api key response

Pero cuando enviamos el valor correcto, nos muestra el resultado esperado:

successfull call with an api key

 

Conclusión

En este post hemos visto qué es una API key

Cuándo implementar una API Key

 

y cómo implementar una API Key en .net

 


Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café