RESTful API for users' data - web-services

I would like to develop a website, with reusable API - and REST-sty;e one should suite quite well.
Lets say that each user can store information about books they like. So I have many users, and each of them can have many books.
As I suppose, I would get list of books by some kind of request as below:
GET /book
But.
User should list only his books, not all of them, that are stored on the server. So how to do this properly?
As I read through many SO Q&A, it seems to be not RESTful to leverage standard authentication with cookies and session id (like it is common with PHP or others), because it preserves state on the server.
Then, first request (GET /book) would not return any results (user not logged in), and after logging, it would return list of this user's books.
Another solution I came across, is to append credentials to every request, like:
GET /book?user=john&pass=1234
Despite of TLS (HTTPS) requirement of that (because of plaintext data), it just seems wrong. Seems like redundancy, bandwith waste, each-request validation etc.
My question is:
If I am not wrong, how to do this good way? Both from the good programming point of view, and performance/network usage prespective?
And maybe REST is not suitable for user owned data?
EDIT:
And OAuth and similar solutions seem way too complicated (and they add overhead too, I think?).

You can add a first mandatory REST method to get an authentication token, so you can require this token in all other REST requests and use it to filter the results.

Use the Authorization header to pass credential information. If OAuth is too complex, use Basic auth over SSL... like so:
GET /user HTTP/1.1
Authorization: Basic ZmlkZGxlcnBpYW5pc3Q6aGVsbG93b3JsZA==
Accept: application/json
(other headers here)
Though I'd definitely recommend a URL that's unique to your user, such as this one:
GET /users/fiddlerpianist/books HTTP/1.1
Note that, in a stateless RESTful service, there is no concept of login or logout. The Authorization header would be passed from the client with every request.

Related

Django: Send a Post Request Through Form to Another Server

I have a form on a template on my domain1 and want to send a POST request to domain2. I am using Django as the framework. I only want domain2 to accept requests from domain1 and domain2 (itself). However, I run into csrf problems.
You need a RESTful API. That's a very large topic and would be dumb/impossible to do the work for you here with the info I've been given, so here's a summary.
I suggest Django Rest Framework for making api's.
What the above means, is that when you want to do this sort of stuff (POST requests from other domains), you need a token. This is usually done with a Json Web Token. Also known as JWT's.
The process goes like this:
Get access token from other site to have permission to use the API from that site. Certain http headers, passwords, etc, are often included with this every single time data is exchanged.
Once you get a response giving you permission, you can now perform the type of request you want, with the data you want.
The data format for all this is USUALLY done with JSON. So you will have to import json, then json.dumps(obj) to turn it into valid json, and json.loads(obj) to turn your response into a python dictionary, so you can use it in your template, or wherever you want.
If you want to see an example of this, I recently made a free GoFundMe clone on my guthub. In the donate() view at the bottom, it uses the requests library, and shows how a JWT is obtained and used. You can see it there.

Security about a simple REST web service

