Header Ads Widget

Ticker

6/recent/ticker-posts

Autenticación como API de hipermedia



La autenticación de usuario, el proceso de responder a la pregunta de quién es alguien, ha evolucionado mucho en los últimos años. Desde los albores de la seguridad informática hasta hace relativamente poco tiempo, la autenticación de usuario se ha representado predominantemente mediante protección por contraseña. Esto implica pedir un nombre de usuario y luego verificar que el usuario detrás de ese nombre conoce la contraseña asociada.

A medida que aumentaba la potencia informática y los ataques se volvían más sofisticados, se hizo evidente que las contraseñas no eran suficientes. La autenticación ahora implica varios métodos combinados en lo que se llama autenticación multifactor. Según la región, la industria y el caso de uso, estos factores tienden a ser diferentes. También confiamos en otras partes para averiguar quién es el usuario; Los inicios de sesión sociales son un buen ejemplo.

Esto significa que lo que solía ser una simple consulta de validación de datos de formulario ahora es un largo viaje de usuario. Puede implicar visitar otros sitios (Facebook o Google), abrir otras aplicaciones (Duo, BankID) y hacer clic en todas las imágenes que muestran semáforos (sin comentarios).

Los servicios de autenticación son sitios web elaborados que guían al usuario a través de todos estos pasos.

En Curity, nos han hecho esta pregunta muchas veces: ¿por qué no podemos obtener una API para autenticar a nuestros usuarios? El razonamiento detrás de esa pregunta es simple: nuestros clientes no quieren enviar a sus usuarios a un sitio web de autenticación desde su aplicación, sino mantenerlos en la aplicación. La respuesta, sin embargo, es menos simple; La autenticación de un usuario da por sentado algunas cosas:

  • El usuario seguirá un recorrido paso a paso predefinido para completar la identificación.
  • El navegador se asegurará de que este sea el caso.
  • Ninguna otra parte puede interceptar los mensajes y hacer uso del resultado final.

Estas expectativas crean un tipo de API bastante diferente. En primer lugar, dado que la autenticación es un viaje, un cliente de API debe adherirse al protocolo cuando se comunica con la API. Debe haber un punto de partida definido y un final definido. Esto contrasta fuertemente con metodologías como GraphQL y niveles más bajos de REST (según lo define el Modelo de Madurez de Richardson ). Ambos están diseñados para permitir que la persona que llama se sumerja en los recursos de la forma en que lo necesita.

Representación hipermedia

Dar un paso atrás y mirarlo desde lejos puede brindar algunas ideas importantes. Este artículo comenzó describiendo cómo se realiza la autenticación en la web, con un sitio web con estado que lleva al usuario a través de los pasos de autenticación. En este contexto, el navegador web es en sí mismo un cliente API, que utiliza REST y HTML para presentar la interfaz de usuario. Esta es una API de Hypermedia, que se ha discutido en las API nórdicas muchas veces antes. (Especialmente interesante es “ Usar hipermedia para diseñar interfaces de usuario basadas en eventos ” basado en la presentación de Asbjørn Ulsberg en la Cumbre de plataformas de API nórdicas). Hypermedia se presta muy bien a un proceso en el que el servidor y el cliente deben caminar en conjunto a través de un flujo. Si reemplazamos HTML con JSON y lo estructuramos de manera más consistente, tenemos una manera perfecta de diseñar una API de autenticación.

Pasos básicos

Veamos un ejemplo de cómo se puede representar una pantalla de contraseña de nombre de usuario simple usando HTML:

<body class="login body-light">
   <main class="container clearfix" role="main">
       <div class="login-well form-light">
           <img class="login-logo" src="https://19yw4b240vb03ws8qm25h366-wpengine.netdna-ssl.com/assets/images/curity-logo.svg" alt="Logo" title="Logo" role="presentation">
           <form method="post" action="/dev/authn/authenticate/htmlSql">
               <div class="form-field">
                   <label for="userName" class="">Username</label>
                   <input type="text" name="userName" class="field-light" autocapitalize="none" autofocus>
               </div>
               <div class="form-field">
                   <label for="password" class="">Password</label>
                   <input type="password" name="password" class="field-light">
               </div>
               <button type="submit" class="button button-fullwidth  mt2">Login</button>
               <div class="login-actions">
                   <a href="/dev/authn/authenticate/htmlSql/forgot-password">Forgot your password?</a>
 
                   <a href="/dev/authn/register/create/htmlSql" class="mt2">
                       <i class="icon ion-android-person-add"></i>
                       Create account </a>
               </div>
           </form>      
       </div>
   </main>
</body>

Ahora, echemos un vistazo a la misma pantalla usando un tipo de medio JSON:

