简体   繁体   中英

How to tell the identity of a user in an OSGI service call in Apache Sling?

In Apache Sling: If you have a multi tenant setting or an environment where users can deploy their own code (eg JSPs or actual Java / Groovy code or whatnot): is there a way to determine the identity of the user that has sent the current request from within a called OSGI service? It'd have to be safe against malicious code.

Background: often it is sufficient to rely on the JCR permissions to protect stuff that the user should not see. But sometimes you want an OSGI service to use a service user to access internal stuff for JCR resources needed for the service implementation, but to which you do not want the user to have access to. Here, you might have a somewhat tamper proof way to identify the user in order to check his permissions to the service.

There are some things which obviously do not work.

  • You could pass the users ResourceResolver as argument to the call into the OSGI service and check what ResourceResolver.getUserId() returns. This can easily be subverted by passing in a wrapper that delegates to the original ResourceResolver but returns something arbitrary for getUserId() here.
  • One could pass the users ResourceResolver as argument to the service, and check the users access to a certain path in the resource tree, and set JCR permissions to protect this path. Unfortunately that's not as easy as it sounds: malicious code could again pass a wrapper here which returns mock resources for this path, simulating access. The only way I see this could work is that the user has to do a write access to that path, and the service user is used to check whether this was actually modified. But that's not a nice way due to performance and other reasons.

Do you have other ideas which might actually work? Thanks a lot!

Note: I am aware that there are other attacks here you'd have to block (for instance the use of reflection to intrude into the OSGI services , but I'd like to at least make it nontrivial.

It is a multitenant system so every user will fall into some tenant. Based on the tenant context you can use RequestContext Object which actually checks whether the user of that tenant has proper access or not using SecurityManager and allows the specific users.

Well, I found at least something: ResourceResolverFactory.getThreadResourceResolver returns the last ResourceResolver for which the request authenticated itself. So if one injects the ResourceResolverFactory into the service, then getUserId of the ResourceResolver returned by this seems to give at least an user id the user can impersonate.

(Notice that this is not necessarily the original id of the user itself, since if the code used ResourceResolverFactory.getResourceResolver , this changes the result. But this at least means the user can impersonate the returned user id.)

Another thing would be to employ a ServletFilter like Composum's PlatformAccessFilter that keeps the ResourceResolver used by the original SlingHttpRequest around in a ThreadLocal. (That scheme breaks down if the malicious code is able to deploy a ServletFilter with higher priority, but we have to stop somewhere.)

Unfortunately, both ideas do not work with a service resolver, since ResourceResolverFactory.getServiceResolver does not set esourceResolverFactory.getThreadResourceResolver .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM