Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

In adding Mobile Toolbox to Bridge, we’re encountering more complex authorization. We have roles like an organization administrator, who can create users who are members of their organization (but who cannot see study participants), and study designers, who can edit some of the things that a developer can edit…but only in the context of the studies they have access to.

Right now these checks are spread out:

  1. Controllers usually check for roles and consent;

  2. AuthUtils methods are called in the services to check the relationship of the caller to entities like studies and organizations.

This is getting messy. I think we could use a more robust alternative. Here are three options I can think of:

Spring Security

This is the most complex option available. Because we didn’t start with it, it would require a lot of implementation work to override Spring’s defaults for authentication, but then authorization could be done with annotations on our service methods.

Implement a DSL

Nothing Spring does is that hard to duplicate with a DSL that uses our existing RequestContext. It could look something like this:

private static final AuthEvaluator IS_ORG_ADMIN = AuthUtils.orgMember().inRole(ORG_ADMIN);
    
// If we pass arguments in when we check, these are threadsafe and composable
private static final AuthEvaluator IS_ORG_ADMIN_OR_ADMIN = IS_ORG_ADMIN.or().inAnyRole(ADMIN, SUPERADMIN);
    
public void mustBeAnOrgAdmin(String appId, String orgId) {
    IS_ORG_ADMIN.checkAndThrow("orgId", orgId);
        
    // do something
}
    
public void mustBeSomeKindOfAdmin(String appId, String orgId) {
    IS_ORG_ADMIN_OR_ADMIN.checkAndThrow("orgId", orgId);

    // do something
}

Pros:

  1. Easier to implement and understand at this point, when compared with overriding Spring Security’s implementation classes

  2. Arguably, easier to understand because it’ll only contain what it necessary for our application (as opposed to Spring which is always more complicated because it can handle anything, including future requirements)

Cons:

  1. If we do this early in the method, like Spring, empty/null/imaginary values are going to throw security exceptions, which might be confusing (but also requires less work on our part). For example if the user submits a made up orgId and the call requires the user be in that organization, they’ll get a security error not a validation error. (I’m fine with this).

  2. More custom code for new developers to learn (assuming they know Spring security down to how it is implemented)

  3. Still only in code and does not move permissions to a database.

  • No labels