authenctication token in a queryString - rest

Our current implementation of the REST API uses apiKey inside queryString for all type of request(PUT, POST, GET). I feel it's wrong but can't explain why(maybe the apiKey can be cashed somewhere between server and client). Something like:
POST /objects?apiKey=supersecret {name: 'some'}
So, is it a security problem? Please describe both HTTP and HTTPS connection case

HTTP
Your supersecret values can be seen and intercepted by thirdparties whenever you send it from the client to the server or vice versa irrespective of whether you use PUT,POST, etc. This is even true when you use cookies for storing those values instead of query string.
HTTPS:
When the data is in transit between your client and server it cannot be intercepted since its protected by https, even if it is in query string. But most people consider sending data in query string as bad, since many system logs the query strings. For eg most servers are configured to print the access logs with the path & query parameters. Also if its from a browser it can be stored in your browser history.

Related

RESTful service. Different response and request schema

My understanding of REST is that a resource endpoint should expose the same schema, irrespective of the HTTP VERB. E.g. the same JSON schema is used for:
PUT /foo/
GET /foo/{id}
POST /foo/{id}
How do I handle fields that should only be populated by the server. E.g. created_on, created_by, id.
Should I use separate schema per endpoint?
Do nothing and ignore the created_on value if it's sent by the client?
Return an error if the client tries to send created_on?
My understanding of REST is that a resource endpoint should expose the same schema, irrespective of the HTTP VERB.
That's not quite right. We would normally expect GET and PUT to use similar representations. POST can use the same representations, but frequently doesn't.
For example: on the web we GET HTML documents, but we POST key/value pairs (application/x-www-form-urlencoded).
How do I handle fields that should only be populated by the server. E.g. created_on, created_by, id.
Treat them as optional fields in your schema is the common answer, I think.
Also, keep in mind that the server is not constrained by the semantics of the request. PUT means "make the resource look like the body of the request", but it is perfectly reasonable for the server to make changes of its own to the resource.
Do nothing and ignore the created_on value if it's sent by the client?
Just so.
You need to be a little bit careful not to imply that you've accepted the provided representation as is, see RFC 7231.

What is the correct REST method for performing server side validation?

If I don't want to update a resource, but I just want to check if something is valid (in my case, a SQL query), what's the correct REST method?
I'm not GETting a resource (yet). I'm not PUTting, POSTing, or PATCHing anything (yet). I'm simply sending part of a form back for validation that only the server can do. Another equivalent would be checking that a password conforms to complexity requirements that can only be known by the domain, or perhaps there are other use cases.
Send object, validate, return response, continue with form. Using REST. Any ideas? Am I missing something?
What is the correct REST method for performing server side validation?
Asking whether a representation is valid should have no side effects on the server; therefore it should be safe.
If the representation that you want to validate can be expressed within the URI, then, you should prefer to use GET, as it is the simplest choice, and gives you the best semantics for caching the answer. For example, if we were trying to use a web site to create a validation api for a text (and XML or JSON validator, for instance), then we would probably have a form with a text area control, and construct the identifier that we need by processing the form input.
If the representation that you want to validate cannot be expressed within the URI, then you are going to need to put it into the message body.
Of the methods defined by RFC 7231, only POST is suitable.
Additional methods, outside the scope of this specification, have been standardized for use in HTTP. All such methods ought to be registered within the "Hypertext Transfer Protocol (HTTP) Method Registry" maintained by IANA, as defined in Section 8.1.
The HTTP method registry gives you a lot of options. For this case, I wouldn't bother with them unless you find either a perfect match, or a safe method that accepts a body and is close enough.
So maybe REPORT, which is defined in RFC 3253; I tend to steer clear of WebDAV methods, as I'm not comfortable stretching specifications for "remote Web content authoring operations" outside of their remit.
TLDR; There's a duplicate question around the topic of creating validation endpoints via REST:
In your case a GET request would seem sufficient.
The HTTP GET method is used to read (or retrieve) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).
restapitutorial.com
For validating your SQL query you could use a GET request to get the valid state of your query potentially using a query parameter to achieve this.
GET: api/validateQuery?query="SELECT * FROM TABLE"
Returning:
200 (OK): Valid Query
400 (MALFORMED): Invalid Query
404 (NOT FOUND): Query valid but returns no results (if you plan on executing the query)
I think this type of endpoint is best served as a POST request. As defined in the spec, POST requests can be used for
Providing a block of data, such as the fields entered into an HTML form, to a data-handling process
The use of GET as suggested in another post, for me, is misleading and impractical based on the complexity & arbitrarity of SQL queries.

Rest POST VS GET if payload is huge

