RESTful principles question - authentication

An intelligent coworker friend of mine brought up a question to me that I was uncertain how to answer and I'd like to pose it to the world.
If a RESTful endpoint uses token-based authentication, aka a time-based token is required to access a resource and that token expires after a certain amount of time, would this violate the RESTful principle? In other words, if the same URL expires after a certain amount of time, so the resource returns a different response depending when it was requested, is that breaking REST?

No, your scenario is not breaking any restful principle that I can think of. You seem to be confusing a request returning a different resource and a request getting a different response.
In your scenario I would expect after the token has expired that the server would return a 401 and the client would initiate some kind of authentication exchange to re-validate the user.
Once revalidated, the server should then return the intended resource.
There are many cases when a request could have completely different responses. 403 Forbidden, 410 Gone are examples.

The user/application access right to the URL may expire but that does not mean the URL expires. In large real world systems the auth part of the API may be handles by a different product, shielding the real API from attacks, unauthorized users, etc. So the RESTful API still follows the restful principles.

Your design is not violating REST constraints, but you must be careful that you use HTTP correctly. If your resources are only intended to be seen by a certain user, that user should be authenticated using HTTP authentication. This will tell public caches not to cache the representations of the resource (which they otherwise usually would).
So, even if you intend the URL to be only known by a certain user, make sure you also have that user authenticate itself using the correct HTTP headers.
Jan

Resources will frequently give a different response depending on when they are requested. That's what happens when the actual resources change over time. Requesting the resource of this page (for instance) in a week will likely give different responses than doing so when you read this the first time.

Related

Can I use GET api when passing authentication token

This is a theoretical question. For some APIs, user need to authenticate themselves and we have authentication token for a user. I feel using GET api is not good idea due to this token.
/get_data/?user_token=hshhlj8979kjhk&dataid=87979
Indeed it's not a good idea, but not due to GET in itself. The real problem is the token as part of the URL and the security problems it creates.
The URL portion of a request is very often cached and logged for auditing or debugging purposes, and having the token there causes it to leak unintentionally.
For example, browsers save your browsing history, and the main portion they record is the URL, so there goes your password to your history, a place it doesn't belongs and is easily exposed accidentally.
Most web servers by default also log the URLs they receive, so again there goes your token. It's quite common for it to end up in logs on web servers, load balancers, intermediate routers and so on, again leaking all over the place.
The solution to this is to strip the token from the URL portion, leaving there only data that's not security-critical. The most common place to put it is in the request's headers. Those are well respected by the HTTP standard and almost never logged or accidentally dumped like the URL.
Of course, all other methods suffer the same. POST, PUT, DELETE, OPTIONS for example, none of them should be ever called with secret data in the URL. Headers provide a "safer" place for that available across all methods. The request body is another common place, but you can't have one in GET, making a header the best alternative.

Appropriate HTTP status for redirecting to authentication in a REST api

I'm kind of surprised that, after searching for this for a while, I didn't find as many answers as I thought would be out there (well I found none), so maybe by asking it here we can help improve search results.
I'm building a REST api which has JWT-based authentication. There is an /auth/login route which returns the token after login/password verification, and the token is subsequently sent in every route in a Authorization http header.
Not, suppose that someone queries another route (say, /cars), without sending the token (that is, before logging in). If I return a 401 unauthorized, I can make the frontend query /auth/login to get the token.
But, strictly speaking, this does not conform to the REST specification, because every resource should be discoverable from the initial one, and a client accessing /cars and receiving a 401 will not know about /auth/login.
So another option would be a redirection like 302. But this semantics means that the resource was temporarily moved, and this is not the case (the resource is still /cars, you just need to authenticate first).
So, what is the correct way to do this procedure in a "true" rest api?
I 100% agree, and that's why I proposed this standard:
https://datatracker.ietf.org/doc/html/draft-pot-authentication-link-01
The idea is that for cases like this, you should be able to return a Link header with an authentication rel, so the client can discover how to proceed.