{
"type": "authentication-step", "links": [ { "href": "/dev/authn/authenticate/htmlSql/forgot-password", "rel": "forgot-password", "title": "Forgot your password?" }, { "href": "/dev/authn/register/create/htmlSql", "rel": "register-create", "title": "Create account" } ], "actions": [ { "template": "form", "kind": "login", "title": "Login", "model": { "href": "/dev/authn/authenticate/htmlSql", "method": "POST", "type": "application/x-www-form-urlencoded", "actionTitle": "Login", "fields": [ { "name": "userName", "type": "username", "label": "Username" }, { "name": "password", "type": "password", "label": "Password" } ] } } ] }

Observe cómo están presentes las posibles acciones. Se deben representar y enviar dos campos. Pero también hay enlaces que se pueden representar donde el usuario puede tomar otra ruta a través del flujo de autenticación si es necesario.

Con el enfoque Hypermedia, el servidor puede controlar el flujo, con un solo punto de entrada y salida, pero presentar al usuario opciones a lo largo del flujo.

El servidor guía al cliente con detalles sobre cómo se debe construir cada pantalla, pero solo hay una cierta cantidad de opciones para implementar. A diferencia de HTML, donde el marcado, el estilo y JavaScript forman un marco masivo para implementar, una API de Hypermedia es un DSL pequeño y bien restringido para representar interfaces de usuario.

 

Está bastante claro que la autenticación es una máquina de estado en la que el servidor guía al usuario a través de varios estados para completar el proceso de autenticación. Recomiendo leer Designing a True REST State Machine para obtener una explicación más detallada de por qué Hypermedia se presta tan bien para este propósito.

Pasos automatizados

No todos los pasos del proceso de autenticación requieren la interacción del usuario. Un buen ejemplo es el proceso de votación . El sondeo ocurre cuando estamos esperando que el usuario realice acciones fuera de banda, como cuando un usuario selecciona un enlace de correo electrónico como método de autenticación. El usuario ingresa su dirección de correo electrónico y luego el proceso de inicio de sesión espera a que el usuario haga clic en ese enlace. Cuando el usuario hace clic en el enlace, el estado del servidor se actualiza y la autenticación puede continuar. Durante este tiempo, debemos indicarle al cliente que sondee periódicamente el servidor para ver si el usuario ha hecho clic en el enlace. Al introducir un tipo de representación de "sondeo", el cliente puede analizar el mensaje y saber que hay acciones para usar sin que el usuario interactúe con él.

{
  "type": "polling-step",
  "properties": {
	"recipientOfCommunication": "johnxxxx@xxxxple.com",
	"status": "pending"
  },
  "actions": [
    {
  	"template": "form",
  	"kind": "poll",
  	"model": {
    	  "href": "/authenticate/email1/link-wait",
    	  "method": "GET"
       }
    },
    {
  	"template": "form",
  	"kind": "cancel",
  	"title": "Restart the process",
  	"model": {
    	  "href": "/authenticate/email1",
    	  "method": "GET",
    	  "type": "application/x-www-form-urlencoded",
    	  "actionTitle": "Restart the process"
  	}
     }
  ]
}

El estado pendingindica al cliente que continúe con la operación. Mientras polling-stepse presente, el cliente continuará sondeando.

En una página web normal, este sería un cliente de JavaScript que sondea el servidor esperando una determinada respuesta, pero con Hypermedia, incluso ese caso mejora. El cliente siempre recibe una respuesta bien definida que sigue el mismo esquema, ya sea que el usuario se autentique mediante correo electrónico, SMS o algún otro método.

Esquemas

A diferencia de una aplicación de autenticación basada en web normal, la contraparte de la API de Hypermedia debe ser estrictamente esquemática. El cliente necesita comprender cada representación (respuesta) leyendo su tipo de nivel superior y luego saber qué elementos posibles pueden existir en esa representación. Este no es el caso en una página web normal, ya que el navegador solo está limitado por el esquema HTML, no por el subconjunto necesario para la autenticación. No hace falta decir que sería un requisito irrazonable que las aplicaciones móviles implementaran algo como HTML para poder realizar un flujo de autenticación. En cambio, hacemos que el esquema sea lo más pequeño posible y completamente predecible. Esto no significa que la aplicación sepa lo que viene a continuación, pero sabe qué hacer con su información actual.

Ejemplo:

type: authentication-step
purpose: interactive user step during authentication
possible top-level elements: properties, actions, messages, links

Ejemplo:

type: polling-step
purpose: automatic step possible top-level elements: properties, actions

Esto se puede formalizar utilizando cualquier lenguaje de esquema adecuado. En Curity, hemos definido nuestras definiciones de esquema en JSON Schema.

Negociación de contenido

Al crear una API dinámica, como una API de autenticación de hipermedia, es importante asegurarse de que el cliente pueda controlar lo que admite. HTTP tiene un gran mecanismo para esto llamado negociación de contenido.

La negociación de contenido es cuando el cliente le dice al servidor qué tipo de contenido puede aceptar, y luego el servidor intenta entregar el contenido en el formato apropiado. Por ejemplo, al solicitar una imagen, el navegador puede enviar:

