Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to make sure an AUTHENTICATED user is AUTHORISED to access a resource - Spring mvc, Spring Security, Hibernate

We have a spring mvc rest api, utilising spring security and hibernate to a MySql db.

We have some roles configured. For example:

Standard user: ROLEA

Super user: ROLEB

Currently to ensure that an authenticated user is authorised to access/update a certain resource we do something like this:

Identify the current authenticated user:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String activeLogin = authentication.getName();

Identify the login associated with the entity they are trying to access:

String loginAssociatedToRequestedEntity = fooService.getEntityA(EntityAId).getEntityB().getEntityC().getLogin();

Compare the user associated with given resource to active login:

if (!loginAssociatedToRequestedEntity.equals(activeLogin)) { 
throw new ForbiddenAccessException();
}

I have a number of issues with this, some of these include:

  • Very wasteful… each entity would have to be hydrated/populated. This could be even worse than the above example if the entity to be accessed is further away from the table with the login names in.
  • Seems like a code smell (Law of Demeter).
  • A request may come in that could update multiple entities. A similar check to the above may have to be repeated.

I have considered the following as possible options:

Spring ACLs

Apache shiro

So my question is, is there a best practice to make sure an authenticated user is authorised to access a certain resource i.e. stopping them from accessing a resource of another user in the same role.

If you could point out a concrete example (github) that would be much appreciated.

TIA.

like image 965
Hurricane Avatar asked Mar 04 '16 14:03

Hurricane


People also ask

How do I authenticate a user in spring?

Simply put, Spring Security hold the principal information of each authenticated user in a ThreadLocal – represented as an Authentication object. In order to construct and set this Authentication object – we need to use the same approach Spring Security typically uses to build the object on a standard authentication.

How does authentication work in Spring Security?

The Spring Security Architecture There are multiple filters in spring security out of which one is the Authentication Filter, which initiates the process of authentication. Once the request passes through the authentication filter, the credentials of the user are stored in the Authentication object.

What dependency will you need to protect resources with Spring Security in spring boot application?

Spring Boot provides a spring-boot-starter-security starter which aggregates Spring Security related dependencies together. The simplest and preferred method to leverage the starter is to use Spring Initializr using an IDE integration (Eclipse, IntelliJ, NetBeans) or through https://start.spring.io.


1 Answers

While role membership checks are somewhat of an anti-pattern (it's better to code to the permission or activity), they are commonly used for service level access control (web requests & method invocations), but not at all suited for securing actual domain objects in a multi-tenant setting, e.g. to prevent a user from accessing a resource of another user of the same role.

Your approach of checking if an authenticated login is associated with a particular domain object will work, but it's cumbersome, couples and/or pollutes your application data model with the security data model, and as you suspected, is not a best practice.

You've already identified some options:

Apache Shiro provides a consistent and easy-to-use API that supports domain object access control, but you're responsible for providing the backend "realm", which means you might have to implement your own data store and/or DAOs.

Spring Security ACLs is Spring's access control paradigm to secure domain objects. It decouples the security data model from your application data model. Access Control Lists make it easy to grant or check access to domain objects by adding or looking up ACL entries, but you might need to write your own DAO if you want to efficiently find all domain objects a user has access to (e.g. to present those objects in a list or to revoke access to them). Furthermore, you are responsible to maintain ACLs because:

Spring Security does not provide any special integration to automatically create, update or delete ACLs as part of your DAO or repository operations. Instead, you will need to write code [...] for your individual domain objects. It’s worth considering using AOP on your services layer to automatically integrate the ACL information with your services layer operations.

— Spring Security 4.0 reference

Lastly, you'd have to customize the ACL implementation if the default API isn't compatible with your application model (e.g. if your domain objects don't have a public getId() or don't use IDs compatible with long)

If you're not married to Spring or Shiro for providing domain object access control, there's yet another alternative:

OACC, an open-source Java security framework (disclosure: I'm maintainer and co-author), that provides a rich API to both enforce and manage your authorization needs. OACC is a complete access control framework with a rich API that doesn't require any DIY implementation to enable the programmatic and dynamic modeling of fine-grained authorization. It features a fully implemented RDBMS-backed data store for its security model, which the API manages for you behind the scenes.

OACC's security model is permission-based: it essentially manages permissions between resources. Resources represent both secured domain objects and the actors on them (i.e. subjects). It also provides efficient query methods to find resources by permission, without loading all resources first and then filtering out the unauthorized ones. These methods are symmetric in the sense that you can find both the resources to which a specified resource has a specific set of permissions, and the resources that have a specific set of permissions to a specified resource

Compare the OACC fragment to grant permission below with the sample code from the Spring Security ACL reference:

// get the resource representing the principal that we want to grant permissions to
User accessorUser = Users.findByName("Samantha");
Resource accessorResource = Resources.getInstance(accessorUser.getId());

// get the resource representing the object that we want to grant permissions to
Resource accessedResource = Resources.getInstance(Foos.findById(44).getId());

// Now grant some permissions
Permission permission = ResourcePermissions.getInstance("ADMINISTER");
oacc.grantResourcePermissions(accessorResource, 
                              accessedResource,
                              permission);

To check for authorization, you can either call

oacc.assertResourcePermissions(accessorResource, accessedResource, permission);

or check the return value of

oacc.hasResourcePermissions(accessorResource, accessedResource, permission);

Another novel feature of OACC are create-permissions, which not only control what kind of resources a subject may create, but also define exactly what permissions they would get on a new resource after creating it - defined once, permissions are automatically assigned to a resource creator, without the need for explicit API calls.

In summary, OACC was developed specifically with your use case of authenticated, fine-grained authorization in mind.

like image 78
fspinnenhirn Avatar answered Sep 20 '22 13:09

fspinnenhirn