El motor de la autenticación de inicio de sesión único es una tecnología llamada Token Web JSON (JWT) que permite que Zendesk confíe en las solicitudes de inicio de sesión que recibe de los sistemas. Si desea ver los detalles, consulte Configuración de inicio de sesión único con JWT (Token Web JSON).
Una solicitud de autenticación de token web JSON tiene este aspecto:
https://joeandco.zendesk.com/access/jwt?jwt=eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpYXQiOjEzNzIxMTMzMDUsImp0aSI6ODg4MzM2MjUzMTE5Ni4zMjYsIm5hbWUiOiJUZXN0IFVzZXIiLCJlbWFpbCI6InR1c2VyQGV4YW1wbGUub3JnIiwiZXh0ZXJuYWxfaWQiOiI1Njc4Iiwib3JnYW5pemF0aW9uIjoiQXBwbGUiLCJ0YWdzIjoidmlwX3VzZXIiLCJyZW1vdGVfcGhvdG9fdXJsIjoiaHR0cDovL21pdC56ZW5mcy5jb20vMjA2LzIwMTEvMDUvQmFybmFieV9NYXR0X2Nyb3BwZWQuanBnIiwibG9jYWxlX2lkIjoiOCJ9.Zv9P7PNIcgHfxZaMwQtMpty3TZnmVHRWcsmAMM-mNHg
Si se pone en la barra del URL de un navegador, se inicia sesión en una instancia de Zendesk.
Es así de fácil. No se necesita nada más. No hay servidores que se contacten el uno con el otro sin que uno los pueda ver. Toda la acción ocurre en el URL.
Un script de autenticación remota simplemente tiene que compilarlo (o algo parecido) para luego llevar ahí al usuario.
Vamos a desglosar el token.
https://joeandco.zendesk.com/access/jwt?jwt=
El primer fragmento es un extremo de URL donde se deben dirigir las solicitudes de autenticación remota. A eso le sigue un signo de interrogación de cierre (?), que indica que se están añadiendo parámetros. Los parámetros pasan cierta información al script en el extremo de destino (https://joeandco.zendesk.com/access/jwt). El script tiene que diseñarse para que pueda admitir estos parámetros, y por esa razón es necesario enviarlo a /access/jwt y no a una simple dirección aleatoria.
Después del signo de interrogación, el nombre del parámetro es “jwt”, y “=” indica que la cadena que sigue es el valor del parámetro.
El resto son datos. Si mira con atención, verá que está dividido en bloques por puntos (puntos finales). Analizaremos los bloques uno por uno.
Bloque 1: encabezado JWT
El primer bloque consiste en el encabezado JWT. Indica que es una solicitud JWT e indica el tipo de algoritmo de hash utilizado. (Más adelante discutiremos este punto.)
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
Lo importante sobre esto (y el resto de los datos) es que está codificado en base64. Esto no es realmente encriptación de modo que se puede descodificar fácilmente con herramientas como estas:
- Herramienta web: http://www.base64decode.org/
- Terminal: http://drewsymo.com/how-to/quick-and-simple-base64-encode-on-mac-osx-terminal/
Así se ve esa cadena descodificada:
{"typ":"JWT",
"alg":"HS256"}
Puede ver que sigue la estructura JSON y tiene dos pares de clave-valor que en efecto quieren decir type: JWT
y Algorithm: HMAC SHA 256
. SHA 256 es un algoritmo de encriptación de 256 bits diseñado por la Agencia de Seguridad Nacional de Estados Unidos . Se usa para generar un tercer bloque, la firma, que vamos a discutir en un momento.
Bloque 2: juego de declaraciones de JWT/Payload
El segundo bloque es bastante más extenso porque contiene el payload. Se conoce como “JWT Claims Set”.
eyJpYXQiOjEzNzIxMTMzMDUsImp0aSI6ODg4MzM2MjUzMTE5Ni4zMjYsIm5hbWUiOiJUZXN0IFVzZXIiLCJlbWFpbCI6InR1c2VyQGV4YW1wbGUub3JnIiwiZXh0ZXJuYWxfaWQiOiI1Njc4Iiwib3JnYW5pemF0aW9uIjoiQXBwbGUiLCJ0YWdzIjoidmlwX3VzZXIiLCJyZW1vdGVfcGhvdG9fdXJsIjoiaHR0cDovL21pdC56ZW5mcy5jb20vMjA2LzIwMTEvMDUvQmFybmFieV9NYXR0X2Nyb3BwZWQuanBnIiwibG9jYWxlX2lkIjoiOCJ9
Contiene una marca de tiempo, un valor aleatorio, un nombre de usuario, una dirección de correo electrónico, una ID externa y algunas etiquetas. Y hay más opciones disponibles. De nuevo, simplemente descodifíquelo con base64 para darle sentido al payload. Voy a separar las líneas para entenderlo mejor.
{
"iat":1372113305,
"jti":8883362531196.326,
"name":"Test User",
"email":"tuser@example.org",
"external_id":"5678",
"organization":"Apple",
"tags":"vip_user",
"remote_photo_url":"http://mit.zenfs.com/206/2011/05/Barnaby_Matt_cropped.jpg",
"locale_id":"8"
}
Requerido
IAT
La primera clave es iat, que quiere decir issued at (emitido al). Es una marca de tiempo en un formato expresado en segundos enteros a partir del 1 de enero de 1970, que es la representación de la hora UNIX. La marca de tiempo debe ser un entero (no decimal) y debe expresarse en UTC. También debe estar dentro de los 3 minutos de la hora actual cuando el servidor de Zendesk la recibe. Esto introduce un mecanismo de autodestrucción en cada solicitud de autenticación remota, que impide que ninguna solicitud se pueda usar más de 3 minutos después de ser generada.
JTI
La segunda clave, jti, significa JSON Token ID o ID de token JSON. No es más que una cadena aleatoria. Tiene que ser lo suficientemente extensa y aleatoria para que las probabilidades de que se vaya a usar de nuevo en esta cuenta sean muy escasas. Si, por accidente o por alguna casualidad, se vuelve a utilizar para otra solicitud de autenticación, la solicitud fallaría. Esto equivale a una clave desechable. Al incluir un valor aleatorio (obligatoriamente) como este, nos aseguramos de que nunca haya dos solicitudes de autenticación iguales. De este modo se evita la reutilización de un URL de solicitud válido. Por ejemplo, imagínese que alguien logró instalar malware en su equipo o su red y ha comenzado a registrar su tráfico. Cada URL al que acceda, será detectado por el intruso. Si este ve y se apropia del URL que fue emitido para usted con el propósito de iniciar sesión en Zendesk, el intruso lo podría utilizar para iniciar sesión haciéndose pasar por usted dentro del plazo de 3 minutos sin esta clave de un solo uso.
Nombre
Lo que sigue es el nombre completo del usuario incluyendo espacios. Lo que Zendesk reciba aquí se establece como el nombre del usuario, aun si antes ya había definido otro nombre.
Correo electrónico
Después viene el correo electrónico del usuario. Esto se usa como el identificador único para un usuario a menos que se reciba una ID externa*. Eso quiere decir que si recibimos un correo electrónico y una ID externa, intentamos buscar el complemento de la ID primero. Si lo encontramos, actualizamos los datos de ese usuario con la dirección de correo electrónico especificada.
*Nota: Si está activada la opción “¿Permitir la actualización de id externas?” en Zendesk, continuaremos usando el correo electrónico para identificar al usuario incluso si se recibe una ID externa. Si el correo electrónico y la ID externa difieren, cambiaremos la ID.
Opcional
ID externa
La ID externa es una ID opcional que se puede usar para identificar a los usuarios en lugar de usar su dirección de correo electrónico (como se señala más arriba).
Organization
También se puede pasar un valor de organización para agregar un usuario a una organización. La organización nombrada debe existir ya, y el nombre debe ser idéntico. De lo contrario, no se realiza ninguna acción.
Etiquetas
La clave etiquetas permite establecer etiquetas para el usuario que está iniciando sesión. La clave reemplaza las etiquetas existentes en el usuario con las etiquetas que se especifiquen, así que se debe proceder con cuidado. Pasar un parámetro de etiquetas en blanco elimina todas las etiquetas de un usuario.
URL de foto remoto
También se puede pasar un valor para remote_photo_url, que acepta un URL público que contiene una foto que se utiliza como la foto de perfil del usuario.
Configuración regional (Idioma)
Se puede pasar un valor para locale_id para establecer o actualizar el idioma del usuario autenticado en Zendesk. El valor debe ser un número que coincida con una configuración regional ya activada en Zendesk. Las configuraciones regionales se pueden ubicar usando el extremo locales.json de nuestra API: http://developer.zendesk.com/documentation/rest_api/locales.html#list-locales
Campos de usuario (no se muestran en el ejemplo)
Este tiene que ser un objeto JSON que incluya pares clave-valor para cada clave de campo y valor. La clave de campo se puede encontrar o definir en la interfaz de Campos de usuario. Observe que solo se pueden pasar campos de usuario personalizados.
Ejemplo:
"user_fields": {"checked": false,"date_joined": "2013-08-14T00:00:00+00:00","region": "EMEA","text_field": null}
Las casillas de verificación utilizan valores booleanos, los códigos de fecha siguen el ejemplo de arriba y los menús desplegables admiten el nombre de la opción. Los campos de texto admiten cadenas.
Número de teléfono (no se muestran en el ejemplo)
Admite una cadena para la identidad del número de teléfono. El número de teléfono se debe especificar usando un formato aceptado. Si desea más información, consulte ¿Cuáles son los formatos de número de teléfono aceptados?.
Bloque 3: firma JWS
El último bloque de la solicitud es la parte encriptada. No hay que preocuparse mucho por esto, pero básicamente toma toda la información anterior (iat, jti, nombre, correo electrónico, etc.) junto con el secreto compartido y la utiliza para generar una cadena encriptada. Luego, conforme a las normas JWT, se toma un bloque de esa cadena encriptada (lo que se conoce como checksum), y eso constituye la firma JWS.
¿Cómo es que es seguro?
Para generar una cadena encriptada válida, hay que conocer el secreto compartido.
La encriptación está diseñada para impedir que se pueda ir a la inversa de la cadena encriptada a los datos y la clave. Aun si tiene el contenido de los datos, es prácticamente imposible deducir la clave.
Pero como usted tiene la clave y nosotros tenemos la clave, y usted nos manda los mismos datos sin encriptar y encriptados, nosotros podemos compilar la firma y verificar que coincida con lo que usted nos envió.
También es una forma de asegurarse de que nadie pueda manipular los datos cuando van en tránsito.
Así es como se compila en seudocódigo:
URLBase64Encode(
HMAC-SHA256(
URLBase64Encode( header_json ).URLBase64Encode( payload_json )
)
)
Al generar el HMAC-SHA256 del encabezado codificado y el payload, se incluye el secreto compartido.
El resultado es este:
Zv9P7PNIcgHfxZaMwQtMpty3TZnmVHRWcsmAMM-mNHg