GET  https://example.com/assets/images/foo.jpg
Accept image/webp,*/*

Esto significa que prefiere una imagen en formato webp, pero si no existe, acepta cualquier cosa ( */*). Esta lista puede ser larga y describe todos los formatos específicos admitidos. Curiosamente, la extensión de archivo (.jpg) realmente no se aplica aquí; es redundante, y hay una excelente presentación de Erik Michaels-Ober: Negociación de contenido para API REST, donde explica esto con más detalle. También recomiendo leer la introducción de Bill Doerrfeld a la negociación de contenido aquí en las API nórdicas.

Cuando se trata de una API de Hypermedia, o cualquier API REST para el caso, el punto de la negociación de contenido es que el cliente pueda determinar si es compatible con la API o no.

Cuando hablamos de autenticación, hay muchas formas en que un usuario puede autenticarse; algunos son mecanismos de autenticación puramente basados ​​en formularios en los que el usuario ingresa alguna credencial o identificador y el servidor lo valida. Pero también hay métodos más complicados, que pueden requerir que el cliente realice pasos adicionales, como comunicarse con el sistema operativo o el navegador para realizar la autenticación biométrica . Esto puede estar más allá de lo que ciertos clientes son capaces de hacer.

Entonces, al usar la negociación de contenido, podemos formar un contrato entre el cliente y el servidor.

GET  https://idp.example.com/api/authenticate
Accept application/vnd.auth+json

Esto le dice al servidor que el cliente desea iniciar un flujo de autenticación utilizando la API de Hypermedia definida por el application/vnd.auth+jsontipo de medio. También le dice al servidor que el cliente es capaz de manejar el contenido que recibe.

Localización

Normalmente, el servidor web es responsable de localizar el contenido servido en el navegador. Esto también se hace mediante una forma de negociación de contenido. El navegador envía el Accept-Languageencabezado donde indica los idiomas y las configuraciones regionales que admite en una lista ponderada, y el servidor hace todo lo posible para cumplir con esto.

Accept-Language en-US,en;q=0.5

Al crear una API de Hypermedia, no hay razón para utilizar un mecanismo diferente. El cliente puede decirle al servidor cómo se deben localizar los mensajes del contenido. Sin embargo, se puede dar más libertad respondiendo también con claves de mensaje para que el cliente pueda localizar los mensajes por sí mismo si así lo desea.

Ejemplo cuando Accept-Language en-US;en;q=05.:

{
  "type": "authentication-step",
  "actions": [
	{
  	"template": "selector",
  	"kind": "authenticator-selector",
  	"title": "Select Authentication Method",


Example when Accept-Language sv-SE;sv;q=05.
{
  "type": "authentication-step",
  "actions": [
	{
  	"template": "selector",
  	"kind": "authenticator-selector",
  	"title": "Välj inloggningsmetod",

Seguridad

Una parte importante de la creación de una API de autenticación es la seguridad. Es crucial no permitir que aplicaciones arbitrarias en Internet accedan a su API, ya que el potencial de uso indebido es enorme. No desea que los atacantes recopilen credenciales de un sitio creando un sitio de suplantación de identidad y probando directamente contra su API para acceder a su API.

Cuando se utiliza un inicio de sesión normal basado en navegador (sin API), es estándar bloquear el encuadre del flujo de autenticación de cualquier persona que no sea de los sitios incluidos en la lista blanca que utilizan políticas de seguridad de contenido (CSP). (Por supuesto, CSP no previene el phishing pero previene XSS). Pero cuando se entrega una API, estos mecanismos de navegador son menos útiles.

Por supuesto, OAuth debería utilizarse para proteger esta API. Sin embargo, podría decirse que OAuth simple y simple no es suficiente en este escenario. Los flujos de interacción del usuario en OAuth están diseñados teniendo en cuenta el navegador. Existe la suposición subyacente de que cosas como CORS son aplicadas correctamente por el navegador y que el navegador puede probar que el sitio se está ejecutando en el dominio que dice. Estas suposiciones se rompen cuando se utiliza un enfoque basado exclusivamente en API.

Recomiendo leer nuestro documento técnico sobre el modelo de seguridad de la API de autenticación de hipermedia que creamos en Curty. Te lleva a través del tema en profundidad.

API de autenticación de hipermedia: el futuro de la autenticación

La autenticación con una API ha sido durante mucho tiempo el santo grial para los desarrolladores de dispositivos móviles y, recientemente, también para los desarrolladores web. Necesitamos escuchar y proporcionar un protocolo seguro para estos casos de uso para evitar que surjan soluciones inseguras de cosecha propia. En Curity, trabajamos con estándares como OAuth y OpenID Connect, y cuando se quedan cortos, trabajamos con las organizaciones estándar para desarrollar nuevas soluciones. Creemos que una API de autenticación hipermedia estándar es el futuro de la autenticación web y móvil.

Publicar un comentario

0 Comentarios