identity/docs/asset-implementation.md

66 lines
No EOL
4.2 KiB
Markdown

# 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](../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/](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_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.