Comments (7)
@broom9 We could definitely consider adding role inheritance. If you have ideas on how this could be implemented, then feel free to share them here and we'll see how we can make things happen.
As of today, and as a you mentioned in your issue, adding multiple roles is indeed the way to go with the current implementation. If you're using the builtin memory store, then it will take care of fetching permissions for all roles the user is assigned to and evaluate permissions associated with each of those roles.
On another note and to better understand your use case, which of RBAC or ABAC do you need?
from access-control.
from access-control.
Reading your explanations, conditions with dynamic variables indeed seem to fit your needs. I'm trying to provide some examples below, let me know if things are not clear enough.
Ensuring that resource.userId == req.user.id
Assuming an endpoint GET /profiles/:user_id
that allows users to fetch profile information. To ensure that the user only accesses their own information, you could write a permission like this:
const permission = {
id: 'UserFetchProfile',
resource: 'profiles',
action: 'fetch',
effect: 'allow',
condition: {
stringEquals: {
simpleValue: {
'req.params.user_id': '{{{subject.id}}}'
}
}
}
};
Then to check the user's permissions:
const subject = new Subject(req.user);
accessControl.authorize(subject, 'profiles', 'fetch', { req }); // <- Passing req to the environment
Ensuring that users only reach the tenant they're allowed to
Gonna assume that you're storing something like a tenant_id
property within your user data and that you're able to access the tenant's id from the url in your request. We can modify the condition as follows to add the constraint.
const permission = {
id: 'UserFetchProfile',
resource: 'profiles',
action: 'fetch',
effect: 'allow',
condition: {
stringEquals: {
simpleValue: {
'req.params.user_id': '{{{subject.id}}}',
'tenant': '{{{subject.tenant_id}}}'
}
}
}
};
Then to check the user's permissions:
const subject = new Subject(req.user); // <- Where req.user.tenant_id is defined
const tenant = parseTenant(req); // <- Your way to parse the tenant information
accessControl.authorize(subject, 'profiles', 'fetch', { req, tenant }); // <- Passing req and "tenant" to the environment
This will guarantee that the user can only fetch their own profile on their assigned tenant.
If what you are looking for is a way to factorize the tenant check for all users, then I'm afraid it could only be done with condition merging, which is a bit different from role inheritance and would probably be hard to implement. I'm definitely open to suggestions on how to handle this though. Hope that clarifies things a bit!
from access-control.
Thanks for the detailed example codes. There is still one thing I'm not sure it's clear.
When you delcare simpleValue condition like this:
simpleValue: {
'req.params.user_id': '{{{subject.id}}}'
}
The key 'req.params.user_id' is retrieved from the environment, basically the package will try to do environment.req.params.user_id
, which makes sense.
Does the value subject.id
need to be in the environment as well? I thought it would use the subject parameter passed into the authorize
method, but from my experiment looks like it needs me to pass "subject" as a key in the environment. https://github.com/bluebirds-blue-jay/access-control/blob/13610cf9bfc8d8ac8553cc813e35b3454482458b/src/classes/condition-evaluator.ts#L81
from access-control.
@broom9 I just checked our own project's implementation and indeed the subject is not passed by Bluejay. Instead we have an environmentFactory
utility that extracts the most common environment values from the request, which I'm partially reproducing here:
import { Keys } from '@bluejay/access-control';
export function environmentFactory(req: Request): TAuthorizeEnvironment {
return {
bodyAttributes: Keys.list(req.body),
body: req.body,
headers: req.headers,
queryAttributes: Keys.list(req.query),
query: req.query,
params: req.params,
subject: req.subject.toJSON() // We store the subject on the request
};
}
Then:
authorizer.authorize(resource, action, environmentFactory(req));
The {{{subject.id}}}
in the previous example is indeed explicitly passed to the environment.
from access-control.
from access-control.
See example here: https://github.com/bluebirds-blue-jay/access-control#condition-variables.
I'm assuming that you found a way to achieve your goal @broom9, closing for housekeeping.
from access-control.
Related Issues (20)
- Better way to accept null values HOT 3
- Can't install this from yarn HOT 3
- Validate resource in addPermissionToRole
- NPM detected vulnerability HOT 2
- Multiple conditions in one statement HOT 3
- Multiple to Multiple condition HOT 1
- Keys.filter() will not filter out an object property that equals an empty object. HOT 4
- Attach more data besides returnedAttributes to permissions HOT 1
- Dependencies due for update HOT 1
- forAnyValueIfExists should pass if environment doesn't have the key
- Suggestions: Hierarchical Role Based Access Control & more... HOT 3
- PermissionEffect type conflict HOT 5
- Fix vulnerabilities HOT 1
- forAllValuesIfExists doesn't pass for env value `null` HOT 4
- Value Associated with Role? HOT 2
- Would this PR be welcomed here? HOT 1
- lodash version bump? HOT 2
- Probably the cleanest repo i've ever seen. Love the use of emojis :) HOT 1
- No Doc for Persistence Layer HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from access-control.