identity/docs/asset-implementation.md

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 the asset-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

  1. The client requests a session_key (the Key from now on) to the identity-api, the Key allows the asset-api to perform limited actions on the account of the user.
  2. The client sends a request to the asset-api with the asset and the Key.
  3. The asset-api retrieves the limits that apply to the account by requesting them to the identity-api using the Key.
  4. After some preconditions are met, the asset is stored and a unique ID is generated and linked to the stored asset.
  5. The asset-api adds the unique ID to the user's asset list by sending a request to the identity-api using the Key.
  6. The client receives an OK response from the asset-api.
  7. The client rotates the Key.

Retrieving an asset

  1. The client requests a session_key (the Key from now on) to the identity-api, the Key allows the asset-api to perform limited actions on the user's account.
  2. The client sends a request to the asset-api with the asset ID and the Key.
  3. The asset-api retrieves the user's asset list by requesting it to the identity-api using the Key.
  4. After some preconditions are met, the asset is sent back to the client.
  5. The client receives the asset from the asset-api.
  6. 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_keys 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_keys 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_keys 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.