If you know anything about CORS, you know it is a methodology for securing calls from frontend components and applications to your API backend. You do this by defining a predetermined 'whitelist' of
allowedOrigins which have access to the backend API. Like so:
allowedOrigins: ['http://localhost','http://localhost:8080','http://127.0.0.1']
But I realized the other day that this is completely broken.
FOR EXAMPLE:
Lets say for instance I run a distributed network across Hospitals but I also integrate with clinics.
My API backend has to allow for
external and internal allowedorigins per endpoint; for example, I may want to limit origins to only the external API endpoints but not internal API administrative endpoints and I don't want to have to create two separate applications for the SAME DATA.
Do CORS configurations allow for this? NO.
You apply one set of rules to ALL endpoints for ALL origins. You can't really create rules per endpoint.
BUT you can... it's just people DON'T.
But they should because it is more secure. Right now, it may be only security through obscurity but someone clever like me could figure it out in two seconds and then I have access to mine all the data on your backend.
This was one of the ways that people mined the data at Facebook apparently; their IP/domain was added to allowed origins as part of the developer program add they a server on the network where they could still call and request the data because the CORS data was just doing basic allows (and did not block their origin per endpoint) and that server allowed those calls as part of their role.
The CORS rules do not apply to the architecture as a whole... they apply to the endpoints.
You are created 'allowedOrigin' rules for your endpoints. So why are you not associating them these origins with endpoints? I guess most people don't question, they only implement.
So today I was addressing architectural pieces and hit this and this was how I address it.
SOLUTION:
In Beapi's beapi_api.yml file, you will find the following:
corsInterceptor:
includeEnvironments: ['development','test','production']
excludeEnvironments: []
allowedOrigins: ['http://localhost','http://localhost:8080','http://127.0.0.1']
What we do instead is turn the allowedOrigins variable into a MAP wherein we list all the controllerNames with the associated origins next to them AND a 'default' catchall in case the controllerName (which exists) doesn't have any allowedOrigins for it.
It would look something like this:
corsInterceptor:
includeEnvironments: ['development','test','production']
excludeEnvironments: []
allowedOrigins:
person:['http://localhost','http://localhost:8080','http://127.0.0.1'']
hook:['http://localhost','http://localhost:8080','http://127.0.0.1',']
personRole:['http://localhost','http://localhost:8080','http://127.0.0.1']
role:['http://localhost','http://localhost:8080','http://127.0.0.1']
default:['http://localhost','http://localhost:8080','http://127.0.0.1']
This would allow us to check the allowedOrigins per URI with no additional processing and minor amount of redundancy in our config.
This adds tremendous value in distributed architectures and much needed security.