Here is my little API with two URL :
/api/location/list -> GET
/api/location/detail -> GET
I'm looking for a process to secure this service with authentication. For now, it can be accessed by only one user (me).
I think oAuth is too complex in my case and I found this resource for designing a simple API.
I understand the principle of private/public key and HMAC but I have a big concern about this :
Say my webservice is consumed by an ajax request with GET verb. I have something like /api/location/list?apikkey=userid&hash=abcde.
A end user can easily sniffed the network during the request (via a simple chrome console), capture full url and access directly to the service multiple times (I think it's a case of replay attacks).
Differents resources talk about timestamp or nonce to make a request unique but I'm a bit lost with implementation.
Any ideas ?
You can try JWToken auth specs, simpler than Oauth, but avoid authorization data as url parameter if possible and use Header's request instead.
If needed consider also ssl encryption at tcp level.
Perhaps you could try to use a token-based approach for security, as described in this blog post:
Implementing authentication with tokens for RESTful applications - https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
The idea is to authenticate to an authentication resource (that can be part of your application) to get temporary token that can be refreshed with a refresh token when expired.
With the use of HTTPS, it seems to be appropriate.
I think that it depends on the security level you expect. Signature-based authentication (the AWS approach) is great but is a bit complex to implement by hand.
Hope it helps you,
Thierry

Are JAXRS restful services prone to CSRF attack when content type negotiation is enabled?

I have a RESTful API which has annotations like #Consumes(MediaType.JSON) - in that case, would the CSRF attack still be possible on such a service? I've been tinkering with securing my services with CSRFGuard on server side or having a double submit from client side. However when I tried to POST requests using FORM with enctype="text/plain", it didn't work. The technique is explained here This works if I have MediaType.APPLICATION_FORM_URLENCODED in my consumes annotation. The content negotiation is useful when I'm using POST/PUT/DELETE verbs but GET is still accessible which might need looking into.
Any suggestions or inputs would be great, also please let me know if you need more info.
Cheers
JAX-RS is designed to create REST API which is supposed to be stateless.
The Cross Site Request Forgery is NOT a problem with stateless applications.
The way Cross Site Request Forgery works is someone may trick you to click on a link or open a link in your browser which will direct you to a site in which you are logged in, for example some online forum. Since you are already logged in on that forum the attacker can construct a url, say something like this: someforum.com/deletethread?id=23454
That forum program, being badly designed will recognize you based on the session cookie and will confirm that you have the capability to delete the thread and will in fact delete that thread.
All because the program authenticated you based on the session cookie (on even based on "remember me" cookie)
With RESTful API there is no cookie, no state is maintaned between requests, so there is no need to protect against session hijacking.
The way you usually authenticate with RESTFul api is be sending some additional headers. If someone tricks you into clicking on a url that points to restful API the browser is not going to send that extra headers, so there is no risk.
In short - if REST API is designed the way it supposed to be - stateless, then there is no risk of cross site forgery and no need to CSRF protection.
Adding another answer as Dmitri’s answer mixes serverside state and cookies.
An application is not stateless if your server stores user information in the memory over multiple requests. This decreases horizontal scalability as you need to find the "correct" server for every request.
Cookies are just a special kind of HTTP header. They are often used to identify a users session but not every cookie means server side state. The server could also use the information from the cookie without starting a session. On the other hand using other HTTP headers does not necessarily mean that your application is automatically stateless. If you store user data in your server’s memory it’s not.
The difference between cookies and other headers is the way they are handled by the browser. Most important for us is that the browser will resend them on every subsequent request. This is problematic if someone tricks a user to make a request he doesn’t want to make.
Is this a problem for an API which consumes JSON? Yes, in two cases:
The attacker makes the user submit a form with enctype=text/plain: Url encoded content is not a problem because the result can’t be valid JSON. text/plain is a problem if your server interprets the content not as plain text but as JSON. If your resource is annotated with #Consumes(MediaType.JSON) you should not have a problem because it won’t accept text/plain and should return a status 415. (Note that JSON may become a valid enctype one day and this won’t be valid any more).
The attacker makes the user submit an AJAX request: The Same Origin Policy prevents AJAX requests to other domains so you are safe as long as you don’t disable this protection by using CORS-headers like e.g. Access-Control-Allow-Origin: *.

How do I implement login in a RESTful web service?

I am building a web application with a services layer. The services layer is going to be built using a RESTful design. The thinking is that some time in the future we may build other applications (iPhone, Android, etc.) that use the same services layer as the web application. My question is this - how do I implement login? I think I am having trouble moving from a more traditional verb based design to a resource based design. If I was building this with SOAP I would probably have a method called Login. In REST I should have a resource. I am having difficulty understanding how I should construct my URI for a login. Should it be something like this:
http://myservice/{username}?p={password}
EDIT: The front end web application uses the traditional ASP.NET framework for authentication. However at some point in the authentication process I need to validate the supplied credentials. In a traditional web application I would do a database lookup. But in this scenario I am calling a service instead of doing a database lookup. So I need something in the service that will validate the supplied credentials. And in addition to validating the supplied credentials I probably also need some sort of information about the user after they have successfully authenticated - things like their full name, their ID, etc. I hope this makes the question clearer.
Or am I not thinking about this the right way? I feel like I am having difficulty describing my question correctly.
Corey
As S.Lott pointed out already, we have a two folded things here: Login and authentication
Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.
Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.
Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}".
Alternatively, you return a document containing the access-token and a href with the resource's link:
<access-token
id="{access token id goes here; e.g. GUID}"
href="/accesstokens/{id}"
/>
Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.
The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)
You don't "login". You "authenticate". World of difference.
You have lots of authentication alternatives.
HTTP Basic, Digest, NTLM and AWS S3 Authentication
HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.
Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.
?username=this&signature=some-big-hex-digest
This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.
Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.
Great question, well posed. I really like Patrick's answer. I use something like
-/users/{username}/loginsession
With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.
The resource is a login session, and that may have an access token or auth code, expiry, etc.
Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.
Edit
I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.
The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.
My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.
It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.
Since quite a bit has changed since 2011...
If you're open to using a 3rd party tool, and slightly deviating from REST slightly for the web UI, consider http://shiro.apache.org.
Shiro basically gives you a servlet filter purposed for authentication as well as authorization. You can utilize all of the login methods listed by #S.Lott, including a simple form based authentication.
Filter the rest URLs that require authentication, and Shiro will do the rest.
I'm currently using this in my own project and it has worked pretty well for me thus far.
Here's something else people may be interested in.
https://github.com/PE-INTERNATIONAL/shiro-jersey#readme
The first thing to understand about REST is that its a Token based resource access.Unlike traditional ways, access is granted based on token validation. In simple words if you have right token, you can access resources.Now there is lot of whole other stuff for token creation and manipulation.
For your first question, you can design a Restfull API. Credentials(Username and password) will be passed to your service layer.Service layer then validates these credentials and grant a token.Credentials can be either simple username/password or can be SSL certificates. SSL certificates uses the OAUTH protocol and are more secure.
You can design your URI like this-
URI for token request-> http://myservice/some-directory/token?
(You can pass Credentilals in this URI for Token)
To use this token for resource access you can add this [Authorization:Bearer (token)] to your http header.
This token can be utilized by the customer to access different component of your service layer. You can also change the expiry period of this token to prevent misuse.
For your second question one thing you can do is that you grant different token to access different resource components of your service layer. For this you can specify resource parameter in your token, and grand permission based on this field.
You can also follow these links for more information-
http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
I have faced the same problem before. Login does not translate nicely to resource based design.
The way I usually handle it is by having Login resource and passing username and password on the parameter string, basically doing
GET on http://myservice/login?u={username}&p={password}
The response is some kind of session or auth string that can then be passed to other APIs for validation.
An alternative to doing GET on the login resource is doing a POST, REST purists will probably not like me now :), and passing in the creds in the body. The response would be the same.