I understand the definition of GET and POST as below.
GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale.
POST: Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.
MY API searches for some detail in server with huge request payload with JSON Message in that case Which Verb should i use ?
Also can anyone please let me know the length of the characters that can be passed in query string.
The main difference between a GET and POST request is that in the former, the entire request is encoded as part of the URL itself, whereas in the latter, parameters are sent after the header. In addition, in GET request, different browsers will impose different limits on how big the URL can be. Most modern browsers will allow at least 200KB, however Internet Explorer seems to limit the URL size to 2KB.
That being said, if you have any suspicion that you will be passing in a large number of parameters which could exceed the limit imposed on GET requests by the receiving web server, you should switch to POST instead.
Here is a site which surveyed the GET behavior of most modern browsers, and it is worth a read.
Late to the party but for anyone searching for a solution, this might help.
I just came up with 2 different strategies to solve this problem. I'll create proof of concept API and test which one suites me better. Here are the solution I'm currently thinking:
1. X-HTTP-Method-Override:
Basically we would tunnel a GET request using POST/PUT method, with added X-HTTP-Method-Override request header, so that server routes the request to GET call. Simple to implement and does work in one trip.
2. Divide and Rule:
Divide requests into two separate requests. Send a POST/PUT request with all payload, to which server will create necessary response and store it in cache/db along with a key/id to access the data. Then server will respond with either "Location" header or the Key/id through which the stored response can be accessed.
Now send GET request with the key/location given by server on previous POST request. A bit complicated to implement and needs two requests, also requires a separate strategy to clean the cached responses.
If this is going to be a typical situation for your API then a RESTful approach could be to POST query data to a buffer endpoint which returns a URI from which you can GET your results.
Who knows maybe a cache of these will mitigate the need to send "huge" blobs of data about.
Well You Can Use Both To get Results From Server By Passing Some Data To server
In Case Of One Or Two Parameters like Id
Here Only One Parameter Is Used .But 3 to 4 params can Be used This Is How I Used In angularjs
Prefer : Get
Example : $http.get('/getEmployeeDataById?id=22');
In Case It Is Big Json Object
Prefer : Post
Example : var dataObj =
{
name : $scope.name,
age : $scope.age,
headoffice : $scope.headoffice
};
var res = $http.post('/getEmployeesList', dataObj);
And For Size Of Characters That Can Be Passed In Query String Here Is Already Answered
If you're getting data from the server, use GET. If you want to post something, use POST. Payload size is irrelevent. If you want to work with smaller payloads, you could implement pagination.

PUT or PATCH to change only one field value

I'm thinking to create an API for users to change their password.
User table has some fields like firstname, lastname and so on.
For this API, should I use PATCH like the below?
PATCH /users/{userId}
{
"password": "new_password"
}
Or, should I use PUT?
PUT /users/{userId}/{password}
This seems awful for security.
By the way, I don't want users to change values of other fields. I think PATCH must let users to be able to change values of any fields. That's why I'm wondering.
Path info and query string will be encrypted using HTTPS/TLS - for that HTTP session. However, it is still a bad idea to put passwords there, since they are likely to be in browser history and/or server logs
PUT /users/{userId}/{password}
... that will stay in web server logs. As secure developers, we are not supposed to even store passwords in databases where they can be stolen (we are to store a hash + salt of a password). Having cleartext passwords in web server logs is worse.
Sending it in the body in a TLS session is the best.
PATCH /users/{userId}
{
"password": "new_password"
}
... and then hash+salt it and store that. Logins, you do the same process (one-way hashes match).
See this: HTTPS, URL path, and query string
From a security POV there is no difference. An attack can read both the query string and the request body. You should use TLS.
Both requests look fine to me. Their URLs and their bodies are good, solid REST.
If you don't want to accept changes to all fields, write logic in your server that rejects requests that trie to change fields that are not to be changed by the user. But this is not a question of PUT vs. PATCH or POST.

Best practice for file-based search in rest service

I'm helping build a similarity search service for files. One way to search for something is with a GET request, by giving a file's URL, but I also need to allow clients to send the file directly. I have to following options:
Make the client send a GET request with a Payload; it seems this is not recommended -- HTTP GET with request body
Use something else than GET (maybe a PUT?) for file-based search. The problem is none of the other HTTP methods seems to suit this purpose.
What option would suit best here? I'm not an expert in this field, and I can't figure out what's the right thing to do in this situation.
Here is the rule I have always followed with REST.
GET - only querying data and returning a data set.
POST - Creating data in the database
PUT - Modifying data
DELETE - Destroy data in the database.
If you are sending a payload for search params, you can do a GET and put those params (assuming they are name/value pairs) in the query string of the URI.
i.e. http://my.simsearch.com?param1=first&param2=second ...
If you are actually going to change the database then a POST or PUT is in order.
I hope this helps.
I ended up sending the payload with a GET request. Even though it's not really recommended, hopefully no libraries will complain about this.