BLOG | NGINX

Autenticación y enrutamiento basado en contenido con JWT y NGINX Plus

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Miniatura de Alan Murphy
Alan Murphy
Publicado el 1 de marzo de 2018

NGINX Plus versión 10 introdujo soporte para descargar la autenticación de servicios web y API con tokens web JSON (JWT, pronunciado “jots”). Desde el lanzamiento de R10, hemos seguido aumentando la funcionalidad en cada nueva versión.

A partir de NGINX Plus R14 , NGINX Plus admite JWT que contienen reclamaciones anidadas y datos de matriz. Cuando se utiliza en un escenario de puerta de enlace de API, NGINX Plus puede usar JWT para autenticar clientes que solicitan conexiones a servicios de backend y destinos de API.

En ocasiones me han pedido que proporcione una configuración básica que use NGINX Plus para autenticar JWT y luego tome decisiones de equilibrio de carga más avanzadas basadas en la información de JWT. La solución más sencilla es simplemente permitir el acceso a un servicio si la autenticación es exitosa y bloquear o redirigir la conexión si no es exitosa.

El tutorial de esta publicación es una prueba de concepto completa para la autenticación JWT y el enrutamiento basado en contenido utilizando NGINX Plus. Para cubrir la gama más amplia de posibilidades y reducir la necesidad de conocimientos previos o experiencia con JWT, he creado un tutorial “JWT 101” que le permite implementar esta solución (con ejemplos y antecedentes) sin ningún conocimiento previo de JWT.

Si ya tiene experiencia con JWT o JWT existentes en su entorno, puede omitir las primeras dos secciones y adaptar los fragmentos de configuración de NGINX Plus proporcionados para que se ajusten a su entorno y comenzar a tomar decisiones avanzadas de equilibrio de carga basadas en sus datos de reclamos de JWT.

Requisitos previos

Este documento asume una instalación nueva de NGINX Plus, con archivos de configuración predeterminados en las siguientes ubicaciones:

  • /etc/nginx/nginx.conf
  • /etc/nginx/conf.d/default.conf

Para obtener más información sobre cómo instalar y comenzar a usar NGINX Plus, consulte la Guía de administración de NGINX Plus .

Todos los comandos CLI asumen privilegios de root , por lo que los usuarios que no sean root deben tener permisos de sudo en su entorno.

Para obtener información adicional y otros casos de uso para JWT con NGINX Plus, consulte los siguientes enlaces:

Creación de un JWT y una clave de firma asociada

Las siguientes instrucciones lo guiarán a través de la creación de un JWT desde cero con datos de carga útil específicos para nuestro ejemplo, como una ilustración de cómo configurar NGINX Plus para el procesamiento básico de reclamos JWT. Si utiliza un JWT existente en lugar del de muestra, debe asegurarse de que su archivo “secretos” contenga la cadena codificada en Base64URL que coincida con la clave de firma que utiliza para crear el JWT. Probablemente también necesites modificar las reclamaciones en la carga útil JWT.

Nota:  Independientemente de cómo genere su JWT, debe utilizar la codificación Base64URL, que maneja correctamente el relleno (realizado con el carácter = ) así como otros caracteres no compatibles con HTTP que normalmente se utilizan en la codificación Base64. Muchas herramientas manejan esto automáticamente, pero los codificadores Base64 manuales basados en CLI y algunas herramientas de creación de JWT no lo hacen. Para obtener más información sobre la codificación Base64URL, consulte la codificación base64URL de Brock Allen y RFC 4648 .

Para este ejemplo, utilizamos la GUI en jwt.io (que realiza correctamente la codificación Base64URL) para crear un JWT HS256 simétrico. La siguiente captura de pantalla muestra cómo se ve la GUI después de ingresar los valores especificados en las instrucciones a continuación y verificar la firma.

