API Design; action endpoints - rest

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.

Related

Rest endpoint authentication response

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.

REST : Correct HTTP verb to check a password

I read many posts about passing sensible data in a GET request but didn't find an answer that would suit my needs.
I have to expose a RESTful resource that will check the password strength.
GET http://api.domain.com/security/password/P#55w0rd
I find the GET HTTP verb suitable since I only want if the password is secure enough.
The problem is that the client will be forced to pass it in the resource (i.e. URL).
Some colleagues told me to use POST and then pass it in the data body but I'm not sure how RESTful is it.
The REST standard just says to use HTTP Verbs. It doesn't actually mandate that you use particular ones. However some conventions have arisen about which verb to use, POST to create & GET to retrieve data, however this should not be followed religiously if it will cause an issue.
As per the following article you should not use GET for password, and yes you can use POST or pass something in the HTTP headers instead.
REST Security Cheat Sheet
Session management
RESTful web services should use session-based authentication, either by establishing a session token via a POST or by using an API key as a POST body argument or as a cookie. Usernames, passwords, session tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.
I went with this:
GET /api/public/check-password
Authorization: Basic <base64(test:<password>)>
The username must literally be either '' (empty string) or 'test'.
I chose to use
test because it's obviously not a real user
GET because no modifications are made
The Authorization header because the security middleware in (most?) application stacks already removes that from logging - so no special care is needed.
/api/public because it doesn't require authentication to do the check
I'm not in love with check-password - that sounds more RPC-ish than REST-ish... but what can you do? At least it's obvious. I'm open to other suggestions.

API Key in path

We have some IoT sensors that POST json payloads to an endpoint. They are configured with only a HTTPS URL to send to, no ability to setup authentication etc.
We need basic ability to see which sensor is sending data, and loosely prevent anyone from sending payloads. Full authentication will not be possible.
It was suggested we could put a token in the path and use it as a super basic API Key. I was wondering what the best format for the route should be...
/api/events/_ingest/api-key
/api/producer/api-key/events/_ingest
I was wondering what the best format for the route should be: /api/events/_ingest/api-key or /api/producer/api-key/events/_ingest
There's no best approach here, both are really bad. The API key does not belong to the URL. It should be sent in the standard Authorization HTTP header.
Once you mentioned in the comments that it will be something temporary, you could try a query parameter. It's still bad though. But you will be able to reuse this same route later, just moving the API key to a HTTP header, when your clients support it:
/api/events/_ingest?api-key=somecoolhashgoeshere

How to pass filter arguments to GET requests in REST APIs?

I'm building a RESTful webservice:
Under GET /clients, I'm getting the list of all known clients.
Under GET /clients/1, I'm getting the client object for the clientId 1.
Everything as it should be.
Those clients have a property called authorized. On my web UI to manage those, I have separated tables for authorized and unauthorized clients. Of course, I do not want to load all the clients from the server just to display the unauthorized ones.
The question is, how could I filter the client over a RESTful URL? As I want to do a proper RESTful API, query parameters are not an option.
I already thought about additionally doing GET /unauthorizedClients and GET /authorizedClients but this seems not right, as I still would use DELETE/clients/%clientId%` to remove one client.
I couldn't think of a pleasing approach for this problem. Any tips on how this could be solved are welcome.
I'm just wondering what prevents you from using query parameters. They are the most appropriate way to filter a collection of resources in REST APIs. Using query parameters won't make your API less RESTful.
You could have the following:
Authorized: GET /clients?status=authorized
Unauthorized: GET /clients?status=unauthorized
Another option is:
Authorized: GET /clients/authorized
Unauthorized: GET /clients/unauthorized
You really should consider query parameters though.
I would go with /clients/unauthorized and /clients/authorized. You need to taylor resource URIs like directories.
This way, there's nothing wrong with deleting clients against the /client/[id] resource.

How to secure Rest Based API?

We intend to develop rest based api. I explored the topic but it seems, you can secure api when your client is an app (So there are many ways, public key - private key etc). What about websites / mobile website, if we are accessing rest based api in website which do not use any login for accessing contents ( login would be optional ) then how could we restrict other people from accessing rest based api ?
Does it make sense using Oauth2.0 ? I don't have clear idea of that.
More clear question could be ,How can we secure get or post request exposed over web for the website which doesn't use any login ?
If it's simple get request or post request , which will return you json data on specific input, now i have mobile website , who will access those data using get request or post request to fetch data. Well, some else can also access it , problem is i am not using Login, user can access data directly. But how can we restrict other people from accessing that data.
What do you think is the difference between securing a website that is not using REST vs one that is using REST API?
OAuth provides authorisation capabilities for your site, in a REST architecture this means a user of the mobile application will have to provide their credentials before being allowed to access the resource. The application can then decide on if that user has access to the requested resource. However you've said your website doesn't need use authorisation.
You can use certificates however good luck managing the certificate for each client. My take on it is for your explanation you don't need to secure your website because you will never be able to manage a trust relationship between the client and the server. There are some options though:
You build your own client application that you ship out to people which can verify itself with the server using a packaged certificate with the client. E.g. iOS has this kind of feature if you build for that device.
You provide a capability to download a certificate that is 'installed' in the browser and used when communicating to your REST API
Use something like a handshaking protocol so when a client wants to make the first request it says; 'hi I'm a client can we chat?' And the server responds with 'yes for the next X minutes we can however make sure you send me this key everytime you tell me something YYYYYY' (you can use something like SecureUDID or equivalent for other devices than iOS).
There are probably others but you get the basic idea. Again in my opinion if your resource doesn't need authorisation then you don't need to secure that REST API. Can I ask what kind of data are you exposing via this REST API or functionality your providing? That might help provide a better answer.
You want authorization: only some agents (mobile clients) and/or users should be allowed to access those APIs.
To solve that problem, you need identification: a way for the server to tell who is who (or what), so the right decision can be made.
There are many different way to provide some form of identification, depending how much you care about security.
The simplest is a user agent string, specific to your mobile clients. But it can be faked easily. Slightly harder to fake are client based 'secrets' - embed some kind of secret or key in your mobile client code. You can make it really complicated and secret, but as ramsinb pointed out, you can't get security this way as it would require you to be able to guarantee that the secret you're shipping with the client (wether it's code, algorithm or any other fancy construct) can't be compromised or reverse engineered. Not happening when you don't control the client.
From there, 3 choices:
Security isn't really required, don't bother
Security isn't really required, but you still want to limit access to your API to either legit users/agents or people ready to invest some time hacking your protection - go with a specific user agent or a client embedded secret - don't invest much into it as it won't block people who really want access to get it anyway
Security IS required - and then I don't think there is a way around authentication, wether it's login/password, user specific (device specific?) keys, OpenID, etc... No matter what, you'll have to add to the user burden to some extent, although you can limit that burden by allowing authentication to persist (cookies, storage....)