API Security : ROLES (RBAC/ABAC) Part 2
I write ALOT on securing your API’s… mainly because I see so many mistakes that could be avoided. One of the BIGGEST is lack of RBAC/ABAC controls. Allow me to explain…
What is RBAC/ABAC?
Role Based Access Control (RBAC) allows for assigning ROLES to endpoint thus requiring a client connection to have said ROLE in the JWT principal in order to access the endpoint.
- http://localhost/user (GET) could be accessed by an ADMIN or USER ROLE
What is ABAC?
Attribute Based Access Control (ABAC) is the declaration of the parameters to be sent/returned for ROLE based endpoint request.
- ADMIN ROLE may access http://localhost/user (GET) by passing an ID and send back the entire database object
- USER ROLE may access http://localhost/user (GET) with NO ID (it grabs the ID from principal in JWT) and send back a PARTIAL DATASET of the User Object.
What Does This Look Like?
There is a great example of this in the Springboot BeAPI starter :
As you see, for each endpoint we add the RBAC/ABAC config options under REQUEST/RESPONSE for each endpoint .
How Does It Work?
We start by declaring all the ROLES as part of a NETWORK_GROUP in our application properties:
security:
networkRoles: {'open':['ROLE_ADMIN','ROLE_ANONYMOUS','ROLE_USER'],'public':['ROLE_ADMIN','ROLE_USER'],'private':['ROLE_ADMIN']}
… and then assign that group of ROLES to each set of endpoint declarations at the top of the file:
"NETWORKGRP": "public",
Each of these documents is loaded at RUNTIME into a cache so that we can check the ROLES from the JWT token to determine if client has access and use what parameters should be being sent/returned
In the example above, we have two declarations for ‘http://localhost/user (GET)’ :
- permitALL : This is used to say all ROLES in NETWORK_GRP (not separately declared like ‘ROLE ADMIN’ below) can call the endpoint with these parameters. If left blank, you send NOTHING.
- ROLE_ADMIN : This is a declaration specific to the ADMIN ROLE stated what should be sent/returned. It is important to note that the datasets CONCATENATE with permitAll.
So as you can see, if USER is in the network_grp, they do not send an ID (as we can grab their identifying information from the JWT)… BUT ROLE_ADMIN is required to send an ‘id’ parameter (as an ADMIN can lookup whoever they want in the system).
And while USER gets a limited dataset, ROLE_ADMIN gets everything sent to ‘permitAll’ as well as it’s own declaration.
Why Use It?
The OWASP API top 10 have several issues that are directly addressed by RBAC/ABAC security:
So as you can see, this is an essential security measure for your API’s.
So Why Don’t People Do This?
For one, too many developers rely on Gateway tools for security of which:
- some do not have this functionality
- some have partial functionality
- NONE integrate with your application
Many (including myself) have tried to address this issue in the community but people like OpenAPI lead , Darrel Miller, have deliberately blocked including this in the schema:
Conclusion
To properly implement RBAC/ABAC, one has to declare their own separate IO State file and enforcing the rules internally via a filter/interceptor.
One can even assign a DEFAULT Role (ROLE_ANONYMOUS) when users access the PUBLIC site to differentiate between logged in users and non-logged-in users.
In general, adding RBAC/ABAC functionality to your site just provides for a far more secure API in general and creates a better overall API application.
For more on this, check out API’s Explained on Amazon.