How can an authentication key be passed to a restful web service?

Some existing web services I consume have methods that look something like this:
List<Employee> employees =
employeeService.GetEmployees(accessKey, allDepartments);
The accessKey serves two purposes; it acts as both authentication and identification. Only valid access codes are responded to (authentication) and it services as a link to a particular client's data.
If the services were to be done a restful manner I'm not sure how this would be achieved. I definitely would not want to do something like this:
http://www.business.com/<GuidHere>/Employees/
Since this would show the accessKey, which is somewhat secret, (ie, its usually in an encrypted file on the client which uses this) we can't show the GUID in a URI. How is something like this achieved using a restful architecture?
You could send the authentication token using HTTP headers.
If this is a RESTful web service I'm assuming it's being consumed by a machine so why not pass the access key in the url?
At then end of the day you need to put it somewhere and hiding them in hidden form fields in the browser (if the service is to be browsable) isn't much in the way of security.
If the key is so sensitive, why not symmetrically encrypt on the server per session and pass that value around instead?
Just some thoughts.
Kev
If time isn't an issue implementing OAuth security may be useful. OAuth uses a public key, and also a secret. The mess is hashed (in most cases) and the server will use the public key + it's copy of the secret to do the same hashing and make sure its result matches the requests.
The benefit is you wouldn't need to use HTTPS or POST. Get* REST api methods should be using the HTTP GET method (I'm not sure if being RESTful is your goal, just thought I would point that out). I agree with Mr. Pang, use http://www.business.com/employees. The query string could contain the list of department ids.
For your case the service call wouldn't have the 'accessKey' argument, rather it would become the public key (I imagine) and be used in either the headers, query string, or as a POST param.
Some good info on OAuth: http://www.hueniverse.com/hueniverse/
As Troy Alford pointed out, my original suggestion was incorrect. You shouldn't be using POST in a situation like this. You should use a GET request with the authentication information in the HTTP headers. Take a look at basic access authentication for one way to do that.