4.2 KiB
Asset implementation
Storing and serving user-generated assets is a difficult task due to potential abuse and the complexities of the web ecosystem.
To overcome some of these shortcomings, there are two distinct services in the Identity project: identity-api
(user data), and
asset-api
(user-generated assets).
This document explains how both of these services communicate and potential improvements that may be implemented in the future.
Introduction to the M2M mechanism
The basis of the M2M mechanism are the following:
asset-api
generates a pubkey pair. The public key is exposed to the public.identity-api
loads theasset-api
's public key at intervals.identity-api
exposes some M2M routes that perform actions such as: retrieving the account of a given user, associating assets to an user account, etc.
Each request performed by asset-api
to identity-api
is signed using the pubkey pair, which allows the identity-api
to verify
that the requester is the asset-api
using the retrieved public key. (Implementation: $/identity-api/src/m2m.ts)
The request body is signed in a PGP-like manner, this can be seen by accessing the index page of the asset-api
(http://localhost:3001/ in default local environments).
Actions
Uploading an asset
- The client requests a
session_key
(the Key from now on) to theidentity-api
, the Key allows theasset-api
to perform limited actions on the account of the user. - The client sends a request to the
asset-api
with the asset and the Key. - The
asset-api
retrieves the limits that apply to the account by requesting them to theidentity-api
using the Key. - After some preconditions are met, the asset is stored and a unique ID is generated and linked to the stored asset.
- The
asset-api
adds the unique ID to the user's asset list by sending a request to theidentity-api
using the Key. - The client receives an OK response from the
asset-api
. - The client rotates the Key.
Retrieving an asset
- The client requests a
session_key
(the Key from now on) to theidentity-api
, the Key allows theasset-api
to perform limited actions on the user's account. - The client sends a request to the
asset-api
with the asset ID and the Key. - The
asset-api
retrieves the user's asset list by requesting it to theidentity-api
using the Key. - After some preconditions are met, the asset is sent back to the client.
- The client receives the asset from the
asset-api
. - The client rotates the Key.
Analysis of the current implementation
The current implementation works fine and it's quite fast. The use of pubkey cryptography allows for an easier handshake and thus
there's less hoops that the asset-api
has to go through to prove its identity.
Currently, the identity-api
obtains the asset-api
's public key and algorithm by sending an HTTP(S) request. This simplifies
the infrastructure and allows the asset-api
to rotate keys on the fly, but it also has the downside that the identity-api
must trust that the URL to the asset-api
is not compromised. Using manual key rotation would be more secure in that sense,
but in practice rotation would be much slower, potentially leading to more practical security problems.
It is theoretically possible to make the identity-api
trust third-party keys using techniques such as DNS poisoning, but in
order to execute such a targeted attack the overall infrastructure must already be compromised.
The use of session_key
s adds another layer of security: the asset-api
must prove its identity, and the user must have given
consent for that service to perform limited actions on their behalf. The current issue is that session_key
s are not time-limited,
which means that if a rotation is not performed, a session_key
could theoretically be completely valid for years.
That could lead to some theoretical attacks, but the scope of session_key
s is so limited that they aren't an issue. Still, in
future iterations of the M2M mechanism this issue will be solved.
Overall, the current implementation is not perfect but it is secure enough for the current use case. In the future, the implementation of standards like OAuth may be considered more adequate.