A nodejs notebook web app with client side encryption. A place to write down important information where you can always get at it.
The .prisma
file is purely for database purposes. It is the raw model of data. The .graphql
is the definition for the graphql schema that is interpretted by Apollo. There will probably some overlap, but these do not need to match. The resolvers are used to define how to respond to graphql requests.
Explain what each script does and the intended purpose for that script.
In order for this application to work, you will need to make sure to have docker installed and accessible without needing sudo access from the current user.
You can install docker using their guides here: https://docs.docker.com/get-docker/ https://docs.docker.com/engine/install/ubuntu/
You can follow this gist to get docker access without sudo: https://github.com/sindresorhus/guides/blob/main/docker-without-sudo.md
Using JWT tokens that contain a user and an id (and expiration built in)
JWT lifetime = 1 day
Stored in HTTP only cookie called jwt
A new JWT encoding/decoding secret is generate each time the server starts
An in memory list of invalidated tokens (store an ID and expiration)
Regularly prunes the invalidated JWT tokens list for expired tokens every 10 minutes
Client can also set their own web3
cookie that contains a web3-token
jwt
will take priority over web3
when authenticating on the server
web3
does not rely on the server side encryption id
Application functions are injected with the current user so each action can be checked for permissions. The resolvers simply link the authorized requests with the appropriate application calls. Permission errors are thrown in application.js (the business logic).
The notebook has a key field at the top of the app. This key is combined with the user id to generate a seed for an encryption key. The encryption key is then hashed and attatched to notes stored in the database so the client can make requests for notes that use the current key. If an authentication token was somehow stolen, an attacker may be able to pull notes from the server, but all of the important data will still be encrypted. So they still need the associated key for each note to be able to read them.
Key: <some string>
User enters key at the top of the app
Seed: <User ID + Key>
A seed is generated by combining the User ID and the Key. This could be done with just the Key, but it means that the Encryption Key of an empty string Key '' would be the same for all users, which is not ideal.
Encryption Key: hash(Seed)
The key actually used for encrypting and decrypting
Key ID: hash(Encryption Key)
A hash of the Encryption Key that can be stored server side inside a note to identify which notes to send to the user when they are using a certain key
The encrypt and decrypt functions are then used on the string based fields stored in the database when posting requests and parsing responses.
Firefox will say that a cookie has expired when in reality it is being intentionally removed by the server. This is a known issue and is safe to ignored.