1

I have an existing endpoint, for example https://api.example.com/ ... I have an existing CORS policy enabled which only allows access from origin example.com.

However, when I visit the endpoint URL directly (ie. https://api.example.com/api/login in my browser, I am able to access the API endpoints directly from there.

Is there a way or best practice to make your API inaccessible from the api.example.com subdomain directly and only accessible from example.com?

I understand they are of the same origin ... in this case, example.com but is there anything I can do?

I have some functions which are supposed to be anonymously accessible, the rest require a JWT token. I'd like to protect these anonymous endpoints so they can only be accessed from my own example.com servers.

Would appreciate any feedback as I'm convinced I'm really missing something obvious.

  • I'm afraid you have some misunderstandings about how browsers and the internet work. I don't have time right this moment for a detailed answer, but the short of it is "no, what you want to do is impossible. You cannot secure your endpoints like that" – Conor Mancone Jun 19 '19 at 1:13
  • Is it the basic idea that you cannot secure your endpoint against itself? Otherwise it won't run at all? – 24x7 Jun 19 '19 at 1:16
  • No. The issue is that anyone can use any HTTP client to make arbitrary requests to your servers and even pretend to be a browser on your main site. All aspects of an HTTP request can be spoofed by the client, and the client doesn't have to be a browser. HTTP simply wasn't designed to allow the server to verify the identity of the client. – Conor Mancone Jun 19 '19 at 1:28
0

Unfortunately what you are trying to do is effectively impossible because HTTP simply was not intended for this use case. I think there are a few misunderstandings that are confusing the issue for you. Running through things:

  1. There is nothing special about browsers. Browsers are just a fancy HTTP client that can send HTTP requests to an HTTP server. However, they are not the only HTTP clients that can send requests to a server. If you have ever made HTTP requests from your own server, you are already aware of this. Similarly tools like postman, curl, etc, are also HTTP clients and can make HTTP requests to your server, except they are not "running" on a domain anywhere.
  2. In fact the whole question of "what domain is making this request?" is a concept that doesn't exist in HTTP. It's easy to misunderstand this fact because of how CORS works, but CORS is something that is baked into browsers - not HTTP. CORS is only meant to protect HTTP requests made by javascript on a webpage inside a browser (again, it's not strictly part of HTTP). As a result if you put up a completely restrictive CORS policy banning access from everywhere except your main domain, that CORS policy would do absolutely nothing if someone visited your API endpoint from literally any other HTTP client - which is what you just discovered. Anyone using postman, curl, etc would still be able to access your API endpoints without issue, regardless of what CORS says, because CORS only matters for browsers.
  3. Blocking by domain is impossible because HTTP doesn't know anything about domains. When a client makes an HTTP request it first uses a DNS service (if needed) to convert the domain name of the destination into an IP address. The client then sends its HTTP request to that IP address. The only thing the server knows is the IP address of the client. All other information is provided by the client and can therefore be easily spoofed by an attacker. I say this because while some browsers may attach information to the HTTP request stating what domain the javascript that made the request is running on, a non-browser client can easily do the same and lie, claiming to be javascript running on your domain.

In short the only thing the server knows is the IP address of the client (technically that can be spoofed to, but it is substantially more difficult). All other information about the request is provided by the client and therefore cannot be trusted for security purposes.

It may help to brush up on the basics of HTTP. The details in that link break things down well. The link also happens to focus on browsers as the HTTP client, which we know is not exclusively true. Ironically articles like that one are why misconceptions like yours are common :) Still, with a proper understanding that HTTP clients can be anything, that link should be helpful.

This doesn't answer how to secure your endpoints. I can't give you an answer there without more details, which would basically make this a new question (aka you'd be better off asking a new question than editing this one, I think). In general there are lots of strategies, but the short of it is that you can't have an anonymous endpoint and also selectively block users, except by IP address (which isn't possible for endpoints that are supposed to be accessed from a browser). As a result there is only one general answer: you need to put some kind of authentication on the endpoint, even if it doesn't specifically require a login.

  • 1
    thank you for making the time and sharing your detailed response, I'll look into adding an authentication method on my endpoint – 24x7 Jun 19 '19 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.