============= Autenticación ============= El método de autenticación empleado en el sistema Arena, ya sea para la comunicación entre microservicios o bien entre dispositivos y microservicios, es el envío de JSON Web Tokens. Mediante el uso de JWT es posible firmar un JSON codificado que contiene los datos necesarios para la identificación hacia una entidad externa. La información enviada en un JWT empleado en el sistema Arena se describe en el último apartado de esta sección. La especificación de un JWT puede consultarse en el `RFC 7519 `_, y un editor en línea puede utilizarse en `jwt.io `_. Calendarizador ============== Descripción general ------------------- Como parte de la inicialización del servidor Onsite, deben crearse credenciales para el servicio de calendarización de señal de estaciones. Se creará en la ruta ``/config/schedulerCredentials`` un archivo de credenciales como sigue: .. code-block:: javascript { "subject" : "GHJ56FG", "secret": "AKG3kjhf936AsDJsis78" } Siguiendo el proceso de instalación, debe copiarse el archivo en la ruta ``/config/schedulerCredentials`` del calendarizador con el objetivo de que este conozca sus credenciales ante Onsite. Adicional a la creación de este archivo de credenciales, Onsite almacenará en su base de datos la información del calendarizador. Es importante considerar que un prerrequisito para el funcionamiento del local es poder asegurar la conexión entre el servidor principal y el calendarizador. Las peticiones que el servidor envíe al calendarizador irán firmadas con el secreto del segundo. .. _dar-de-alta-local: Dar de alta un local ==================== Un súper admin tiene la facultad de crear sucursales Onsite para que posteriormente estas se identifiquen ante Offsite durante su respectivo proceso de inicialización. A continuación se describe dicho comportamiento. Descripción general ------------------- .. image:: /images/user/location_creation_overview.svg :align: center 1. Un súper usuario solicita la creación de una sucursal en el servidor Offsite. 2. Offsite efectúa validaciones sobre la creación de sucursal y confirma la creación exitosa al usuario. 3. Como parte del proceso de inicialización, un servidor Onsite solicita darse de alta ante Offsite haciendo uso de un código de registro proporcionado por el súper usuario. 4. Offsite asocia la sucursal física con la virtual creada en el punto 2 y confirma al local. Flujo ----- .. image:: /images/user/location_creation_sequence.svg :align: center Se hace uso de las siguientes rutas para el registro de sucursales Offsite: ``POST /locations`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Autorización:** User (*super*) Mediante esta ruta se solicita la creación de una sucursal por un usuario. El cuerpo de la petición es el siguiente .. code-block:: yaml name: Antara prefix: AN domain: antara.onsite.arena.mx address: Lomas Altas 23 city: Ciudad de México state: Distrito Federal timezone: America/Mexico_City countryId: 3 phone1: 52436788 phone2: 55362820 phone3: 92838273 email: antara@domain.com Al recibir esta petición, Offsite confirma que no se tenga registro de una sucursal con el mismo nombre o prefijo. Posteriormente, crea una sucursal y genera una clave única con formato ``PPXXXXXX``, donde ``PP`` corresponde al prefijo de la sucursal y ``XXXXXX`` es una cadena alfanumérica aleatoria de 6 dígitos. La clave única debe ser devuelta como parte de la respuesta. El propósito de esta clave es ser usada por el servidor Onsite durante su proceso de inicialización. Durante este momento se crea el nombre del bucket del local siguiendo la convención ``arena_onsite_PPXXXXX``, donde PPXXXXX corresponde al *subject* que le otorga Offsite a Onsite al momento en que el segundo se da de alta. Adicionalmente, se crea un Access Key para la sucursal con el campo ``accepted_at`` siendo nulo, indicando así que la sucursal no ha sido ligada a ningún servidor físico. Esta ruta responde con el estado ``201 Created`` acompañado de la sucursal recién creada. Si el nombre, el prefijo o el dominio de la sucursal no son únicos, se responde con el estado ``409 Conflict``. Si el país indicado no se encuentra, se responde con el estado ``404 Not Found``. Adicional a validaciones de sintaxis de la petición, se responde con el estado ``422 Unprocessable Entity`` bajo cualquiera de los siguientes casos: - El nombre de la sucursal contiene algún carácter no permitido. Los caracteres válidos son [a-zA-Z0-9] y el símbolo de espacio. - Los campos de nombre, dirección, país o ciudad exceden los 100 caracteres de longitud. - El teléfono presenta algún caracter no numérico, o la longitud es mayor a 13 dígitos. - La longitud del prefijo es distinta a dos caracteres o presenta algún caracter no alfanumérico. Es responsabilidad del súper usuario notificar al administrador de la sucursal sobre el código de verificación obtenido como respuesta en esta petición. Dicho código será usado para completar la creación de una sucursal. Offsite: ``GET /locations/access_keys/{code}`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Mediante esta ruta una sucursal solicita su reconocimiento y asociación a un registro *Location* en Offsite, referenciado por el valor ``code``. Al recibir esta petición, se liga el local que hace la petición con el objeto *Location* cuyo código de verificación coincide con ``code``. Adicionalmente, se actualiza en el Access Key de la sucursal el campo ``accepted_at``, siendo este igual a la fecha Unix del momento de recepción de la petición. El servidor Offsite responde con el estado ``200 OK`` acompañado de la información del local. Si no se encuentra el código de verificación, se responde con el estado ``404 Not Found``. Si el código ya se encuentra en uso para otro local, se responde con el estado ``409 Conflict``. Al momento de recibir respuesta de la petición, Onsite crea el bucket de imágenes con el nombre proporcionado por Offsite. Observaciones ------------- - La cadena ``subject`` es de longitud 7 y única. - La cadena ``secret`` debe ser aleatoria, de 20 caracteres y puede contener mayúsculas, minúsculas y números. No hay restricción de unicidad sobre la cadena. - El valor ``prefix`` debe ser único por cada local. - El dominio de un servidor Onsite debe ser único. - Mientras las credenciales de un servidor Onsite se encuentren pendientes de aprobación, este no debe permitir solicitudes de registro provenientes de dispositivos como Kiosk o Timer. - El Access Key del modelo Location tiene como nulo el campo ``expires_at``, indicando que las credenciales de un servidor Onsite no expiran. .. _alta-dispositivo: Dar de alta un dispositivo ========================== Al momento de dar de alta un nuevo dispositivo capaz de efectuar peticiones al servidor Offsite, es necesario que se autentique previamente con Onsite para que dicho local almacene las credenciales del dispositivo y las comunique a Offsite. A continuación se describe dicho proceso. Descripción general ------------------- .. image:: /images/authentication/device_authentication_overview.svg :align: center 1. El dispositivo solicita darse de alta ante Onsite. 2. Onsite calcula un ``subject`` y un ``secret`` y los devuelve al dispositivo. Estos valores no se encuentran validados todavía. El dispositivo almacena las credenciales obtenidas, mismas que usará en todas las peticiones efectuadas a Offsite. 3. Mediante acción de administrador, Onsite solicita a Offsite que acepte al dispositivo cuya información le envía. 4. Offsite notifica a Onsite del estado de la validación. Flujo ----- Kiosk ^^^^^ .. image:: /images/authentication/kiosk_authentication_sequence.svg :align: center Se requieren las siguientes rutas: Onsite ``POST /kiosks`` *********************** Mediante esta ruta un cliente solicitará ser reconocido como Kiosk con los siguientes parámetros: .. code-block:: yaml kiosk: name: CUKiosk04 donde ``name`` corresponde al nombre mediante el cual se identificará al Kiosk. La ruta responderá con el estado ``201 Created`` acompañado del Kiosk recién creado, con sus nuevos valores de autenticación. Si el nombre del Kiosk es inválido, se devolverá el estado ``409 Conflict``. En caso de que el Kiosk sea creado exitosamente, se calcula en Onsite un ``Access Key`` cuyo ``subject`` será una cadena única *PPXXXXX*, donde *PP* corresponde al prefijo del local y *XXXXX* es una cadena alfanumérica creada aleatoriamente. El ``level`` de la llave de acceso creada corresponderá a aquel otorgado a un Kiosk. .. _ver-quioscos: Onsite: ``GET /kiosks`` *********************** **Autorización:** User Mediante esta ruta se solicitará a Onsite la lista de los Kiosks existentes. Esta ruta puede buscar por los campos ``name``, ``subject``, o ``acceptance_pending``; siendo este último criterio el empleado para saber si un Kiosk está pendiente de aceptación. Onsite: ``PUT /kiosks/{subject}`` ********************************* **Autorización:** User (*onsite*, *super*) A través de la cual se solicita a Onsite que registre en Offsite las credenciales del Kiosk con el ``subject`` al que se hace referencia en la ruta. Como consecuencia, debe establecerse el campo ``accepted_at`` correspondiente al Kiosk como la fecha Unix en que es aceptado. La ruta responderá con el estado ``200 Ok`` acompañado del Kiosk validado. Esta ruta devuelve un estado ``500 Server error`` si el Kiosk no pudo ser dado de alta en Offsite. Offsite ``POST /kiosks`` ************************ **Autorización:** Location A través de la cual Onsite solicita la creación en Offsite de un nuevo Kiosk con los siguientes parámetros: .. code-block:: yaml kiosk: name: CUKiosk04 subject: CUY7sR3 secret: 494414ded24da13c451b La ruta responderá con el estado ``201 Created`` acompañado del Kiosk recién creado. Si el nombre del Kiosk es inválido, se devolverá el estado ``409 Conflict``. En este caso, debe iniciarse de nuevo el proceso de autenticación desde el Kiosk. Observaciones ************* - La cadena ``subject`` es de longitud 7 y debe ser única. - La cadena ``secret`` debe ser aleatoria, de 20 caracteres y puede contener mayúsculas, minúsculas y números. No existe restricción de unicidad sobre la cadena. - Las credenciales devueltas a un Kiosk carecen de validez mientras este no haya sido aprobado. Cualquier petición que un Kiosk realice a Onsite u Offsite previa a la autorización no debe ser permitida. - El Access Key del modelo Kiosk tiene como nulo el campo ``expires_at``, indicando que las credenciales no expiran. Timer ^^^^^ .. image:: /images/authentication/timer_authentication_sequence.svg :align: center Se requieren las siguientes rutas Onsite: ``POST /timers`` ************************ Mediante la cual un cliente solicitará ser reconocido como Timer con los siguientes parámetros: .. code-block:: yaml stationName: TV023 name: CUTi912 donde ``stationName`` corresponde al nombre de la estación a la cual se quiere enlazar el Timer, y ``name`` corresponde al nombre mediante el cual se identificará al Timer. Al recibir la petición, se crea un Timer con los valores proporcionados y con nuevas credenciales de autenticación. Posteriormente, el Timer es vinculado con la estación indicada. La ruta responderá con el estado ``201 Created`` acompañado del Timer recién creado, con sus nuevos valores de autenticación. Si el nombre del Timer es inválido, o si la estación ya cuenta con un Timer asociado, se devolverá el estado ``409 Conflict``. Si la estación indicada no existe, se responde con el estado ``404 Not Found``. En caso de que el Timer sea creado exitosamente, se calcula en Onsite un ``Access Key`` cuyo ``subject`` será una cadena única *PPXXXXX*, donde *PP* corresponde al prefijo del local y *XXXXX* es una cadena alfanumérica creada aleatoriamente. .. _ver-timers: Onsite: ``GET /timers`` *********************** **Autorización:** User (*super*, *onsite*) Donde se solicitará a Onsite la lista de los Timers existentes. Esta ruta puede buscar por los campos ``name``, ``subject``, ``is_pc``, ``acceptance_pending``; siendo este último criterio el empleado para saber si un Timer está pendiente de aceptación. .. _autorizar-timer: Onsite: ``PUT /timers/{subject}`` ********************************* **Autorización:** User (*super*, *onsite*) Mediante la cual se solicita a Onsite que registre en Offsite las credenciales del Timer con el ``subject`` al que se hace referencia en la ruta. Como consecuencia, debe establecerse el campo ``accepted_at`` correspondiente al Timer como la fecha Unix en que es aceptado. La ruta responderá con el estado ``200 Ok`` acompañado del Timer validado. Esta ruta devuelve un estado ``500 Server error`` si el Timer no pudo ser dado de alta en Offsite. Offsite: ``POST /timers`` ************************* **Autorización:** Location A través de la cual Onsite solicita la creación en Offsite de un nuevo Timer. .. code-block:: yaml name: CUTimer27 subject: CUY7sR3 secret: 494414ded24da13c451b La ruta responderá con el estado ``201 Created`` acompañado del Timer recién creado. Si los datos de creación del Timer son inválidos se devolverá el estado ``409 Conflict``. Onsite: ``GET /timers/token_status`` ************************************ **Autorización:** Timer A través de esta ruta se consulta la validez del JWT del cliente Timer que solicita la petición. Para un Timer autenticado se responde con el estado ``200 OK`` acompañado de la siguiente información: .. code-block:: yaml name: CUTimer27 subject: CUY7sR3 accepted_at: 1479862013 Donde el campo ``name`` corresponde al nombre registrado del Timer, y los valores restantes pertenecen al Access Key asociado. En caso de proporcionar autorización inválida, se responde con el estado ``401 Unauthorized``. Observaciones ************* - La cadena ``subject`` es de longitud 7 y debe ser única. - La cadena ``secret`` debe ser aleatoria, de 20 caracteres y puede contener mayúsculas, minúsculas y números. No existe restricción de unicidad sobre la cadena. - Las credenciales devueltas a un Timer carecen de validez mientras este no haya sido aprobado. Cualquier petición que un Timer realice a Onsite u Offsite previa a la autorización no debe ser permitida. - El Access Key del modelo Timer tiene como nulo el campo ``expires_at``, indicando que las credenciales no expiran. .. _baja-dispositivo: Dar de baja un dispositivo ========================== Al momento de dar de baja un dispositivo, deben borrarse sus credenciales tanto del local al que pertenece, como del servidor Offsite. Las rutas empleadas en el proceso se describen a continuación. Flujo ----- Timer ^^^^^ .. _borrar-timer: Onsite: ``DELETE /timers/{subject}`` ************************************ **Autorización:** User (*super*, *onsite*) A través de esta ruta, un usuario solicita el borrado de un Timer de una sucursal, el cual no debe estar aceptado para ninguna estación. De esta manera, se niega la vinculación de un Timer con una estación. Como consecuencia de la recepción de la petición, se elimina el Timer en el servidor Onsite. Como en este punto no existe registro del Timer en Offsite, no es necesario reportar a este la eliminación del dispositivo. La ruta responde con el estado ``200 OK`` acompañado del Timer recién eliminado. Si el Timer ya fue aceptado y vinculado a una estación, se responde con el estado ``403 Forbidden``. Si el dispositivo no se encuentra, se responde con el estado ``404 Not Found``. El tipo de borrado de la entidad es *hard delete*. .. _eliminar-timer-offsite: Offsite: ``DELETE /timers/{subject}`` ************************************* **Autorización:** Location Mediante esta ruta se solicita la remoción de un Timer de la lista de entidades autenticadas, indicando para el borrado el ``subject`` del Access Key del Timer. Como consecuencia, serán eliminados del sistema tanto el Timer como su Access Key relacionado. La ruta responde con el estado ``200 OK`` acompañado del Timer recién eliminado. Si el Timer a eliminar no existe, se responde con el estado ``404 Not Found``. El tipo de borrado de la entidad es *hard delete*. .. _eliminar-kiosk: Kiosk ^^^^^ Onsite: ``DELETE /kiosks/{subject}`` ************************************ **Autorización:** User (*super*, *onsite*) A través de esta ruta, un usuario solicita el borrado de un quiosco de una sucursal. De invocarse sobre una entidad Kiosk no validada, esta es eliminada del listado de autorizaciones pendientes por otorgar. Como consecuencia de la recepción de la petición, se solicita a Offsite la remoción del Kiosk de la lista de entidades autenticadas como se indica en :ref:`eliminar-kiosk-offsite`, esto en caso de que el Kiosk haya sido verificado como entidad autenticada. Posterior al borrado en Offsite, se procede a eliminar el quiosco localmente. La ruta responde con el estado ``200 OK`` acompañado del Kiosk recién eliminado. Si el dispositivo no se encuentra, se responde con el estado ``404 Not Found``. Si el Kiosk no pudo ser eliminado en Offsite, se cancela el borrado y se responde con el estado ``503 Service Unavailable``. El tipo de borrado de la entidad es *hard delete*. .. _eliminar-kiosk-offsite: Offsite: ``DELETE /kiosks/{subject}`` ************************************* **Autorización:** Location Mediante esta ruta se solicita la remoción de un Kiosk de la lista de entidades autenticadas, indicando para el borrado el ``subject`` del Access Key del Kiosk. Como consecuencia, serán eliminados del sistema tanto el Kiosk como su Access Key relacionado. La ruta responde con el estado ``200 OK`` acompañado del Kiosk recién eliminado. Si el Kiosk a eliminar no existe, se responde con el estado ``404 Not Found``. El tipo de borrado de la entidad es *hard delete*. .. _autenticacion-usuarios: Portal de administración ======================== El portal de administración permite a usuarios autenticados efectuar operaciones sobre el sistema. Un usuario inicia sesión ante Offsite y se le responde con un ``secret`` que usará para firmar los JWT que envíe con sus peticiones. Descripción general ------------------- Los usuarios inician con su dirección de correo electrónico y contraseña ante Offsite para obtener un ``secret``. La invocación a cualquier otra ruta distinta al inicio de sesión requerirá incluir un JWT firmado con el ``secret`` proporcionado por Offsite en este paso. .. image:: /images/authentication/user_login_overview.svg :align: center En caso de que el usuario realice peticiones a Onsite, estas deberán incluir también un JWT firmado con el ``secret`` que le fue proporcionado por Offsite, por lo que Onsite deberá consultar la validez del JWT recibido en la petición. .. image:: /images/authentication/user_authentication_overview.svg :align: center Flujo ----- Se requieren las siguientes rutas para el manejo de la sesión del usuario: Offsite ``POST /users/login`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Donde un usuario ingresa con su dirección de correo electrónico y una contraseña. A continuación, debe crearse en el servidor un ``secret`` que será devuelto al usuario para que firme las peticiones subsecuentes, mismo que debe expirar 7 días después de la fecha de creación, o de actualización en caso de que el campo ``accepted_at`` sea no nulo. Para verificar la fecha de expiración se consulta el atributo ``expires_at`` del Access Key, el cual corresponde a una fecha UNIX en segundos. La petición de inicio de sesión lleva por cuerpo .. code-block:: javascript { "email": "admin@admin.com", "password": password } Si el usuario con el correo electrónico especificado existe y la contraseña es correcta, se sobreescribe el Access Key asociado al usuario que ingresa al sistema; esto es con el fin de limitar la creación de Access Keys a uno por entidad autenticada. En caso de sobreescritura, los valores reeemplazados son ``secret``, ``expires_at``, ``accepted_at`` y ``requested_password_recovery_at``, donde este último es establecido como nulo. La fecha de expiración se actualiza a 7 días después de la fecha actual. Si el correo electrónico y la contraseña corresponden a un usuario existente, se devuelve el estado ``200 OK`` acompañado del secreto correspondiente, así como el perfil del usuario. Si las credenciales proporcionadas son inválidas, es decir, la combinación *(email, password)* no existe, se devuelve el estado ``401 Unauthorized``. Para peticiones subsecuentes, el usuario se autenticará con un JWT firmado con el secret recibido en el inicio de sesión, y el cual llevará por payload el siguiente JSON codificado .. code-block:: javascript { "sub": "admin@admin.com", "iat": 1469491719 } Al recibir un JWT, el servidor debe verificar que el valor ``iat`` contenido en el payload no difiera en más de dos minutos de la fecha actual del servidor; esto con el fin de evitar ataques de replay. Esto no implica que se requiera un nuevo inicio de sesión, sino el reenvío de la petición. Offsite: ``POST /users/logout`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Autorización:** User Donde se solicita el cierre de sesión de un usuario, ocasionado que se establezca como nulo el valor ``accepted_at`` del Access Key correspondiente. Si el cierre de sesión es exitoso, se devuelve un estado ``200 OK``. De ocurrir un error en el servidor, el estado a devolver es ``500 Internal Server Error``. Observaciones ------------- - El campo ``expires_at`` en un Acces Key se calcula sumando 7 días al campo ``created_at`` en Offsite en caso de ser creado, o al campo ``accepted_at`` en caso de ser actualizado. En Onsite, se suman 15 minutos siguiendo los mismos criterios. - Los inicios de sesión no requieren de autenticación de terceros, por lo que el campo ``accepted_at`` es igual a la fecha de creación. - Al efectuar un cierre de sesión, el campo ``accepted_at`` del Access Key correspondiente en Offsite debe cambiarse a nulo, con el fin de marcar que las credenciales son ahora inválidas. Asistente ========= La creación de una cuenta de asistente puede ser efectuada únicamente por un perfil *User*. Posterior a esto, un asistente tendrá permisos para iniciar sesión ante Offsite y efectuar peticiones, dado que la autenticación es un requisito para el perfil *Assistant*. .. _crear-asistente: Creación de asistente --------------------- Flujo ^^^^^ Offsite: ``POST /assistants`` ***************************** **Autorización:** User (*super*, *onsite*) Mediante la cual un usuario solicita la creación de un asistente con los siguientes parámetros .. code-block:: yaml name: Juan lastName: Pérez Pérez phone: 5514326754 position: Asistente username: Juan01 email: juan@arena.com.mx donde ``username`` corresponde al nombre de usuario del asistente. Esta ruta responde con el estado ``201 Created`` acompañada del asistente recién creado si la acción fue exitosa. La ruta responde con el estado ``409 Conflict`` si el nombre de usuario del asistente o el correo electrónico ya están en uso. Se responde con el estado ``422 Unprocessable Entity`` bajo cualquiera de los siguientes casos: - Los campos de nombre o apellido exceden los 100 caracteres de longitud. - El nombre de usuario tiene longitud mayor a 25 caracteres, o menor a 4. - El nombre de usuario presenta símbolos distintos a ``[AB...Zab...z01...9]``. - El teléfono presenta algún caracter no numérico, o la longitud es mayor a 13 dígitos. El establecimiento de contraseña se lleva a cabo mediante la siguiente ruta: .. _restablecer-pass-asistente: Offsite: ``POST /assistants/password`` ************************************** **Autorización:** Assistant Mediante esta ruta, se solicita el establecimiento de contraseña del asistente que lleva a cabo la petición. El cuerpo de la petición contiene únicamente el campo de contraseña a establecer. Al recibir esta petición, se marca como expirado el Access Key del asistente cuyo secret se recibe en la petición. Esto con el objetivo de que el Key generado para el restablecimiento de contraseña sea de un único uso. Adicionalmente, se elimina el valor en el campo `requestPasswordRecoveryAt`. La ruta responde con el estado ``200 OK`` como resultado de la modificación de la contraseña. Si el asistente no solicitó restablecimiento de contraseña, se responde con el estado ``403 Forbidden``. Manejo de sesión ---------------- Descripción general ^^^^^^^^^^^^^^^^^^^ .. image:: /images/authentication/assistant_login_overview.svg :align: center Flujo ^^^^^ Onsite: ``POST /assistants/login`` ********************************** Donde un asistente ingresa con su nombre de usuario y contraseña. A continuación, debe redirigirse la petición al servidor Offsite para obtener un ``secret`` que será devuelto al asistente para que firme las peticiones subsecuentes. Al recibir un Access Key para el asistente, éste sobreescribe los valores en el registro de Onsite. La petición de inicio de sesión lleva por cuerpo .. code-block:: javascript { "email": "juanperez@domain.com", "password": password } Si el correo electrónico y la contraseña corresponden a un asistente existente, se devuelve el estado ``200 OK`` acompañado del secreto correspondiente. Si las credenciales proporcionadas son inválidas, es decir, la combinación *(username, password)* no existe, se devuelve el estado ``401 Unauthorized``. Si se recibe de Offsite un registro de asistente distinto al cual se tiene registro, este debe ser actualizado. Por el contrario, si el recurso no existe, el servidor local debe eliminar también registro del asistente. Para peticiones subsecuentes, el asistente se autenticará con un JWT firmado con el secret recibido en el inicio de sesión, y el cual llevará por payload el siguiente JSON codificado .. code-block:: javascript { "sub": "juanPerez", "iat": 1469491719 } Al recibir un JWT, el servidor debe verificar que el valor ``iat`` contenido en el payload no difiera en más de dos minutos de la fecha actual del servidor; esto con el fin de evitar ataques de replay. Esto no implica que se requiera un nuevo inicio de sesión, sino el reenvío de la petición. Offsite: ``POST /assistants/login`` *********************************** **Autorización:** Location Donde una sucursal solicita el inicio de sesión de un asistente. A continuación, debe crearse en el servidor un ``secret`` que será devuelto para que el asistente para que firme las peticiones subsecuentes, mismo que debe expirar al final del día de la fecha de creación, o de actualización en caso de que el campo ``accepted_at`` sea no nulo. Para verificar la fecha de expiración se consulta el atributo ``expires_at`` del Access Key, el cual corresponde a una fecha UNIX en segundos. La petición de inicio de sesión lleva por cuerpo .. code-block:: javascript { "email": "juanperez@domain.com", "password": password } Si el asistente con el correo electrónico especificado existe y la contraseña es correcta, se sobreescribe el Access Key asociado al asistente que ingresa al sistema; esto es con el fin de limitar la creación de Access Keys a uno por entidad autenticada. En caso de sobreescritura, los valores reeemplazados son ``secret``, ``expires_at`` y ``accepted_at`` y ``requested_password_recovery_at``, donde este último es establecido como nulo. La fecha de expiración se actualiza a 24 horas después de la fecha actual. Si el correo electrónico y la contraseña corresponden a un asistente existente, se devuelve el estado ``200 OK`` acompañado del secreto correspondiente. Si las credenciales proporcionadas son inválidas, es decir, la combinación *(username, password)* no existe, se devuelve el estado ``401 Unauthorized``. Si el asistente fue eliminado, se responde con el estado ``404 Not Found``. En consecuencia a este error, el servidor Onsite elimina registro del asistente. Onsite: ``POST /assistants/logout`` *********************************** **Autorización:** Location Donde se solicita el cierre de sesión de un asistente, solicitando el cierre de sesión ante Offsite y ocasionado que se establezca como nulo el valor ``accepted_at`` del Access Key correspondiente. Si el cierre de sesión es exitoso, se devuelve un estado ``200 OK``. De ocurrir un error en el servidor, el estado a devolver es ``500 Internal Server Error``. Offsite: ``POST /assistants/{id}/logout`` ***************************************** **Autorización:** Location Donde se solicita el cierre de sesión de un asistente, ocasionado que se establezca como nulo el valor ``accepted_at`` del Access Key correspondiente. Si el cierre de sesión es exitoso, se devuelve un estado ``200 OK``. De ocurrir un error en el servidor, el estado a devolver es ``500 Internal Server Error``. Onsite: ``GET /assistants/access_keys`` *************************************** **Autorización:** Tournament Handler Donde el manejador de torneos solicita a Onsite la información de los asistentes con el objetivo de almacenar una copia local. La ruta responde con el estado ``200 OK`` acompañado de todos los asistentes que existen en el local. Esta ruta es invocada por parte del manejador de torneos al recibir una petición proveniente de un asistente del cual no se tiene registro. Observaciones ^^^^^^^^^^^^^ - El nombre de usuario y el correo de un asistente deben ser únicos. - La contraseña de un asistente debe ser de longitud no menor a 6 caracteres. .. _borrar-asistente: Borrado de asistente -------------------- Flujo ^^^^^ Offsite: ``DELETE /assistants/{id}`` ************************************ **Autorización:** User (*onsite*, *super*) Mediante este ruta se solicita la remoción del registro de un asistente del servidor Offsite, proporcionando en la ruta el identificador del asistente. Como consecuencia, se elimina el asistente y su Access Key correspondiente del sistema, quedando así tanto el correo como el nombre de usuario libres para ser tomados por otra entidad a crear. La ruta responde con el estado ``200 OK`` acompañado del asistente eliminado. Si el asistente no pudo ser localizado, se responde con el estado ``404 Not Found``. Al eliminarse el asistente, quedan libres tanto el correo como el nombre de usuario para ser tomados por otra entidad a crear. El tipo de borrado de la entidad es *hard delete*. Portal de jugador ================= El portal de jugador permite los ``Player`` autenticados llevar a cabo operaciones sobre su cuenta. Un jugador que desee interactuar con el portal debe autenticarse ante Offsite con el fin de obtener un secreto, y así firmar los JWT que envíe con sus peticiones. Descripción general ------------------- Los jugadores inician con su dirección de correo electrónico y contraseña ante Offsite para obtener un ``secret``. La invocación a cualquier otra ruta distinta al inicio de sesión requerirá incluir un JWT firmado con el ``secret`` proporcionado por Offsite en este paso. .. image:: /images/authentication/player_login_overview.svg :align: center En caso de que el jugador realice peticiones a Onsite, estas deberán incluir también un JWT firmado con el ``secret`` que le fue proporcionado por Offsite, por lo que Onsite deberá consultar la validez del JWT recibido en la petición. .. image:: /images/authentication/player_authentication_overview.svg :align: center En caso de recibir un JWT correspondiente a un ``subject`` del cual no se tiene registro, si habiendo usado el ``secret`` conocido no es posible verificar la validez del JWT, o si el Access Key ya expiró en Onsite, este debe consultar a Offsite para conceder acceso al usuario. Si el jugador existe en Offsite, este devuelve a Onsite los datos del jugador con con el fin de que la información sea consistente en ambas entidades. Flujo ----- Se requieren las siguientes rutas para el manejo de la sesión del jugador: .. _login-jugador: Offsite: ``POST /players/login`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Donde un jugador ingresa con su dirección de correo electrónico y una contraseña. A continuación, debe crearse en el servidor un ``secret`` que será devuelto al jugador para que firme las peticiones subsecuentes, mismo que debe expirar 7 días después de la fecha de creación, o de actualización en caso de que el campo ``accepted_at`` sea no nulo. Para verificar la fecha de expiración se consulta el atributo ``expires_at`` del Access Key, el cual corresponde a una fecha UNIX en segundos. La petición de inicio de sesión lleva por cuerpo .. code-block:: javascript { "email": "jose@domain.com", "password": password } Si el jugador con el correo electrónico especificado existe y la contraseña es correcta, se sobreescribe el Access Key asociado al jugador que ingresa al sistema; esto es con el fin de limitar la creación de Access Keys a uno por entidad autenticada. En caso de sobreescritura, los valores reeemplazados son ``secret``, ``expires_at``, ``accepted_at`` y ``requested_password_recovery_at``, donde este último es establecido como nulo. La fecha de expiración se actualiza a 7 días después de la fecha actual. Debe verificarse que la fecha de la última transacción del jugador sea menor a tres meses. En caso contrario, debe crearse una transacción negativa con el monto igual al saldo del jugador; esto con el objetivo de expirar sus monedas. Esta transacción no será reportada al sistema Vista. Si el correo electrónico y la contraseña corresponden a un jugador existente, se devuelve el estado ``200 OK`` acompañado del secreto correspondiente. Si las credenciales proporcionadas son inválidas, es decir, la combinación *(email, password)* no existe, se devuelve el estado ``401 Unauthorized``. Para peticiones subsecuentes, el jugador se autenticará con un JWT firmado con el secret recibido en el inicio de sesión, y el cual llevará por payload el siguiente JSON codificado .. code-block:: javascript { "sub": "jose@domain.com", "iat": 1469491719 } Al recibir un JWT, el servidor debe verificar que el valor ``iat`` contenido en el payload no difiera en más de dos minutos de la fecha actual del servidor; esto con el fin de evitar ataques de replay. Esto no implica que se requiera un nuevo inicio de sesión, sino el reenvío de la petición. .. _logout-jugador: Offsite: ``POST /players/logout`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Autorización:** Player Donde se solicita el cierre de sesión de un jugador, ocasionado que se establezca como nulo el valor ``accepted_at`` del Access Key correspondiente. Al haber efectuado el cierre de sesión en Offiste, esta persiste en el servidor Onsite donde se copiaron los valores de autenticación del jugador. Si el cierre de sesión es exitoso, se devuelve un estado ``200 OK``. De ocurrir un error en el servidor, el estado a devolver es ``500 Internal Server Error``. Offsite: ``GET /players/access_keys/{token}`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Autorización:** Location Donde Onsite solicita a Offsite la información de un jugador con el objetivo verificar su autenticación para una petición recibida. La ruta responde con el estado ``200 OK`` acompañado del jugador que cumple con el criterio de búsqueda. .. hint:: Al recibir respuesta de esta petición, Onsite actualiza el valor ``avatarUrl`` del jugador para que coincida con aquel devuelto por el servidor Offsite. Consulta de validez de sesión ============================= Es posible que durante el transcurso de la sesión de un usuario, sean cambiados los permisos de éste, o, en el caso final, que el usuario en cuestión sea eliminado del sistema. Dado que una gran parte de las consultas se hacen sobre los servidores Onsite, es necesario que éste tenga registro de la validez de la sesión del usuario. Para lograr lo anterior, se usa al servidor Offsite como servidor de autenticación. Esto es, en cada ocasión que un servidor Onsite reciba una petición con una autenticación de usuario, será necesario consultar al servidor Offsite para conocer la validez del token proporcionado en la consulta. Si el token es válido y la jerarquía del usuario es acorde a la petición efectuada, esta es permitida en el servidor Onsite. De lo contrario, la solicitud del usuario es rechazada. A continuación se indica la ruta empleada por el servidor Onsite para la consulta de la validez de un token de usuario. Flujo ----- Offsite: ``GET /users/access_keys/{token}`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Autorización:** Location Mediante esta ruta se consulta la información de autenticación de un usuario que lleva a cabo una petición en el servidor de una sucursal, proporcionando el token obtenido de Offsite mediante el inicio de sesión. La ruta responde con el estado ``200 OK`` acompañado del usuario cuya sesión activa corresponde al token proporcionado. Si no existe un Access Key no expirado con el token proporcionado, se responde con el estado ``404 Not Found``. Estructura de los JSON Web Token empleados ========================================== Un JSON Web Token empleado para la identificación ante un servidor de Arena consta de las siguientes cadenas concatenadas con ``.`` : 1. **Header**. Un JSON codificado que contiene el algoritmo a utilizar y el tipo de token .. code-block:: javascript { "alg": "HS256", "typ": "JWT" } 2. **Payload**. Un JSON codificado que contendrá los siguientes valores .. code-block:: javascript { "sub": "CUY7sR3", "iat": 1469491719 } donde ``sub`` corresponde al *subject*, el identificador generado por el servidor para la entidad que le envíe peticiones; e ``iat``, el cual corresponde a la fecha Unix en segundos en la cual se emitió el token (*issued at*). 3. Una firma de verificación generada como se establece en el estándar *RFC 7519*.