[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] remote service call authorization implemenation

Hi Scott,
Thanks for the comments.
My use case is quite simple: I'm using spring security framework server side for authentication and authorization because it's quite easy to configure and a lot of the authentication and authorization work is done for you. Of course I still need to provide the authentication information in a spring security manner and because I'm using ECF for client/server communication, it comes down to implement some "binding" code between ECF and spring security.
The "binding" code is a class (see code below) implementing both IConnectHandlerPolicy and IRemoteServiceCallPolicy, it gets the authentication manager of spring security injected to delegate the authentication and it uses SecurityContextHolder to inject the authentication info (granted authorities) right before the service call and clears the context after the call. So in my use case it does not matter which approach is used, both are easy to implement. Currently, only downside of first approach is casting IRemoteServiceRegistration to RemoteServiceRegistrationImpl of ECF generic in order to call callService method but as you said it's easy to solve by adding callService method on IRemoteServiceRegistration interface.
Code below is shown with the second approach:



import java.util.HashMap;






















* Class delegating the authentication to spring security and keeping the authorization roles

* for the authenticated user until disconnect or log off


@author Franky Bridelance



class AuthenticationInterceptor implements IConnectHandlerPolicy, IRemoteServiceCallPolicy {

private AuthenticationManager authenticationManager;

private final Map<ID, Authentication> authenticatedUsers = new HashMap<ID, Authentication>();


public PermissionCollection checkConnect(Object address, ID fromID, ID targetID, String targetGroup, Object connectData) throws Exception {

if (connectData instanceof UsernamePasswordAuthenticationToken) {

Authentication request = (Authentication)connectData;

// can throw an AuthenticationException

Authentication result =


authenticatedUsers.put(fromID, result);


return null;



public void refresh() {

// TODO Auto-generated method stub



* Setter method to inject authentication manager dependency


@param authenticationManager


public void setAuthenticationManager(AuthenticationManager authenticationManager) {

this.authenticationManager = authenticationManager;



public void postInvocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID, Object result) throws Exception {

Authentication authentication =


if (authentication != null) {





public void preInvocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception {



2010/10/7 Scott Lewis <slewis@xxxxxxxxxxxxx>
Hi Franky,

First, I want to say...nice job!  This will make a very nice addition to ECF remote services.

I should say though that we are approaching ECF 3.4 minor release (hopefully at the end of this month), and it may not be possible to get these API changes (and consequent changes to provider impls) decided upon and incorporated into the ECF 3.4 release.  We've got to have an EF review and stuff like that as part of the release...so I just want to make sure you know that if we don't get this work into that release it's simply because of the mechanics of the releng process...and no reflection on the value of this work.  I'm sure that we will be able to get it into later releases in some form.

With my comments below, I'm going to focus on the API additions rather than the implementation...i.e. to the org.eclipse.ecf.remoteservice package...rather than the specifics of the implementation.  The reason for this is that I think that the API additions/changes are the most important to think carefully about...as API is forever :), while implementation bugs can be relatively easily fixed.

So...see further comments inline.

On 10/5/2010 6:09 AM, Franky Bridelance wrote:

Hi Scott, all,

<stuff deleted>

- Server creates container
- Get ISharedObjectContainerGroupManager interface from the container
- Set an implementation of IConnectHandlerPolicy on ISharedObjectContainerGroupManager that will 
      + get the connect data 
      + use this connect data to authenticate (via spring security)
      + if authentication fails throw an exception
      + if authentication succeeds: retrieve the authorization roles (via spring security) for the authenticated user and link this to the client container ID (fromID arg in IConnectHandlerPolicy.checkConnect) --> question: is the client container ID unique?


For the authorization of remote service call there's as far as I know no API available, so I checked what is needed and came up with a proposal API. I tried to make the API generic enough to support several authorization implementations, provider independent and at the same time fitting ECF generic implementation and spring security integration.

This is great...exactly right about the need for generality and cross-provider support.

So what I need is a way to intercept the remote service call at the server side to do some authorization checking (or in my case to provide the needed information to spring security). It's important to have the interception "around" the remote service call such that authorization specific code can be performed before and after the remote service call (in my case some authorization info would be put before the service call for spring security and cleaned up after the call). In ECF generic implementation, what I think would be the right place (but here I'm maybe looking too much at how to integrate with spring security) is in RegistrySharedObject.executeRequest within the run method of the created IProgressRunnable around "localRegistration.callService(call)". I have three reasons to place the authorization interception there:
1. If an exception must be thrown because the call is not authorized the exception will be handled correctly.
2. We're sure not to have any thread context switching from this point to the local service method call (at least not in the ECF layer, you can still have thread context switching within the service method call but that's application specific).
3. It's the last method having all information needed for authorization: ID of the caller (client container), method call and service on which call is performed.

Yes, understood.

For the API, I was thinking to have a policy interface (like the IConnectInitiatorPolicy and IConnectHandlerPolicy) that can be set on IRemoteServiceContainerAdapter interface (question: is this the right place?

Because IRemoteServicecontainerAdapter looks more a client oriented interface while the IRemoteServiceCallPolicy is more a server thing),

Yes, it is the right place for this, I believe.  IRemoteServiceContainerAdapter has both remote service 'host' (aka server), and 'consumer' (aka client) methods on it...as there isn't any assumed asymmetry in the remote service API (all just remote service api supporters...able to both register remote services and access the remote service).

for example:

public interface IRemoteServiceCallPolicy {
    public Object callWithAuthorization(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;

and on IRemoteServiceContainerAdapter there should be a new method:

public void setRemoteServiceCallPolicy(IRemoteServiceCallPolicy policy);

<stuff deleted>

There's one thing that bothers me with this solution: an implementation of the IRemoteServicecallPolicy.callWithAuthorization would need to have ECf generic internal knowledge to be able to  call localRegistration.callService method because this method is not part of the IRemoteServiceRegistration interface.

Hmm.  One possibility is that the IRemoteServiceRegistration interface be enhanced (i.e. to include a callService method). 

Another (maybe better) solution could be to have an interface with a pre invocation hook and a post invocation hook. The preinvocation hook can then be used to authorize the service method call and the post invocation hook can be used to clean up authorization data that was set up at the preinvocation hook.
public interface IRemoteServiceCallPolicy {
    public void preInvocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;
    public void postInocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;
<stuff deleted>

What's you opinion on this?

This second approach is interesting.  It's perhaps a little more complex (two methods rather than one), but in some ways it's more similar to the approach taken in Java 2 security (i.e. the security manager).

My immediate inclination is to prefer the first one (for simplicity).  But I would like to discuss with you (Franky) in public (i.e. here on the mailing list) a little bit about your use case...to try to understand which would work better for this and other use cases.

So if you don't mind me asking in public...what are you doing inside of IRemoteServiceCallPolicy for your use case?  Is one of the two approaches you list above simpler in your use case?  If so, which one?

Thanks again for doing this...and for considering contributing back to the ECF project.  This will help all in the community.


ecf-dev mailing list