Simply send a key in HTTP header to authenticate for a REST call? - rest

I have some REST services on my site that will be available for 3rd parties to access.
My plan is simple. In order to call on these services, they need to request a key from me. I will privately supply them with a GUID. Each call to any of my services will, via a filter, check the header for the key and accept/reject the request accordingly.
This site is all HTTPS so the key would be encrypted during transit. I'm not worried about the key being visually identifiable to authorized clients. In other words, I'm not worried about any kind of 'inside' attacks or people sharing the key. I just don't want random, unauthorized outside users.
I have looked around and I don't really see anybody doing it exactly this way. I feel like I'm over-simplifying... but on the other hand, I don't see what's wrong with it either.
My question is.. does this sound secure enough (from a basic/minimal perspective) or does it expose some gaping security hole that I'm not seeing?
FWIW - I am using the Spring Framework, including Spring Security 4.
Thanks!

If it's HTTPS and the API key is in the header encrypted during transit as you described etc, then it follows a pretty standard design authentication pattern.
Your security now depends on how you distribute and store your API keys.
Although, you could use an "Application Identifier and Key pairs" approach.
Whereas the API Key Pattern combines the identity of the application
and the secret usage token in one token, this pattern separates the
two. Each application using the API issues an immutable initial
identifier known as the Application ID (App ID). The App ID is
constant and may or may not be secret. In addition each application
may have 1-n Application Keys (App_Keys). Each Key is associated
directly with the App_ID and should be treated as secret.
Just in case you wish to extend the application in the future.

Related

How to design RESTful API URI when you can't have user ID on the URI

Make-up scenario:
Let's say I am building a RESTful Web API backend for managing the payment plans for members:
It's for members so you would have to register with us. Each member would have a member ID internally.
There are various payment plans: 0% interest for 6 months, 0% interest for 12 months, etc. Each payment plan would have an ID internally.
The relationship between member and payment plan is many-to-many.
Each member also would have 1 active plan at a time. You can change it, but there is only 1 active plan allowed for a member.
Now if I want to design an API endpoint to return the information about the member active payment plan, I would normally do something like:
/members/{member-id}/plans/active
I understand that it might be a bad idea to put state on the URI (I had a separate question for that matter), but please bear with me.
Now here is the tricky part: the company's policy states that I can't have the member ID in the URI. They will have some kind of tokens in HTTP header, which is required in order to access the RESTful API endpoints, that contains the member ID.
My API application, which is ASP.NET Core Web API by the way, has no problem creating a filter to parse that token and transform it into member ID, in the code. It's just that my API URIs can't have the member ID anymore.
How would you design the URI in this case?
Without the member ID on the URI, mine would look like
/plans/active
And the data now would be all driven/filtered by that member ID, securely inside the API backend. Is this normal?
the data now would be all driven/filtered by that member ID, securely inside the API backend. Is this normal?
It sounds to me as though things are going sideways; as though people don't understand REST, or that people don't understand that what they are trying to achieve isn't a good fit for REST.
In order to obtain a uniform interface, multiple architectural constraints are needed to guide the behavior of components. REST is defined by four interface constraints: identification of resources.... -- Fielding, 2000
REST uses a resource identifier to identify the particular resource involved in an interaction between components. REST connectors provide a generic interface for accessing and manipulating the value set of a resource, regardless of how the membership function is defined or the type of software that is handling the request. The naming authority that assigned the resource identifier, making it possible to reference the resource, is responsible for maintaining the semantic validity of the mapping over time (i.e., ensuring that the membership function does not change). -- Fielding, 2000
The web works on the shared understanding that uniform resource identifiers identify resources. The URI is the key of the key/value store. When you start moving identifying information into other parts of the request, then you are opting out of the "uniform interface" that is shared by everyone else. This puts interop at risk.
On the other hand, much of the web also assumes that identifiers are published, and there isn't in general a lot of discipline to restrict the copying of them. So you certainly don't want secrets and/or sensitive information included.
The answer in REST is to use another layer of indirection. The rule is that we should be using a URI, and each identifier should map to one resource. But there's no rule that says that the spelling of the URI must match the semantics of the resource.
In other words: URL shorteners work!
GET /99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1
As far as REST is concerned, that's a perfectly valid request, with an entirely satisfactory identifier. As long as your server understands how to find the secrets using that key, then that's fine.
Of course, you could add semantic information to the URI that isn't sensitive, to help the humans orient to the context
GET /members/99bfb1e3-89a4-4a44-a6d7-0e70c209f447/plans/active HTTP/1.1
GET /members/plans/active/99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1
GET /members/plans/active?99bfb1e3-89a4-4a44-a6d7-0e70c209f447 HTTP/1.1
These are all also fine (again, assuming that you can use the information provided to discover the sensitive information you need to produce/modify the corresponding resource).
On the other hand, if your organization's concerns are related to leaking the identifier itself... then somebody with seniority should really be challenging the assumption that REST/HTTP is the right answer to the problem.
As your deviate further from the "standard" for HTTP messages, you increase the risk that some general purpose component isn't going to understand what is going on, and if that results in significant loss of property, your lawyers aren't going to be happy.
In my opinion this is pretty normal. This is usually the case when you are using a JWT token for authentication for example. The token not only authenticates the user but also contains relevant information about it.
In these cases, you will also see APIs with that kind of endpoints without any information about the user (like an ID or something) explicitly in the path.
Just a suggestion or a point of view from my side, I would actually keep the members part in the path: /members/plans/active.

