Having a body on a delete request as an additional layer of security - rest

I'm developing an web API and I'm trying to follow the principles of REST. I'm now at the stage of creating the endpoint where a user can delete its own account. I have also implemented JWT functionality where the JWT is valid for 1 day.
I want to add an extra layer of security when the user is deleting its own account. My idea is that the user have to provide its current password in the body of the delete request. I did some googling which pointed to having a body in a delete request is a bad idea because some entities does not support it, e.g. the Angular HttpClient, some web services might strip the body, etc.
I know GitHub have a similar functionality when deleting a repository, you have to provide your password. I like this feature because it prevents unauthorized persons from spoofing the JWT on critical operations, right?
What are your recommendations
Proceed with using DELETE and deal with the potential problems that might come along with this approach?
Instead use POST, PUT or PATCH even though it would look semantically wrong?
Other solution?

I would not recommend to use other http methods like put or patch if you really want to delete it and not only disable it. That would not be intuitive for the API user and could lead to misunderstandings.
One solution for your use case is to introduce an additional resource (e. g. deletionRequest) to request (but not immediately execute) the deletion of the profile with a post call. Then you could do the actual deletion with a delay (preferably longer than the token life span). You could then inform the user via email about the deletion, so the real user has the chance to revoke the deletion. If the user does not react in time, the deletion is executed.

Related

What is the best approach to stop your platform's users to "sniff" the frontend requests to backend and modify them?