Trabajando en la GUI en jwt.io , genere un JWT HS256 verificando o insertando los valores indicados en los campos de la columna Decodificado a la derecha:

  1. Verifique que aparezca el siguiente valor predeterminado en el campo ENCABEZADO , modificando el contenido para que coincida si es necesario:

    { "alg": "HS256", "típico": "JWT"
  2. En el campo VERIFICAR FIRMA , reemplace el valor en el cuadro (por defecto, secret ) con nginx123 . (Realice este cambio antes de ingresar datos en el campo CARGA ÚTIL para evitar un problema que ocurre si invierte los dos pasos).

  3. Reemplace el contenido del campo PAYLOAD con lo siguiente:

    { "exp": 1545091200,
    "nombre": "Crear nuevo usuario",
    "sub": "cuser",
    "gname": "wheel",
    "guid": "10",
    "Nombre completo": "John Doe",
      "uname": "jdoe",
      "uid": "222",
    "sudo": verdadero,
    "dept": "IT",
    "url": "http://secure.example.com"
    }

    Nota:  La afirmación exp establece la fecha y hora de vencimiento del JWT, representándolo como un tiempo de época UNIX (la cantidad de segundos desde la medianoche UTC del 1 de enero de 1970 ). El valor de muestra representa la medianoche UTC del 18 de diciembre de 2018 . Para ajustar la fecha de vencimiento, cambie el tiempo de época.

  4. Verifique que la barra debajo de los campos esté azul y diga Firma verificada .

  5. Copie el valor de la columna Codificado de la izquierda en un archivo o búfer. Es el texto completo del JWT que el usuario jdoe necesita presentar para acceder a http://secure.example.com y lo usaremos en nuestras pruebas a continuación . Aquí mostramos el JWT con saltos de línea para fines de visualización, pero debe presentarse a NGINX Plus como una cadena de una sola línea.

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwOTEyMDAsIm5hbWUiOi
    JDcmVhdGUgTmV3IFVzZXIiLCJzdWIiOiJjdXNlciIsImduYW1lIjoid2hlZWwiLCJndWlkI
    joiMTAiLCJmdWxsTmFtZSI6IkpvaG4gRG9lIiwidW5hbWUiOiJqZG9lIiwidWlkIjoiMjIy
    Iiwic3VkbyI6dHJ1ZSwiZGVwdCI6IklUIiwidXJsIjoiaHR0cDovL3NlY3VyZS5leGFtcGx
    lLmNvbSJ9.YYQCNvzj17F726QvKoIiuRGeUBl_xAKj62Zvc9xkZb4

Trabajando en el host NGINX Plus, siga estos pasos para crear el archivo de clave que NGINX Plus usa para verificar los JWT firmados con nginx123 :

  1. Ejecute este comando para generar la cadena codificada en Base64URL correspondiente a la cadena de firma. (Los comandos tr realizan las sustituciones de caracteres necesarias para la codificación Base64URL).

    # echo -n nginx123 | base64 | tr '+/' '-_' | tr -d '=' bmdpbngxMjM
  2. En el directorio /etc/nginx/ , cree el archivo de clave llamado api_secret.jwk que NGINX Plus utilizará para verificar las firmas JWT. Inserte el siguiente contenido. El valor en el campo k es la forma codificada en Base64URL de nginx123 , que generamos en el paso anterior.

    {"keys": [{
    "k":"bmdpbngxMjM",
    "kty":"oct"
    }]
    }

Configuración de NGINX Plus para gestionar JWT

Las instrucciones de esta sección configuran NGINX Plus para validar el JWT incluido en una solicitud y presentar un recurso protegido si el cliente está autorizado (en lugar de la página predeterminada que ven los clientes no autorizados). También definimos un nuevo formato de registro que captura información relacionada con JWT.

Configuración de la validación JWT y el enrutamiento basado en contenido

En estas instrucciones, seguimos la mejor práctica estándar de cambiar el nombre del archivo de configuración default.conf para que NGINX Plus no lo lea y crear una nueva configuración específicamente para realizar pruebas. Esto le permite restaurar fácilmente la configuración predeterminada cuando haya terminado las pruebas o si hay un problema durante las pruebas.

  1. Cambiar el nombre de default.conf :

    # mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
  2. Cree un nuevo archivo de configuración llamado jwt-test.conf en /etc/nginx/conf.d/ , con el siguiente contenido. Configuran el registro específico de JWT, la validación de JWT y el enrutamiento basado en contenido (a continuación del fragmento se incluye un análisis completo).

    servidor {
    escuchar 80;
    registro de acceso /var/log/nginx/host.access.log jwt;
    
    ubicación / {
    raíz /usr/share/nginx/html;
    índice index.html index.htm;
    
    # Validación de JWT
    auth_jwt "Dominio de prueba JWT" token=$arg_myjwt;
    auth_jwt_key_file /etc/nginx/api_secret.jwk;
    registro de errores /var/log/nginx/host.jwt.error.log debug;
    
    if ( $jwt_claim_uid = 222 ) {
    add_header X-jwt-claim-uid "$jwt_claim_uid" siempre;
    add_header X-jwt-status "Redireccionar a $jwt_claim_url" siempre; return 301 $jwt_claim_url;
    }
    
    if ( $jwt_claim_uid != 222 ) {
    add_header X-jwt-claim-uid "$jwt_claim_uid" siempre;
    add_header X-jwt-status "Usuario no válido, sin redirección" siempre;
    }
    }
    }

Las directivas en el bloque de ubicación le indican a NGINX Plus cómo manejar las solicitudes HTTP que incluyen un JWT. (Para obtener información sobre la configuración de registro definida por la directiva access_log , consulte la siguiente sección ). NGINX Plus realiza estos pasos:

  1. Extrae el JWT del argumento myjwt en la cadena de solicitud (como se especifica en el argumento de token de la directiva auth_jwt ).

  2. Decodifica el JWT utilizando la clave de firma especificada por la directiva auth_jwt_key-file (aquí, api_secret.jwk ). Actúa sobre la carga útil de la siguiente manera (estas acciones son inherentes al procesamiento de JWT y no tienen directivas NGINX Plus correspondientes):

    • Verifica que el JWT no haya expirado; es decir, la fecha de expiración especificada por el reclamo exp en la carga útil no está en el pasado.
    • Crea un par clave-valor para cada reclamo en la carga útil. El nombre de la clave es una variable con el formato $jwt_claim_claim -name (por ejemplo, $jwt_claim_uid para el reclamo uid ).
  3. Registra cualquier error en /var/log/nginx/host.jwt.error.log en el nivel de depuración .

  4. Comprueba si el valor de $jwt_claim_uid es222 (como se especifica en las dos directivas if ) y envía la respuesta adecuada al cliente. Así es como se utiliza la información del JWT para realizar el enrutamiento basado en contenido.

    • Si el valor es222 NGINX Plus envía una respuesta que redirige al cliente (la directiva de retorno ) a la URL especificada en la reclamación de URL de JWt. Para fines de depuración, agrega dos encabezados a la respuesta (las directivas add_header ): el primero captura el valor del reclamo uid y el segundo registra el hecho de que el cliente fue redirigido.
    • Si el valor no es222 NGINX Plus sirve la página de índice predeterminada (tal como se define en las directivas raíz e índice en el mismo bloque de ubicación ). Nuevamente, para fines de depuración, agrega encabezados que capturan el valor del reclamo uid y registran el hecho de que el cliente no obtuvo acceso a la URL especificada en el JWT.

    Nota:  Generalmente, no se considera la mejor práctica utilizar la directiva if para evaluar variables, y generalmente recomendamos utilizar la directiva map en su lugar. Sin embargo, para los fines de este ejemplo simple, la directiva if funciona según lo previsto.

En efecto, la configuración proporciona acceso a recursos protegidos sólo a usuarios autorizados. Es decir, los usuarios con un JWT válido obtienen acceso a la URL especificada en el JWT, mientras que los usuarios sin un JWT válido obtienen acceso a una página predeterminada.

Registro de datos JWT

Completamos la configuración del manejo de JWT para el enrutamiento basado en contenido definiendo un formato de registro llamado jwt , al que se hace referencia en la directiva access_log en jwt-test.conf . Captura datos JWT en el registro de acceso.

  1. Agregue la siguiente directiva log_format a /etc/nginx/nginx.conf :

    formato_de_registro jwt '$dirección_remota - $usuario_remoto [$hora_local] "$solicitud" ' '$estado $bytes_del_cuerpo_enviados "$referencia_http" "$agente_usuario_http" '
    '$algoritmo_de_encabezado_jwt $uid_de_reclamo_jwt $url_de_reclamo_jwt';

    Este formato incluye las dos reclamaciones JWT que se utilizan en este tutorial ( uid y url ), pero puede registrar cualquier dato de reclamación JWT con el nombre de variable correspondiente a la reclamación, en el formato $jwt_claim_claim ‑name .

  2. Guarde nginx.conf y luego ejecute el siguiente comando para probar la configuración completa (incluido el nuevo archivo jwt-test.conf ) para verificar su validez sintáctica. Corrija cualquier error informado.

    # nginx -t
  3. Recargar NGINX Plus.

    # nginx -s recargar
    

Probando la configuración

Usando un navegador o una herramienta CLI como curl , podemos probar que NGINX Plus está validando correctamente el JWT, autenticando al cliente que lo presenta y realizando enrutamiento basado en contenido. (Para probar solo la autenticación y la validación, pero no el enrutamiento basado en contenido, comente los dos bloques if en jwt-test.conf ).

Para ejecutar la prueba, incluimos el argumento myjwt en la URL de la solicitud, proporcionando el texto completo del JWT en el que se encuentra la reclamación de la URL .222 . Nuevamente hemos agregado saltos de línea para fines de visualización.

http://example.com/index.html?myjwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiO
jE1NDUwOTEyMDAsIm5hbWUiOiJDcmVhdGUgTmV3IFVzZXIiLCJzdWIiOiJjdXNlciIsImduYW
1lIjoid2hlZWwiLCJndWlkIjoiMTAiLCJmdWxsTmFtZSI6IkpvaG4gRG9lIiwidW5hbWUiOiJqZG9
lIiwidWlkIjoiMjIyIiwic3VkbyI6dHJ1ZSwiZGVwdCI6IklUIiwidXJsIjoiaHR0cDovL3NlY3VyZS5le
GFtcGxlLmNvbSJ9.YYQCNvzj17F726QvKoIiuRGeUBl_xAKj62Zvc9xkZb4

Aquí está el comando curl correspondiente (sin saltos de línea, por lo que puedes copiarlo y pegarlo si lo deseas):

# curl -v ejemplo.com/index.html?myjwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwOTEyMDAsIm5hbWUiOiJDcmVhdGUgTmV3IFVzZXIiLCJzdWIiOiJjdXNlciIsImduYW1lIjoid2hlZWwiLCJndWlkIjoiMTAiLCJmd WxsTmFtZSI6IkpvaG4gRG9lIiwidW5hbWUiOiJqZG9lIiwidWlkIjoiMjIyIiwic3VkbyI6dHJ1ZSwiZGVwdCI6IklU IiwidXJsIjoiaHR0cDovL3NlY3VyZS5leGFtcGxlLmNvbSJ9.YYQCNvzj17F726QvKoIiuRGeUBl_xAKj62Zvc9xkZb4

Porque el valor de la reclamación uid en el JWT es222 Esperamos que NGINX Plus muestre el contenido de la página restringida, http://secure.example.com .

Ahora probamos para verificar que cuando la reclamación de URL en el JWT no es222 NGINX Plus no muestra el contenido de la página restringida, sino que presenta la página index.html del servidor local, en este caso http://example.com/index.html .

Comenzamos generando otro JWT en jwt.io con una reclamación uid distinta a222 ; a modo de ejemplo, lo hacemos111 . Aquí está la URL de solicitud con ese JWT:

http://example.com/index.html?myjwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiO
jE1NDUwOTEyMDAsIm5hbWUiOiJDcmVhdGUgTmV3IFVzZXIiLCJzdWIiOiJjdXNlciIsImduYW
1lIjoid2hlZWwiLCJndWlkIjoiMTAiLCJmdWxsTmFtZSI6IkpvaG4gRG9lIiwidW5hbWUiOiJqZG9
lIiwidWlkIjoiMTExIiwic3VkbyI6dHJ1ZSwiZGVwdCI6IklUIiwidXJsIjoiaHR0cDovL3NlY3VyZS5l
eGFtcGxlLmNvbSJ9.Ch9xqsGzB8fRVX-3CBuCxP1Ia3oGKB1OnO6qwi_oBgg

El comando curl es:

# curl -v ejemplo.com/index.html?myjwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwOTEyMDAsIm5hbWUiOiJDcmVhdGUgTmV3IFVzZXIiLCJzdWIiOiJjdXNlciIsImduYW1lIjoid2hlZWwiLCJndWlkIjoiMTAiLCJmd WxsTmFtZSI6IkpvaG4gRG9lIiwidW5hbWUiOiJqZG9lIiwidWlkIjoiMTExIiwic3VkbyI6dHJ1ZSwiZGVwdCI6IklUIiwidXJsIjoiaHR0cDovL3NlY3VyZS5leGFtcGxlLmNvbSJ9.Ch9xqsGzB8fRVX-3CBuCxP1Ia3oGKB1OnO6qwi_oBgg

En este caso, esperamos que NGINX Plus sirva http://example.com/index.html .

En ambas condiciones de prueba, puede utilizar una herramienta de inspección de encabezados (como curl o las herramientas para desarrolladores proporcionadas con algunos navegadores) para verificar que los nuevos encabezados, X-jwt-claim-uid y X-jwt-status , se hayan agregado a la respuesta.

Si tiene algún problema durante la prueba, verifique los registros de acceso y errores en /var/log/nginx/host.jwt* . El registro de errores en particular revela problemas con la verificación, el acceso a su archivo de verificación, etc.

Pasando el JWT en una cookie

En nuestro ejemplo básico, NGINX Plus extrae el JWT del argumento myjwt en la URL de solicitud. NGINX Plus también admite pasar el JWT en una cookie (para obtener más detalles, consulte la documentación de referencia de JWT de NGINX ). En jwt-test.conf , cambie la directiva auth_jwt para que el primer elemento en el parámetro token sea $cookie en lugar de $arg :

auth_jwt "Reino de prueba JWT" token=$cookie_myjwt;

Para proporcionar el JWT en una cookie llamada myjwt , el comando curl apropiado es:

# curl -v --cookie myjwt= JWT-text ejemplo.com/index.html

Pruebe usted mismo el enrutamiento basado en contenido con JWT: comience hoy su prueba gratuita de 30 días de NGINX o contáctenos para analizar sus casos de uso .


"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.