identifying caller in capnproto RPC

I am implementing a service in CapnProto. The service follows these steps (roughly):

  1. authenticate on the server
  2. do operations through a Service interface (object-capability) once authenticated.

I want to achieve something like the following:

interface Authorization {
   login @0 (userName :User) -> (result :Service);
}

interface Service {
   # doOperation needs userName in order to operate, as an implicit
   # parameter, when the RPC arrives. I do not want to use an explicit 
   # userName parameter. Otherwise, a user could claim to
   # be someone else in a function parameter. To achieve this I need
   # to know who is the userName that holds this capability from inside
   # doOperation. I want to avoid token authentication 
   # for each operation.
   # Thus, the RPC I am implementing is stateful.
   doOperation @0 (param1 :A); 
   #...
}

What I want is, that from doOperation, I can identify the user that is using that capability (I want to know her userName). Namely:

  • What I have solved is that the user using the Service capability is known to have that permission (since the Service is the result of calling login)

  • The problem is that I have many of those users, and, for each of them, I want to do the matching between the user of the Service capability and her login in the first step.

1 answer

  • answered 2019-08-24 08:26 Germán Diago

    It turns out that this was very simple.

    When creating Service interface in code, just pass the authentication information and save it in the Service object, like this:

    class ServiceImpl : public Service::Server {
       string userId_;
    public:
       explicit ServiceImpl(string userId) : userId_(move(userId)) {}
    protected:
       kj::Promise<void> doOperatoration(DoOperationContext ctx) override {
            //use userId_ here
    
       }
    };
    
    class AuthorizationImpl : public Authorization::Server {
    protected:
       kj::Promise<void> login(LoginContext ctx) override {
           std::string user = ctx.getParams().getUserName();
           //Here I forward the authentication state to the service
           ctx.getResults().setService(kj::heap<ServiceImpl>(user);     
           //..
       }
    };