Rest endpoint authentication response - rest

If I have a RESTful endpoint for authentication such as
Www.example.com/login
Does it make sense to return more than user info. For example can I return
Username, email, peers AND also return a list of loans or other business specific data which also returned from another endpoint.
Or should I make another http request to
Example.com/dataEndpoint

Not enough information to provide a valid answer, so here's a high level attempt at one...
Are you trying to implement one of the authentication standards (OAUTH, SAML, Any one of the certificate based ones), or something custom?
If you are trying to implement a standard, then you need to follow that standard for the login/authentication endpoints.
If you are writing your own custom protocol, then its up to you but I'd recommend you not overload any endpoint with too many different responsibilities as it will become harder to maintain over time.

Related

API Design; action endpoints

Let's say I have a devices which will connect to a server and register/transfer data through an API.
I understand that you would have things like:
GET: api/devices
GET: api/devices/:id
POST api/devices
DELETE: api/devices/:id
Those are examples of typical CRUD endpoints.
But where would I add endpoints for checking if this device is allowed to connect with it's factory ID?
I was thinking of always passing a post field with an API key in the form of a device ID, but that would mess with the HTTP verbs.
So I think the best way is to add a parameter like this:
GET: api/devices/:id?id=something
But that would become redundant with this endpoint.
So the question is; how would I successfully identify my own devices?
It sounds like you're simply looking for a way to do authentication. Take a look at the Authorization header and the various authentication schemes for it. If existing authentication schemes don't fit your needs, you can also extend it with your own. Common ones are Basic, Digest and Bearer. An example of a vendor-extension is AWS.

Is it legal to have REST resource such as /currentUser in terms of RESTful and stateless?

