Una aplicación web que estoy desarrollando será una aplicación de una sola página (SPA) que interactuará con un backend API REST, a través de jQuery.ajax()
calls.
El SPA y la API se servirán a través de una conexión https / TLS. La API se servirá desde un subdominio del dominio SPA:
SPA: example.org
API: api.example.org
... y responderá con los encabezados CORS apropiados:
Access-Control-Allow-Origin: example.org
Access-Control-Allow-Methods: GET, POST, etc. // whatever applicable to the requested resource
Access-Control-Allow-Headers: Accept, Authorization, Content-Type
Al iniciar sesión en el SPA, el usuario (una organización) recibirá su sha1 API-key
asociado único (ya sea en una cookie o como una variable javascript global), que el SPA utilizará para interactuar con la API, para el Duración de la sesión de inicio de sesión del usuario. El SPA emitirá este API-key
en cada solicitud a la API en un encabezado Authorization
:
Authorization: MyAppsApi apikey=<API-key>
El almacenamiento de persistencia de la API REST se basará en XML. Todavía no me he decidido por un proveedor de mecanismos de almacenamiento real (considerando el uso de eXistdb , por el momento). Sin embargo, en esta etapa temprana de desarrollo, simplemente estoy usando DOMDocument
de PHP y DOMXPath
, sin capacidades de lectura / escritura concurrentes.
La API REST además generará dinámicamente consultas XPath, basadas en la ruta del URI de la solicitud recibida. Sin embargo, la comunicación entre el SPA y la API probablemente se hará en JSON.
Considere este ejemplo de documento XML:
<?xml version="1.0" encoding="utf-8"?>
<organisations>
<organisation id="1">
<apiKey>some hex sha1 digest</apiKey>
<products>
<product id="1">
<parts>
<part id="1">
<subParts>
<subPart id="1">
...
</subPart>
</subParts>
</part>
</parts>
</product>
</products>
</organisation>
<organisation id="2">
<apiKey>another hex sha1 digest</apiKey>
<products>
...
</products>
</organisation>
</organisations>
Actualmente, este documento se valida mediante un esquema XSD personalizado.
La API REST primero determinará si existe un nodo <organisation>
con el <apiKey>
emitido antes de seguir interactuando con el XML. Si se encuentra el nodo <organisation>
, se usará como el nodo de contexto para cualquier consulta XPath adicional.
Las rutas URI de solicitud estarán restringidas por el siguiente patrón de expresiones regulares:
~\G(/(?<collection>[a-z]+)(?:/(?<resourceId>\d+))?)(?:(?=(?1))|/?$)~
permitiendo solo /<loweralpha>+(/<digit>+)?
segmentos
Considere estas rutas de ejemplo de URI de solicitud y sus XPath generadas dinámicamente:
/products/1 => .//products/*[@id="1"]
/parts/1 => .//parts/*[@id="1"]
/products/1/parts/1 => .//products/*[@id="1"]/parts/*[@id="1"]
Como puede ver, serán relativos al nodo de contexto <organisation>
.
Teniendo en cuenta que aún no he investigado completamente el funcionamiento típico de los backends XML, puede resultar que mi configuración de XML anterior sea defectuosa para empezar, ya que debo crear un documento XML por organización, mitigando el riesgo de acceder a nodos que no pertenecen al nodo de contexto <organisation>
.
Sin embargo, ¿ve algún defecto inherente en esta configuración actual?
En mi configuración actual, me preocupa sobre todo la consulta dinámica de XPath que podría resultar demasiado arriesgada. Tal vez un adversario es capaz de colarse en los ejes XPath, de alguna manera? Pero también me interesa conocer otras posibles fallas.
Gracias.
PS .: quizás debería haber aclarado más cuáles son los riesgos, lo que más me preocupa:
- ¿Puede un adversario obtener de alguna manera la clave API de una (otra) organización?
- ¿Puede un adversario manipular de alguna manera el contenido de una (otra) organización?