So I have a platform that works like this: Users can create accounts by logging in with their Google (I USE AUTH0) and then they can create "Projects" which contain lots of other unimportant stuff regarding my current problem (like todo lists, ability to upload files etc; they can also Edit the project by changing some of it's attributes like name, description, theme and so on). There is a home page where everyone can see each other's projects and access them (but not upload files, change the tasks in the to do lists; this is possible only by the person that owns it).
By using a tool like Burp, people can see the request made from frontend to backend, for example when accessing one of the projects, and modify it on the fly.
This is what it looks like inside Burp when they access one of the projects:
As you can see there is a Get request to /projects/idOfTheProject; they can replace the GET with DELETE for example and they will successfully delete it; they can also see what is sent to the backend when a project is edited (name changed, description, thumbnail picture etc) and change anything they want about it.
How should I prevent this?
What I've looked at so far:
a. JWT - Probably the best fitting for my situation, but required the most work to be done (as I already have my platform almost finished with no such a security measure implemented yet, so I may need to rewrite a lot of things in both backend and frontend)
b. Sending the user's id that initiated the action as well to the backend and verify if it has the necessary privileges - the worst solution as users can access each other's profile and see the id, then just change another field in the request's JSON
c. Have a sort of token for each user and send that instead of the user's id - in this way somebody can't get your token by just looking at the communication between frontend and backend (only if it is using YOUR account). That token should be taken maybe somewhere from the auth0 when they create their account? If they provide something like that; or I can just create it myself and store it alongside the other user variables. You would still see the requests in plain text but even if you modified something you would still have to "guess" the owner's token, which will be impossible.
For frontend I use NextJS and for backend Flask.
Thank you in advance!
The TL;DR is that you don’t. A determined user will always be able to see what requests are being sent out by the code running on their computer and over their network. What you are describing when asking how to prevent people from “sniffing” these requests is security through obscurity, which isn’t actually secure at all.
What you should do instead is have an authorization system on your backend which will check if the current user can perform a given action on a given resource. For example, verifying that a user is an administrator before allowing them to delete a blog post, or making sure that the current user is on the same account as another user before allowing the current user to see details about the other user.

Creating user record / profile for first time sign in

I use an authentication service Auth0 to allow users to log into my application. The application is a Q&A platform much like stackoverflow. I store a user profile on my server with information such as: 'about me', votes, preferences, etc.
When new user signs in i need to do 1 of 2 things:
For an existing user - retrieve the user profile from my api server
For a new user - create a new profile on the database
After the user signs in, Auth0(the authentication service) will send me some details(unique id, name and email) about the user but it does not indicate whether this is a new user(a sign up) or a existing user(a sign in).
This is not a complex problem but it would be good to understand best practice. I can think of 2 less than ideal ways to deal with this:
**Solution 1 - GET request **
Send a get request to api server passing the unique id
If a record is found return it
Else create new profile on db and return the new profile
This seems incorrect because the GET request should not be writing to the server.
**Solution 2 - One GET and a conditional POST request **
Send a get request to api server passing the unique id
The server checks the db and returns the profile or an error message
If the api server returns an error message send a post request to create a new profile
Else redirect to the home page
This seems inefficient because we need 2 requests to achieve a simple result.
Can anyone shed some light on what's best practice?
There's an extra option. You can use a rule in Auth0 to send a POST to the /users/create endpoint in your API server when it's the first time the user is logging in, assuming both the user database in Auth0 and in your app are up-to-date.
It would look something like this:
[...]
var loginCount = context.stats.loginsCount;
if (loginCount == 1) {
// send POST to your API and create the user
// most likely you'll want to await for response before moving on with the login flow
}
[...]
If, on the other hand, you're referring to proper API design and how to implement a find-or-create endpoint that's RESTful, maybe this answer is useful.
There seems to be a bit of disagreement on the best approach and some interesting subtleties as discussed in this post: REST Lazy Reference Create GET or POST?
Please read the entire post but I lean towards #Cormac Mulhall and #Blake Mitchell answers:
The client wants the current state of the resource from the server. It is not aware this might mean creating a resource and it does not care one jolt that this is the first time anyone has attempted to get this resource before, nor that the server has to create the resource on its end.
The following quote from The RESTful cookbook provided by #Blake Mitchell makes a subtle distinction which also supports Mulhall's view:
What are idempotent and/or safe methods?
Safe methods are HTTP methods that do not modify resources. For instance, using GET or HEAD on a resource URL, should NEVER change the resource. However, this is not completely true. It means: it won't change the resource representation. It is still possible, that safe methods do change things on a server or resource, but this should not reflect in a different representation.
Finally this key distinction is made in Section 9.1.1 of the HTTP specification:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
Going back to the initial question, the above seems to support Solution 1 which is to create the profile on the server if it does not already exist.

How to secure REST API PUT/POST calls being called manually through postman

Actually I have an API called update user data, it is called when the user moves from one page to another page. If the user copy the API from console and post in postman, user should not able to update the user data. How to provide security or implement feature to not to update data through post man.
You really can't.
You can slightly make it harder using some CSRF protection, but that's just it - it will only make it a bit harder, but not stop anyone determined.
If your API is public, you should be ready for your users to have custom client apps.
I am a bit confused by your question. Because PostMan or other applications like Fiddler are created to make the job easier for developers during development. anyhow if you are concern about who makes call to your webpage, you can make your API private and just give access to the user that have the right credentials. You can also read about CSRF or XSS.

How to design REST API for non-CRUD "commands" like activate and deactivate of a resource?

Before I decided to ask this question I have searched quite a long for the answer but I haven't found any satisfactory. (e.g. Examples of the best SOAP/REST/RPC web APIs? And why do you like them? And what's wrong with them?)
And the problem is actually quite simple. I have an object/resource named Account. My REST API supports all CRUDs with GET, POST, PUT and DELETE already with proper error handling, status codes etc.
Additionally however I want to expose an API ("command") to activate and deactivate selected Account resource.
Even if the "isActive" is a property of the Account I don't want to use just the Update from my CRUD of the whole Account.
I know it is easy to violate REST principles and make RPC style design with such design like this:
PUT /api/account/:accountId/activate
PUT /api/account/:accountId/deactivate
So what is the best solution for this use case?
My current idea is to use PUT and DELETE verbs like this (to treat it as a sub-resource) as proposed here http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful:
PUT /api/account/:accountId/isActive // for activate
DELETE /api/account/:accountId/isActive // for deactivate
What are your solutions?
How about coming up with a noun for the feature you want to modify - 'status' in this instance. This would then become a sub resource of the parent entity. So for your case I would model the URI as follows:
/api/accounts/{accountId}/status
If the 'update' semantics are idempotent then PUT would be most appropriate, else that would need to be a POST (e.g if nonces are involved and are invalidated by the service). The actual payload would include a descriptor for the new state.
Note, I pluralized 'accounts' since you can have multiple of those, but status is singular since your account can have only one state.
PATCH is the most appropriate method in this case. Please find more at RESTful URL for "Activate"
The POST method would create the resource 'account'. Active can be seen as one of the properties of the resource 'account'. Hence it should be a PUT request.
I would say even deactivate must be a PUT request as the account resource will still exist.
To activate an account you can set a property on the resource. That is:
/api/account/{accountId}?activate=true
To deactivate:
/api/account/{accountId}?activate=false
A GET request on the account would return a JSON with the activate value in it.
A DELETE request should completely delete the account resource.
First off, PUT is appropriate compared to POST, because you are creating a resource to an already-known location. And, I think, there's no dilemma about DELETE. So at first glance, your current approach seems to beat the alternatives.
I used to think the same way, until I implemented my own REST api, in which I wanted the admin to be able to set an account in a deactivated - yet not deleted, just "banned" - state. When I gave it a little more thought, I decided to do it vice versa.
Let me explain. I like to see the activation resource as "the option to activate the account". So if a url like /account/foo/activation exists, it could only mean that the account is not activated and the user has the right to activate it. If it doesn't exist, the account is either already activated or in a banned state.
Consequently, the only rational thing to do in order to activate the account is to try and DELETE the resource. And, in order to enable activation, an admin would have to PUT an activation resource.
Now, the question that comes to mind is how do you distinguish a banned account from an already activated one. But since a ban could be seen as a resource too, you could create a /account/foo/ban resource collection. In order to ban an account, probably for a fixed amount of time, you just POST a resource under that collection, containing all the details of the ban.

Does it violate the RESTful when I write stuff to the server on a GET call?

I would like to record user actions on my website, not only on POST requests, but on GET requests as well. For example, suppose the user tries to search for a city with the following GET request:
/search_city?name=greenville
This request would return a list of cities with the name "greenville". I'd also like to save this keyword to the server, as the "search history" for a user. I'm planning to just do the save this information during the processing of the GET call.
Is this a violation to RESTful principles? If yes, how do I do this the right way?
I see this kind of audit logging as an invisible side-effect. If the next person to call
/search_city?name=greenville
still gets the same answer then your GET is valid. A similar case would be some kind of cache building, the caller of GET doesn't (need to) know that you're doing some extra work.
Focus on the formal API - send this request get this response.
If there's some resource available in the API where the user search history is available, then it's not OK to do that, since your GET request has a visible side-effect. For instance, a client caching responses is under no obligation to know that any resource changed because he did a GET request to anything else. I think the only way to do this and stay compliant is to explicitly mark the side-effected resource as uncacheable.
In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.
Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
If that's kept only for internal usage, I guess it's fine to do it that way, but I still recommend against it.