REST API Best Practice For Accessing Self/Own Objects

Say I'm creating a journaling application and I want users to be able to post entries to their journals.
I do not intend to ever allow a user (even a moderator) to post an entry in someone else's journal.
That said, are there any arguments for exposing the account or journal id in my endpoint path?
I would think that POST api/journals/postEntry would be sufficient as I can determine the user via access token or JWT token.
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Short answer: it's a violation of the uniform interface constraint.
See Fielding, 2000.
What you are doing, in effect, is creating this little corner of the world where, instead of using the target-uri to identify a resource, you are instead using target-uri + token.
Which means that your thing doesn't use the semantics that the general purpose components in the world are expecting.
For example, when I copy the URI out of my user agent, and share it with someone else, that other person doesn't get the result I expect -- they end up looking at their view, not mine.
The fact that we can stick a URI in an email message and have it just work for the person reading the email is a really big piece in the adoption story.
Furthermore, the cache constraint in REST rather depends on being able to use the identifier as the primary cache key. So your bespoke identity mechanism has the potential to mess up caching.
IN PRACTICE: you are using HTTP, and HTTP has caching rules that prohibit sharing authenticated requests. So the caching issues mentioned above are purely theoretical.
Alternatives you might consider
You could arrange for /api/journals/postEntry to redirect to /api/journals/{userJournalId}/postEntry
You could use the Content-Location header to indicate that there is a more specific identifier for the current representation.
You can use the canonical link relation to help clients navigate to the preferred resource from the alternatives.

Node - request authentication using secret

Lets assume i have REST api with products and i want it to be accessible only for specified users.
The list of users is known for me and i'm looking for some way to give them safe access to my API.
I don't want to create authentication with username and password, generate token and this stuff.
What i can imagine is that i'm giving each of my users some secret string
and they use it in every request.
And what i need is some example/tutorial/name of this kind of solution,
i'm sure there are some standards for that but i don't know it.
I know it's kind of nooby question - sorry for that, i'm just asking ;).
Thanks in advance!!
You are looking for a simple shared-secret authentication. A simple solution in this case is just to check for the secret as a param (or it could be in the request header). For example, the client can call:
https://example.com/valuable-stuff?secret=2Hard2Gue$$
You implement this in your web request handler as:
SECRET = '2Hard2Gue$$'
function showValuableStuff() {
if (params['secret'] != SECRET)
return NotFounderError;
// now retrieve and output the resource
}
Some practical considerations are:
Use a secure connection for this to prevent the secret being leaked (ie a secure HTTPS exposure).
Be careful where you store the source code if you're hard-coding it. A fancier solution is use an environment variable which is set on the server, so you keep this out of the source code. Or at least to encrypt the part of the source that contains the secret.
While this is fine for simple solutions, it violates the basic security principle of accountability because you are sharing the secret with multiple people. You might want to consider allocating each individual their own random string, in which case, you may as well use HTTP Basic Authentication as it's well supported by Apache and other web servers, and still quite a lightweight approach.

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.

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....)