Authorization dependent REST API

as part of a server REST API design I'm considering I'd like to be able to return data that is conditional on the level of authorization of the client. What would be the recommended way of doing accomplishing that and still calling it one API? More specifically, consider the following example for a book access API:
HTTP GET /library/books/{book-name}
Any authenticated client should be able to get (JSON) data for the book, like:
{
"book":
{"book-name":"abc", "author":"someone"}
}
But a specific sub-set of authenticated clients should also be able to get:
{
"book":
{"book-name":"abc", "author":"someone"},
"private-info" :
{"book-status":"on-loan", "price":"$20"}
}
For a given book, any suitably authorized client can also access the "private info" via a direct HTTP GET /library/books/{book-name}/private-info.
Now, assuming a suitable client authentication scheme is in place, I cannot help but think that the HTTP GET /library/books/{book-name} above is actually looking like two API's, distinguished by authorization state on the server regarding authentication. This seems not very RESTful.
Perhaps it would be better to keep the base GET book API the same for all without ever having any "private-info", while offerring authorized clients only access to the private-info URI and returning 403 to all others?
How does this type of conditional data access typically get handled with REST APIs?
There is nothing inherently wrong with your approach - it makes good sense to hide information as you suggest based on the user's authorization. REST says nothing about this - the representation of a resource may depend on user authorization, moon phase or what ever else you can think of.
You can although improve caching if you extract the private information to a separate resource. In this case you would have some rather static content for /library/books/{book-name} which can be cached on the client side. Then you would have /library/books/{book-name}/private-info which would be more volatile and user-dependent - and thus not easily cachable.
Building on this you can include a link to the private information in the original resource:
{
Title: "A book",
Author: "...",
PrivateInfoLink: "http://your-api.com/library/books/{book-name}/private-info"
}
The benefit of this is two-fold:
1) The server can leave out the link if the client does not have access to the private information and thus saving the client from a unnecessary round trip to (not) get the private info.
2) The server is free to change the private-info URL if it needs so later on (it could for instance be different URLs based on the user authorization).
If you want to read more about the benefits of hypermedia then try this: http://soabits.blogspot.dk/2013/12/selling-benefits-of-hypermedia.html
I recently answered a similar question. You can find my answer here.
The bottom line is: You should try to separate business logic from authorization logic always. This means you want to externalize your authorization. There are several ways of doing that.
In your particular case, imagine the list of sensitive fields that only a subset of clients can view changes over time, that would potentially require a rewrite of your API. If you decouple authorization logic from your business logic (API) then you can easily update authorization logic without having to rewrite any code. This is called externalized authorization management (see this great Gartner paper on the topic).
As part of my day-to-day job, I help clients secure APIs and web services using XACML. The best practice is always to keep concerns separate.

Is this a correct implementation of REST?

Im steadily building the resources of my API, however after much research on the correct ways to build a RESTful API, I have been unable to find an example of how 'complex' requests should be received.
For example, as part of the login process (which is little more than an authentication key update), the following URI is dispatched by the client:
/api/auth/login
There are no values on the URI, the resource is /auth/ and the command being triggered is /login/. The actual login details are sent to the server Authorization header.
Now, what prompted me to ask this question is as I was writing a command to allow the client to get a reminder of how long the key is valid for, I was immediately drawn to getkeyexpiration or something similar as a command name.
Suddenly I felt that this doesn't sound like what I read about in the 6 constraints, this feels more like operation calls.
So, based on the above examples, is this still a RESTful API? I am concerned as I cannot think of a way to perform this by simply using URI resource names and appended values.
Thank you
EDIT:
From reading this: http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
I am starting to understand that by naming resources and only resources with noun words, the context of how the server will operate becomes a lot clearer.
Regarding my above example:
/api/auth/login
I have used auth as a prefix of login, because that is the context of the resource. I am designing my system to be extendible and require a way to categorize resources on the URI level. Is there a standard way of doing this?
Your RESTful resources should be nouns, because HTTP provides the verbs.
I would suggest something like this instead:
/api/key
Which you can then POST to (with HTTP Authorization headers included) create a new key, returning something like this:
/api/key/1234ABCDBLAHBLAH
This is a key specific to your session, which you can then GET to retrieve details about it such as expiration time, etc. You will have to pass that key with each subsequent request, of course.
If the key stuff sounds clunky when discussed in the context of a RESTful API, it's because it usually is. Sessions are human/browser concepts, but RESTful APIs are application/integration concepts.
Since servers don't "log on" to other servers, this begs the question: if you're already OK with requiring the caller to pass an Auth header to your login API, why not just require it be passed for each API call, and forget the notion of keys altogether?

