-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Send a confirmation email before deleting company #184
Comments
Hey, I don't think this is really a matter of encryption here. You really only need to prove the user has access to the side channel, so the solutions usually would be:
A detail that might seem weird to you here is that I suggest storing the user id of who requested the deletion. That's because I think you should re-check the authorization at the time of performing the actual deletion. Finally, my two cents are that the platform admins (gods, right?) should probably still have access to a direct deletion endpoint, or at least a bulk deletion endpoint, because you might need to perform bulk deletions for moderation purposes. |
Hey, answering the question: I don't totally oppose the stateful approach (i.e., using the DB to store token -> deletion request info), however, I have two arguments towards the stateless approach:
From what I know of JWT, that is pretty similar to the solution I described: a set of data in an object, that will be signed and converted to a string. The only difference being that in JWT the data is signed but not encrypted (at least by default, we can always encrypt the data before putting it in the JWT). Since we shall not be sending any private information in the token (companyIds and accountIds may be public), a JWT token would work here. However, I have one question: when you mention Finally, regarding other endpoints/features, that should be discussed in another issue for that matter (I think regardless of the "requester", there should always be a confirmation step, due to the nature of the request. regarding bulk operations, that's something to think in the future maybe) |
Yes, those fields would make up the payload. I want to put the emphasis on the jwt-like in my other comment. JWT is a specific format for authentication/authorization that needs to support a lot of stuff like different encryption schemes and what not. It would probably be enough to issue a token like: const token = {
version: "1.0.0",
payload: {
companyId: "wtv",
requesterId: "wtv",
issueTime: "2021-09-06T07:29:50.000Z", // or epoch-based timestamp
// optionally a nonce here too
},
signature: "abcxyz this would be some sort of signature of the payload with an asymmetrical key"
} Then you can generate the URL either by base 64 and url-encoding the entire token or simply by generating a query string (won't commit to a format suggestion here). Either way, the point here is that you share with the authentic user a piece of data that only you can access: on the db-backed case, you're the only one who knows which IDs have been stored and the user is the only one who knows their key to that collection, and on the token-based solution, only you have the private key and only the user knows what would be the signature for their specific token. Now, I still think this token based approach, even when simplifying the most we can while keeping the properties we need, turns out over-engineered vs storing an extra kilobyte for each deletion request. I also wanted to push back and say that I doubt that for this specific use case industry uses more cryptographic keys than db-backed keys, since as soon as you start needing to account for other concerns, like rate-limiting these kinds of destructive requests, you will probably need to store it somewhere either way. Now, I am not planning on implementing this regardless of the chose architecture, so it is not my choice to make, but I just want to make sure the decisions taken are well thought out and the simplest they can be. Engineering is more than cleverness and premature optimisation, after all! 😃 |
Currently, after #178, companies (or gods) can delete a company by calling the respective endpoint, which will trigger the deletion of the offers, the company, and the associated account.
As this is really destructive, this endpoint should only send a confirmation email to the respective company with a link to execute the deletion, should they really want to do it.
The link would be to a new endpoint (which can be called at
/:companyId/delete
, and we can change the current one to/:companyId/requestDeletion
to make it more accurate).This new endpoint would have an associated "code", containing all the relevant data, in a secure/ non-easily-reproducible way. Of the top of my head, I'm thinking we can have a "secure string" in .env (similar to the one we use for session cookies -
SESSION_SECRET
) which would be our symmetric key used both for encryption/decryption.The data (to be encrypted by that key) should contain all the relevant parameters so that the endpoint knows what to delete (maybe only the companyId is enough, maybe you want to add more things to make it faster - accountID?), however you can also add a timestamp, so that if more than X time has passed, the endpoint won't do anything, again, for safety. Then you should JSON.stringfy that data and encrypt it, which will give you a nice "random" string (generated in the
/requestDeletion
endpoint, which will be a parameter of the/delete
endpoint. That endpoint will use the same key to decrypt the data and execute the deletion.Here you can see more or less how this would work in terms of encryption/decryption: https://gist.github.com/ccorcos/1a26653ac5b59cdc3a59 (it's a bit outdated, so you may need to research if nodejs has updated these functions), just search for symmetric encryption with nodejs
The text was updated successfully, but these errors were encountered: