Moleculer: Authorization between services

Created on 17 Jun 2018  Â·  13Comments  Â·  Source: moleculerjs/moleculer

First of all, Really love the idea and structure of moleculer. Now we are thinking about using it in production.

From security point of view, we needed to implement “Authorization between Services”. So, what would be the best approaches to achieve this in moleculer?

Eg: let’s say we have a “transferMoney” service and we don’t want it to be accessible by all other services, except a few selected services.

Question

Most helpful comment

I have create and Identity service which is responsible for authentication and authorization.
Each service has it's own token, which is passed in each request between the services.
Before processing the request, each endpoint calls the authorization service with the token and the desired action.

Voila!

Basically, I've applied the same logic as I would process clients requests to the frontend api.

All 13 comments

It's great! I hope you can use it easily in your project :+1:

I recommend using middleware for authorization. With is you can check the permission before the real action handler is called. If the caller has no enough permission you can throw an error instead of calling the action handler. I recommend checking the validator middleware code because it does similar things.

Validator middleware code: https://github.com/moleculerjs/moleculer/blob/master/src/validator.js#L43
Docs about middlewares: http://moleculer.services/0.12/docs/broker.html#Middlewares

@icebob Thanks for your quick response.

Right now we are using JWT for service to service authorization and we got to do the same or something similar when we switch to moleculer.

If I understand you correctly, there is no built in functions for service to service authorization/whitelisting. We have to implement ourselves.

Yes, there is no built-in authorization between services.

@icebob noted. I think, I will work on it as a plug-in which would be more useful for a lot of people.

So, is there a way we can identify the caller service’s name and action?

Hi everyone! how are you?

@icebob with the new incoming action hook feature is going to be easier this kind of things right? https://github.com/moleculerjs/moleculer/blob/next/CHANGELOG.md#action-hooks

Yes, it's also exactly perfect for this things.
@ZeroHackeR currently you can't detect the caller services. Mainly if you use broker.call. Via ctx.call you can identify it in caller side (ctx.service.name) and you can put it to the ctx.meta

@icebob @tinchoz49 Thank you all for your inputs...

Action Hook & Middleware are good ways to intercept the requests.
However, they are not secure by default.

Lets continue form the previous example. if we allow requests with "billing" role to access "transferMoney" action, it will prevent from other services calling this action easily. But, as soon as they find out that they can bypass security check by adding "billing" role in their requests, we will be screwed.

So, I am thinking about node/service level verification/authorization before allowing an action to be called. As of now, I am not sure how I can do that with moleculer yet... :P

@icebob can namespace be used to isolate services? or it also is not secure?

@ZeroHackeR I think it is not good. the namespace is to segment your different systems on the same network. So namespace=A can't see & call services in namespace=B.

I had no similar scenario to authorize service call, but just an idea:

  1. You generate a token or API key for every service.
  2. Set this token to the service settings, or with env var...etc
  3. When you make a call, you should put it to the meta.
  4. create a e.g. guard service, which can resolve service by the token and can check that it has authority to call the "called" action.
  5. Write a middleware which catches all action calls get token from meta and call guard service before the real action will be called.

What do you think?

Of course you should keep in secret the service tokent. Every service knows only own token.
If you think it can be good, I gladly make a example code for the middleware.

But, as soon as they find out that they can bypass security check by adding "billing" role in their requests, we will be screwed.

If you work with a signed token it doesn't matter if they add the "billing" role, the token signature is not going to pass the validation.

Another option is to encrypt the object with security information (in this case the roles) using something like https://github.com/hueniverse/iron

I understand that it's better having some isolation (doing some services not visible for others) but that approach I think is better in scenarios where you have a strong isolation in different areas, like having a set of services for the frontend and another one for the backend. You can isolate this services, for example, using docker with different networks and connect them only by a secure gateway where actually you can define the rules to expose which actions do you want to be public/private.

I have create and Identity service which is responsible for authentication and authorization.
Each service has it's own token, which is passed in each request between the services.
Before processing the request, each endpoint calls the authorization service with the token and the desired action.

Voila!

Basically, I've applied the same logic as I would process clients requests to the frontend api.

great solution!

Hey, @ghqppio
What about overhead and delay with your authorization calls between the services?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DarkBlaez picture DarkBlaez  Â·  4Comments

demetriusnunes picture demetriusnunes  Â·  5Comments

ngraef picture ngraef  Â·  3Comments

slinkardbrandon picture slinkardbrandon  Â·  4Comments

icebob picture icebob  Â·  3Comments