RESTful HTTP: Showing different representations to two users on the same URI

I'm designing a hypermedia API, yes, a RESTful API, with the hypertext constraint.
Each user of the system will access the system using their own credentials, so every request we process is authenticated and authorized. Each user will typically have specific credentials so that they may have different permissione (e.g. none, read, read/write) on each collection.
We want the client to be primed with the one URI that it starts with, which would be perhaps an atom services document, or a hierarchy (draft atom hierarchy extensions) of atom collections.
My question is basically should users see different representations for the same URI, or should users be directed to different URIs based on their permissions?
For example: User A and User B have different permissions in the system. They log in with different credentials, to the same start URI. A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same URI
302 (or other redirect) each user to e.g. /endpoint/userA (which they own)
The tradeoff between cacheability is of course minimal, since resources are cached only by the client and not by intermediaries, but there's a tradeoff for visibility too (URI contains (aythenticated) user ID). Finally there's the future possibility of allowing User A (or a super user) to see what User B sees.
I'm not asking what Twitter or Facebook do, I'm more interested in what REST practicioners have to say about this.
My question is basically should users see different representations
for the same URI, or should users be directed to different URIs based
on their permissions?
For example: User A and User B have different permissions in the
system. They log in with different credentials, to the same start URI.
A successful response may be one of the following 2:
200 OK, and User A sees something different than user B on the same
URI
302 (or other redirect) each user to e.g. /endpoint/userA (which
they own)
Both ways are RESTful. The representation of a resource can depend on the permissions. The communication is stateless because you send the credentials (username, password) with http auth by every request. Redirection to another representation variant after permission check is a great idea. That way you can completely separate the authorization logic from the resource representation logic, so you can move it even to another server and you can create very well cacheable resource representations. For example by GET /endpoint/userA you can redirect userA to /endpoint/userA?owner=true, because she is the owner of the profile, or you can create a composition of features: /endpoint/userA?feature1=true&feature2=false etc... It is very easy to setup fine grained access control for that. Another way to stay cacheable if you append the user id to every request's queryString, but this solution with redirection is much cleaner. Thank you for that!
Personally I find this a really tough call to make and I think it depends a lot how much content would change. If the difference is the omission of a few extra details then I would probably treat it as a single resource that varies based on the user.
However, once the differences start to get more significant then I would look at creating different resources. I would still try and avoid creating resources that are specific to a particular user. Maybe for a particular resource you could create a set of subresources, with differing levels of content. e.g.
/Customer/123?accesslevel=low
/Customer/123?accesslevel=medium
/Customer/123?accesslevel=high
This method in combination with the 302 may be sufficient in some cases. For more complex cases you could use multiple query string parameters.
/Employee/123?SocialSecurityNo=yes&SalaryInfo=yes
I do not believe there is an easy answer to this question. I think the answer is similar to most tricky REST scenarios: your solution can be as creative as you want as long as you don't violate the constraints :-)
Option 1, replying with 200 is an acceptable REST response and is more user friendly than option 2.
The Google Data APIs provide a decent REST implementation on top of their user services, and they implement option 1. For example the Google Calendar Data API allows a user to query the person's own feed by performing a HTTP GET request on http://www.google.com/calendar/feeds/default/private/full.