I am implementing a service in CapnProto. The service follows these steps (roughly):
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.
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);
//..
}
};