Friday, May 10, 2019

Follow up on Cors Issue

So the other day I realized that CORS does not take into consideration Networks; it only limits by connecting domain and as a result networkGroups have to either maintain ALOT of redundacny (and which are bound to have a hole eventually) or they have ZERO SOLUTIONS.

So I started fixing this in the framework.

I now have started to add 'networkGroups' as a configuration setting so depending on whether you have multiple VPNs, networks, etc, you can maintain CORS settings for all and associate endpoints with the networkGroups.

For example, if we define our 'networkGroups' as public & private, we can then associate them in CORS settings like such:


    corsInterceptor:
        includeEnvironments: ['development','test','production']
        excludeEnvironments: []
        networkGroups:
            public: ['http://localhost','http://localhost:8080','http://127.0.0.1','http://test.nosegrind.net']  
            private: ['http://localhost','http://localhost:8080','http://127.0.0.1']  


This is how our allowedOrigins now looks for two separate networkGroups.

Now comes the COOL Part

Then we can associate the network group with the IOState files so that each set of endpoints has a setting of who networkGrp can access it:


    "NAME":"person",
    "NETWORKGRP": "public",
    "VALUES": { ...

This allows us to say 'Person' endpoints are all part of the 'public' networkGrp

Wednesday, May 8, 2019

CORS Issue Affecting THE WORLD

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.