In terms of RESTful and stateless it's pretty legal to have resource like
/users/123
But, the question is: is it legal to have resource that omits user id and assumes that it's implicitly resolved on the server from the user session? For example:
/loggedUser
That resource would point to /users/123 when user with identifier 123 is authorized.
Picking a resource locator
Using /me, /users/me, /users/myself, /users/current or similar URIs to identify a resource that corresponds to the authenticated user is perfectly fine from a REST perspective. According to Roy Thomas Fielding's dissertation, any information that can be named can be a resource:
5.2.1.1 Resources and Resource Identifiers
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. [...]
When using the URIs mentioned above, you have an identifier for the authenticated user and it will always identify the concept of an authenticated user, regardless of which user is authenticated.
The stateless constraint
The stateless constraint is not related to how your resources are identified. The stateless constraint is about not storing any session state on server side. In this approach, each request from client to server must contain all the necessary information to be understood by the server.
See que following quote from Fielding's dissertation:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
When targeting protected resources that require authentication, for example, every request must contain all necessary data to be properly authenticated/authorized.
A similar question has been answered here and here.
It is OK as long as you use only the data from request (HTTP Headers in your case). In other words, this may work only for users that pass authentication.
Yes.
It is very common for ReST services to make assumption about authorization context.
Though making such a decision will limit usability of that route for users other than the logged on user. For example an admin might need to use that service for a specific user.
A ReST endpoint may even use Claims that exist in the Authorization context. for example return different data for a user that has logged in using certain mechanism.
of all HTTP headers, there are some that are probably not good to be used to tailor the ReST response. for example I will not use the 'referer'.
Make sure you check for any caching strategy you may have before making such design decisions.
It is perfectly legal as long as you keep it stateless. That is, you infer the current user from a security context provided with the HTTP request, usually a token of some kind.
For example, you perform a GET /current-user with an Authentication header containing a JWT token. The server can get most of the user info of the current user from the JWT token and complete with data from the database and retrieve it back to the caller.
I'd also recommend not to use camel case in URIs. It can be a nightmare for devs and some servers are case insensitive.
Beware, if you are holding a server user session, as you imply in your question, your API is already stateful.
As #n00b says, REST isn't a formal standard - and that's probably a good thing.
The original definition comes from Roy Fielding's dissertation. - so if you're doing the things Roy recommends, your design is RESTful. There are a few other things people have added to that - for instance, the Richardson Maturity Model is pretty commonly accepted. There are a few public "standards" documents on the web, e.g. Microsoft's version. I don't think they address this question directly, though.
So, it's up to you - but for what it's worth...
I believe APIs should be consistent and predictable. If I am asking for information about a user, I don't really like that there are two ways of doing it - one by ID, and one using a magic identifier for the current user. I also don't like the idea of introducing the concept of state into the API - by saying "there's an conceptual entity in your API called current user", you are introducing the concept of statefulness, even if you use HTTP headers to manage that.
So, if your RESTful API is designed for use by client application, I think it's reasonable to ask that client to manage state, and carry around the ID for the current user. This also makes your GET requests consistently cacheable - you can theoretically cache /users/123, but you cannot cache /loggedUser.
I believe there is a logical difference with your authentication and authorization action (I've logged in, proven who I am, and therefore got access to specific resources on the system), versus "I am user 123".
The reason you might disagree with this is that it makes your API harder to discover by human beings - someone who is trying to figure out how to get information about the current user has to log in, and then remember their user ID.

Is returning different output based on authentication credentials RESTful?

I have a REST API which allows the developer to fetch a certain resource:
/api/projects
/api/project/4
...
The API requires authentication. The authentication token is added to the HTTP headers.
Is it RESTful to return a different output based on which user is authenticated?
Thanks!
REST doesn't define anything in that respect.
You should keep authentication logic and authorization logic independent of your RESTful architecture.
There are indeed requirements whereby you want to change what is returned based on different attributes / parameters e.g.:
authentication type
time of day
user location
device type...
You would achieve that by using a filter in front of your REST service. Filters / interceptors are explained here.
You would then send an authorization request to a decision point that determines what can be returned based on the identity (or other attributes) of the user.
For instance you could have a logic to return projects to a user if and only if they belong to the same region. The REST endpoint would still be /api/projects but the content returned would differ based on the authZ logic. Have a look at XACML and ALFA to implement that layer.
HTH

Client Facing REST API Authentication

I have seen many different posts regarding different solutions for authenticating a RESTful API and I have some questions, given this current scenario.
I've built a REST API that will allow clients of my software service (we are a B2B company) to access resources programmatically. Now that I've got the API working properly, I'd like to secure it in the most standardized way possible. I need to allow access to certain resources based on the caller of the API. That is to say, not all users of the API can access all resources.
I have URLS available in the following formats:
https://mydomain/api/students
https://mydomain/api/students/s123
https://mydomain/api/students/s123/classes
https://mydomain/api/students/s123/classes/c456
So far I've come up with these possible solutions:
Provide a unique key to each client that they can use to ultimately generate an encrypted token that will be passed as a GET parameter at the end of each REST call to (re)-authenticate every single request. Is this approach too expensive
https://mydomain.com/api/students/s123?token=abc123
Provide a value in the HTTP Authorization Header as seen here. Is this almost the same as #1? (Except I can't paste a URL into the browser) Do people use these headers anymore?
Use OAuth 2 (which I'm still a bit unclear on). Does OAuth 2 actually authenticate the client as a logged in user? And doesn't that go against the spirit of a REST API being stateless? I was hoping OAuth was the proper solution for me (since it's a public standard), but after reading up on it a little bit, I'm not so sure. Is it overkill and/or improper for REST API calls?
My goal is to provide an API that will not have to be changed for each client that wants to consume the API, but rather that I can provide a standard documentation made available to all of our clients.
I'll be happy to post additional details if I've been unclear.
There are 2 type of clients you probably want to prepare your API:
trusted clients - Which are written by you. They can have the username and password of the actual user, and they can send that data to your server with every request, possibly in a HTTP auth header. All you need is an encrypted connection by them.
3rd party clients - Which are written by some random developer. You can register them in your service and add a unique API key to each of them. After that if an user wants to use their services, you have to show her a prompt in which she can allow access to the 3rd party client. After that the 3rd party client will be assigned to the user's account with the given permissions and it will get an user specific access token. So when the client sends its API key and the user specific token along with the request, then it sends the requests in the name of the user.
OAuth can help you to control the second situation.
Your URLs do not have a meaning to the clients. By REST you have to decouple the clients from the URL structure by sending links annotated with semantics (e.g. link relations). So your documentation does not have to contain anything about the URL structure (maybe it can be useful for server side debug, but nothing more). You have to talk about different types of links. By generating these links on server side, you can check the permissions of the actual user (or 3rd party client) and skip the links which she does not have permission to follow.

Why is form based authentication NOT considered RESTful?

Although I "think" I understand it I need some clarity. With PURE Restful authentication, things do get a bit unwieldy and using forms helps a lot with the UI of the application (i.e., get to have separate login page, forgot password links, easier logout? etc.,)
Now Forms come along and some folks say "not restful" - what is "not restful" about them? Is it that there is no corresponding login resource so to speak? Or does it force something else that I'm missing?
Note: If ones create sessions with them, that's a different matter altogether. I'm more keen on know "why" are they branded as restful? Just googling for "Form based authentication vs restful authentication" throws up quite a few hits.
One could use these "forms" to authenticate and pass on tokens for the application to store in cookies etc., which I feel is entirely restful (assuming cryptographic security etc.,)...
There is nothing wrong with sending your credentials, perhaps through a form, for authentication. The problem is most Form based systems rely on sessions, thus requiring you to only log in "once".
Sessions are server state, thus violating the stateless constraint of a REST architecture.
If you have to send the credentials each time, you can either include them in the payload (i.e. using a form), or you can use the HTTP Authorization header.
If you include them in the payload, you can include them in the body, but only for a POST or PUT, and not a GET or DELETE (since they don't have bodies).
If you include them in the URL as part of the query parameters, then the URL is no longer necessarily representing the actual resource. One of the other tenets is that the URL matches the resource. Adding out of band information (such as credentials) within the query parameters muddies that constraint up a bit.
So, for a REST system over HTTP, you're better to use the existing HTTP Authorization mechanism than working out something else. You could also use client specific SSL certs as well, that works fine also.
Excellent question. I think that RESTful purists will likely say that having a URI associated with an action rather than a resource is what makes form-based auth not RESTful, which is something you pointed out yourself.
Honestly I think that the idea of a 100% pure RESTful application is somewhat of a Utopian ideal when it comes to web applications. I believe it is achievable, however, for RESTful web services, since the calling applications can pass credentials with the request header.
At the end of the day, I think that as long as your application works it is fine, and you should not worry about whether or not it is purely RESTful.
That's my $0.02.
From this answer:
To be RESTful, each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP.
It's not that form-based auth is not RESTful — it's not RESTful to have a session at all. The RESTful way is to send credentials with every request. This could easily be eavesdropped upon, however, but HTTPS/SSL/TLS closes that hole.
Form-based authentication does not use the authentication techniques that are built into HTTP (e.g. basic authentication, digest authentication).
REST purists will ask you to use the functionality built into HTTP wherever possible. Even though form-based authentication is extremely common, it is not a part of the official protocol. So the REST purist sees form-based authentication as an instance of "building functionality on top of HTTP when that functionality already exists within HTTP itself."
Now Forms come along and some folks say "not restful" - what is "not restful" about them?
The authentication credentials are not in the standard place.
REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms. -- Fielding, 2008
RFC 7235 describes the Authorization header; that gives us a standard way to distinguish authorized requests (which have the header) from anonymous requests (which don't have the header).
Because we can distinguish authorized and anonymous requests, general purpose components can do interesting things.
For example, if the origin server is restricting access to a resource, we probably don't want a shared cache to be re-using copies of the HTTP response to satisfy other requests. Because the authorization has a standardized form, we can define caching semantics that restrict what a shared cache is allowed to do.
Putting the same information into a cookie header, in effect, hides the authorization semantics from general purpose components.
(This is somewhat analogous to using POST requests for safe requests -- general purpose components can't distinguish semantically safe POST requests from semantically unsafe POST requests, and therefore can't do anything intelligently take advantage of the safe handling).
If we had smarter form processing -- form input controls that copied information into the Authorization header instead of the query string/request-body -- then forms would be fine. But (a) we don't have that and (b) we are unlikely to get it, because backwards compatibility.