Giter VIP home page Giter VIP logo

Comments (5)

ramonitor avatar ramonitor commented on May 22, 2024 1

@onury, thanks for the very thorough explanation, going the route you described. Thanks again!

from accesscontrol.

onury avatar onury commented on May 22, 2024

You should never expose your grants model to client side. It can be altered so it's not safe. Always do the restriction before serving the resource or content.

So for example; when your web app makes an API request and if the current role does not have permissions; it'd return 403 with a message and client-side would adapt and show the message or a templated page.

You could also fetch app configurations (such as the navigation links) restricted for that role, right at the beginning. So..

Do NOT load everything, then restrict by the role.
Do restrict on server-side by the role first, then serve.

from accesscontrol.

ramonitor avatar ramonitor commented on May 22, 2024

Thanks for your reply. Maybe I was not totally clear on my goal. :)

Of course the backend API is restricting data access according to the grants defined. I'm only looking for an easy way to reuse the inheritance model of AccessControl roles defined on the backend without defining my own logic on the frontend so that the client interface can act according to the grants defined.

For instance if on the backend I define User has readOwn permission on the Settings resource and Admin extends User, I would like to make the Settings navigation menu option available for both Admin and User without building my own logic.

So in code on the frontend I would like to do something like:

const showSettingsMenuEntry = ac.can(currentuser.role).readOwn('Settings').granted

The backend API will always make it's own decision if access to user settings data is allowed or not. I'm only reusing the same grants model on both sides, the API decides on data operations, the frontend on navigation, routes etc.. At least, that's the idea.

Hope this clarifies the goal some more, but your suggestion about fetching app configuration and navigation options is indeed better. Thanks.

from accesscontrol.

onury avatar onury commented on May 22, 2024

I'm only looking for an easy way to reuse the inheritance model of AccessControl roles defined on the backend without defining my own logic on the fronted...

The front-end code should not have any knowledge about roles or their hierarchy.

...so that the client interface can act according to the grants defined.

Yes but the way to do this should not be done by processing roles or permissions on the client-side. Server-side is the only territory that's in your control. So server should only return the privileged data, not the privilege metadata (roles, permissions, etc).

...I would like to make the Settings navigation menu option available for both Admin and User without building my own logic...

When the user is first authenticated, the session has information about their access level on server side. So when the client consumes any API endpoint, the returned data — for example in your case, the actual settings object (including navigation menu options) — would be a filtered object. In other words, it would be different for each user (role).

...So in code on the frontend I would like to do something like:
const showSettingsMenuEntry = ac.can(currentuser.role).readOwn('Settings').granted

This code is not safe on client-side, it can be altered. This also implies that Settings belonging to other roles are currently available (already fetched from server).

Instead, for example; you should do:

Server-Side:

Let's say this is the full Settings data:

{
    navigation: {
        enabled: true,
        barColor: 'blue',
        controlPanel: {
            accounts: true,
            products: true
        }
    },
    ... // some other settings...
}

Now, what we want is user role should not have access to any controlPanel in the navigation; but admin should have.

Here is your grants setup:

ac.grant('user')
    .readOwn('Settings', ['*', '!navigation.controlPanel'])   // all attrs except navigation.controlPanel
    ... // some other grants for 'user' role
    .grant('admin')
    .extend('user')
    .readOwn('Settings', ['*']); // all attributes of Settings

This is the handler for the corresponding API endpoint:

app.get('/:username/settings', (req, res) => {
    const isOwn = req.params.username === req.user.username;
    const permission = isOwn
        ? ac.can(req.user.role).readOwn('Settings')
        ? ac.can(req.user.role).readAny('Settings');
    if (permission.granted) {
        promiseSettings()
            .then(data => {
                const filteredData = permission.filter(data);
                res.json(filteredData);
            });
    } else {
        res.status(403).end(); // forbidden
    }
}

Remember that AccessControl implements attributes-based control as well as role-based control. So; you see above, before returning data to client side, data is filtered by the granted attributes.

Client-Side

Let's say the accessing user(name) is john. Client-side code does not know if this user is an admin or not.

function onLoad() {
    return get('/john/settings')
        .then(settings => {
            if (settings) {
                ui.initNavigation(settings.navigation);
            }
        });
}

Here, there is no indication of any roles or permissions. The data will decide what to do. If john is an admin, then settings.navigation would include controlPanel property. For example, you can bind your view controls to these to show or hide particular sections of the page.

Hope this clarifies a bit.

from accesscontrol.

onury avatar onury commented on May 22, 2024

For improved security,

I'd suggest you separate your administration part of the application from the one end-users reach. (It can even be protected via VPN-only entrance, if you have the resources). By inspecting the view and client source, someone can see/guess the structure, some field names, etc and use that info when they want to disturb your backend (i.e. attempt to inject code within data posted over to server, brute or DoS attacks, etc..).

from accesscontrol.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.