Java webapp API id-based security filter - filter

We're building our API and looking for an organized way to grant users access based on what role and permission they have.
From the starting point, we have 3 roles
Admin: can get and edit everything in his organization
Team Admin: can get and edit only his team info and users' info
User: can get any edit his own information
Entity
Team
User
For Security Filters:
We're using JAX-RS with Security Roles and #RoleAllowed to filter access to resources
Id-based filter by if / then / else function. Example with a team admin access to a user.
function isAllowAccess(teamAdminId, userId) {
allowedUserIdsList = queryfor(teamAdminId);
if (userId in allowedUserIdsList) then ... else BAD_REQUEST
}
This code is growing with the increase complexity of multiple roles and many entities. So my questions:
What will be the best way to have an organized id-based filter, is there reputable library for this?
Should we maintain a separate table containing accessible ids of each
entity for each team_admin_id? Then every row updated or inserted will trigger the update of this table.
Is there a formal or widely acceptable method to reduce database
call overhead in each call just to check if the team_admin is
allowed to access a particular user?

Related

AWS Cognito use custom attribute to map Spring application ROLE instead of cognito:groups

In my application the users are split in 2 macro categories: Customer and Backoffice, every category has a subset of role, for example MANAGER and USER for Customer type and different ones for the Backoffice type.
So a user could be a Customer with a MANAGER role or a Backoffice with, for example, a SALES role.
Every Spring + Cognito guide on web uses cognito:groups to map the Spring ROLE, but for my case I would need to nest groups which is not possible on Cognito.
I've been thinking to use 2 custom attributes ( writable only by the admin) to set the category and role of the user respectively.
My question is, is there any disadvantage to using attributes instead of the groups?
One major concern is, those custom attributes won't be available as claims in the access token. But groups are available. So If you plan to use acces_token you may have to consider that.
There are some other minor considerations that I can think of, which may or may not be related your implementation:
Maximum number of custom attributes per user pool is 50.
Once created, you can not edit the name, min/max length and mutable property of the custom attribute. Also we can not delete that.
Even though nested groups are not supported in Cognito, is it not an option to create groups like: category_role? example: Customer_ MANAGER?

How to manage store "created by" in micro-service?

I am building the inventory service, all tables keep track the owner of each record in column createdBy which store the user id.
The problem is this service does not hold the user info, so it cannot map the id to username which is required for FE to display data.
Calling user service to map the username and userid for each request does not make sense in term of decouple and performance. Because 1 request can ask for maximum 100 records. If I store the username instead of ID, there will be problem when user change their username.
Is there any better way or pattern to solve this problem?
I'd extend the info with the data needed with from the user service.
User name is a slow changing dimension so for most of the time the data is correct (i.e. "safe to cache")
Now we get to what to do when user info changes - this is, of course, a business decision. In some places it makes sense to keep the original info (for example what happens when the user is deleted - do we still want to keep the original user name (and whatever other info) that created the item). If this is not the case, you can use several strategies - you can have a daily (or whatever period) job to go and refresh the users info from the user service for all users used in the inventory, you can publish a daily summary of changes from the user service and have the inventory subscribe to that, you can publish changes as they happen and subscribe to that etc. - depending on the requirement for freshness. The technology to use depends on the strategy..
In my option what you have done so far is correct. Inventory related data should be Inventory Services' responsibility just like user related data should be User Services'.
It is FE's responsibility to fetch the relevant user details from User Service that are required to populate the UI (Remember, call backend for each user is not acceptable at all. Bulk search is more suitable).
What you can do is when you fetch inventory data from Inventory Service, you can publish a message to User Service to notify that "inventory related data was fetched for these users. So there is a possibility to fetch user related data for these users. Therefore you better cache them."
PS - I'm not an expert in microservices architecture. Please add any counter arguments if you have any.*

CRUD operations validation

Supposed I have a database with 3 tables:
Customers
Orders
CustomerOrders
I build a WebAPI with standard auth using bearer token and I have a middleware to receive all necessary claims from the token, and I have a controller for basic CRUD operations for Orders.
for example:
DELETE - Orders/{id}
PUT - Orders/{id}
How can I make sure that the order that the user is trying to manipulate belongs to the current user?
Do I first need to query the database to make sure that the OrderId belongs to the current UserId before each operation? or is there an easier way to do it?
You can somehow manage to have the information if the user the token was issued for granted the client application to manipulate orders in general dependending on the options of your identity management and token provider.
But to make sure that this specific order belongs to the current user can only be checked in your backend and this needs of course to be done with every operation. The order id could be brute-forced (guessed) and manipulated in the request so therefore you need check this on each request.
I suggest though to extract this checking logic - does the passed order id belong to the user id provided in the token - to some service method to make it reusable from different places. In your case, for instance reuse it for the different CRUD methods such as DELETE and PUT.

How to filter data in CDS(powerapps) to restrict unauthorized users

I have created a custom entity in common data services(CDS) that streams in data from a survey.
I'll however need to give access to the data to various people. In my dataset, I have a column called community, which should represent which people have access to what data based on the community they've entered the column.
How exactly can I filter the data, after it has streamed in to ensure I only give access to people of a particular community. And yes every community is exclusive, no two people can be in two different communities.
I want to filter by the community, such that those in community A see only A and not B or C.
There’s no straight one step OOB configuration to achieve this. Because the row level security depends on the column value ie. community field value of each record.
One way is to create owner teams and add the users to right teams, then the custom entity record has to be owned by respective team - owner team of each custom entity record can be filled/assigned automatically based on the community field value on create using plugin/workflow/Flow.
Most important, in security role for that custom entity - read privilege has to be given only for user level. Assign the security role to Teams.

Access rights for the users in a team

I have users in a team having access to particular fields on lead, opportunity and account entities. I have few users who are in team they just need access to fields on lead and Opportunity entity not on account ?
I thought Ill use field level security on the fields to achieve this, having field level security will have effect other functionality in the system. Any thoughts on how to achieve this ?
Breaking down CRM security levels:
Role level - Entity level (e.g. access to Lead but not marketing list)
Record level - Read/Write/Access (e.g. read lead record but not modify them)
Field level - Field level show/hide (e.g. hide a lead's account field for certain users or team).
In your case, it depends on what defines having access (is it more of a don't need to see or a should not see scenario). If it is just a case of a set of users don't have to deal with certain fields use different CRM forms for different teams, if it is a case of they should not be seeing the data use field level security.
This also would hopefully answer "having field level security will have effect other functionality in the system?" questions, if field level security is implemented, the fields which are restricted read won't show up in the advanced find queries or reports for the users who are not assigned the field level security profiles. Also once you have secured the field, every new user or team needs the field level security profile assigned, else they won't be able to see the field.

Resources