0

I want to execute everything in a user context. Meaning that if the request comes from one user then the service has a token of only this user and can't execute anything for another user.

Now the problem:

Service A publishes a message to MQ which is consumed by Service B.

Service B then makes a REST call to Service C to retrieve some user data and then execute some action.

The problem is that Service B doesn't have the user context anymore because the "request" is coming from a Message Queue. It means that either Service B or Service C should have God privileges to execute things for any user which doesn't sound appealing from a security perspective.

How to deal with this problem? Maybe there is a pattern it?

8
  • 1
    Assuming Service B can only process messages produced by Service A, can it not take the assumption that if Service A produced a message for a given user, then the user is authorized to perform that action? Otherwise, is there anything preventing you from adding the user context to the message produced by Service A? Sep 23 at 13:05
  • There is no user token in the message. That also sounds like a security problem. Service B can technically see on which user the action needs to be executed but can't verify as there is no user token at that point.
    – user980828
    Sep 23 at 13:08
  • 1
    "There is no user token in the message." That was my point, what's preventing you from adding it (or any other information allowing you to verify authorizations) to the message? I fail to see a security problem in your scenario. Can you describe furthermore what the issue is from a security point of view, and how it may be exploited? Sep 23 at 13:09
  • If message execution fails it can get logged with a stacktrace and the user token will be exposed in the logs. But I guess it's acceptable in such case? Maybe there should be a special mechanism in place to filter out the message body from stacktrace.
    – user980828
    Sep 23 at 13:16
  • @user980828 you do not need to filter the entire message body, that would significantly reduce the usefulness of the logs. You can just filter out the sensitive properties. I mean just hardcode the exclusion of userToken.
    – marstato
    Sep 23 at 13:19
0

I'll have to frame challenge this. Your code inherently has super-user/god/system-level/call-it-what-you-want privileges. Your code decides what happens. If your code is buggy, no permission system will save you!.

But let me address two actual approaches first:

1. Put the authentication token into the Message

If you do this, service B can use the token for all its actions. All actions can be properly secured. But what do you do when that token expires before your message is consumed? In that case you're totally out of luck. For that reason i'd discourage this approach.

2. Put the user id into the message

This way, service B still has the context information. It can now obtain a token for itself with permission scope of that user; the token gets granted to service B (and you can verify that only service B can make requests with it) but the token has the permission scope of the user, so all actions can be properly secured. Further upside is that you can track in your logs that some actions were not performed directly by a user but rather by one of your services on behalf of the user. This requires service B to have that impersonation privilege, though. I'd say this is perfectly acceptable.

But this one also has a problem: what if service B has to perform an action that an end-user should never be allowed to do themselves, but can reasonably result from one of their actions? Then this doesn't help, either.

So, here comes a little frame challenge:

3. God privileges and code review

Give service B god privileges. You can still use tokens that encode the "service XY acts on behalf of user Z" information for audit and debugging purposes.

Then, use code reviews to make sure

  • all user-reachable endpoints have proper and correct permission checks on them
  • your code doesn't do sh*tty things!!, especially code that reacts to MQ messages.

Here is an example of one such situation where you need god privileges. Say you're working on a car sharing software. You have a rental service. It that handles ending the rent with the user and then publishes a CarRentalEndedMessage. Your cleaning-planning service will want to listen for this message and maybe enlist the car for cleaning. That is 100% reasonable. But do you want your end users to be able to enlist vehicles for cleaning?

0

Your solution, for a system that ships text-based messages around, is a SOAP message. All that authentication and message authenticity, transactions, etc. can all be added to the SOAP Header. Platforms already now how to process and recognize that.

This type of problem is what SOAP was designed for - the need to send a message over multiple types of transport (HTTP, file, message queues, email, etc.) while maintaining that application context stuff.

For example, when I program that, the code for Service C already has awareness of the user ID I can use it programmatically by calling the application Platform API. And since SOAP is standardized, I'm not locked into a particular set of libraries or products.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.