Let's say I have multiple microservices like authorization service (OAuth2 with JWT), VideoService and MyApplicationService.

The VideoService provides videos for MyApplicationService. Both services save user data.

A frontend makes use of all 3 services and a user doesn't know that she's actually using multiple services.

The problem is that the user registers on the authorization service. Therefore, he still needs to be registered at the 2 other services. How should this be done?

The best solution that I've come up with so far is registering the user implicitly, so that when an unknown user makes a request, a new user is automatically created (as long as the auth is valid, of course). This seems like a decent solution but doesn't feel "clean".

Is there a better, or more standard solution?

up vote 3 down vote accepted

This is where a central messaging component works well in a micro services environment. The Authorization service needs to publish an event (send a message to a queue) that a new user was registered, along with the minimal information the other services need. The other services listen for new messages on this queue and respond to the "user registered" message by auto creating their profile.

So basically the workflow should be:

  1. Authentication service publishes a "user registered" message to the user authentication queue

  2. The VideoService and MyApplicationService listen in on the authentication queue, and respond to the "user registered" message

  3. The other two services create the user profile as a result of responding to the "user registered" message.


To be honest, each micro service having its own "user profile" functionality breaks one of the main guidelines of micro service architecture: Each micro service should specialize in 1 and only 1 business function. A "user profile" is a business function.

I recommend extracting the "user profile" functionality of the VideoService and MyApplicationService into yet another service: the User Profile Service.

It would involve identifying a clear abstraction for user profiles in different services. If you can't reasonably create an abstraction for this concept, then I would keep the user profile in the other services.

Based on your question, I would suggest reviewing the following:

  1. "The VideoService provides videos for MyApplicationService". Ideally, microservices shouldn't provide (communicate) with each other. They should only serve the user (or external client). Having a network of services talking to each other creates what is called a "distributed big ball of mud".
  2. "Both services save user data". This is fine, as long as they save different data. For example, "VideoService" stores the "user preferred video categories", whether "MyApplicationService" might store the user name and phone number. So each service stores only the "part of the user" that is required for that service to operate (this is the basis to avoid service to service communication).
  3. "he still needs to be registered at the 2 other services". This is your main question, which I'll answer below:

If, by "registered" you mean that each service needs to "know" the existence of the user, for example, when a new user is registered, the VideoService creates a record with an empty list of "preferred video categories", then the right approach would be what Greg Burghardt suggested (I would just clarify that you don't put a message into a queue, but you publish an event, which ends up being a message to 2 queues, one for each service). You can identify this pattern when you here requirements like "When a user is registered, a default user profile is created" (The "When" part normally identifies a business event that is published and another service is interested in).

If, otherwise, when you say "registered at the 2 other services" you are talking about authentication, then the problem is completely different. I personally wouldn't have a client talking to multiple apis. Instead I would have a single API gateway which would then call the internal microservices APIs. This gateway would take care of authentication and basic authorization (validate roles or permissions required to access every endpoint). If, on the other hand, you prefer having a client talking directly to all microservices, you should build some shared infrastructure that would take care of single sign on to all APIs, so that the user would have to be registered only once.

  • Having a network of services talking to each other creates what is called a "distributed big ball of mud". How do you get user identity information from User Service when it is required in the Video Service without a cross microservice call? – ieXcept Sep 3 at 7:39
  • 1
    If by user identity you mean something like the user id and roles of the user doing the request, then you can have some cross cutting component that makes this information available for every request (like an injectable IUserContext). If, instead, you mean some other user properties, then you should consider moving those properties to the VideoService. – Francesc Castells Sep 3 at 9:29
  • yes, I meant user's id and roles, and I agree with you in that the inter-service calls should be as rare as possible, but I think that it is not quite possible practically to design fully separated microservices. Even absolutely Single Responsible microservices in choreography architecture sometimes need to call several other services to fulfill the user request from a gateway service. – ieXcept Sep 3 at 13:04
  • 1
    OK, then this is a cross cutting concern. Authentication and Authorization should be delegated as much as possible to an API Gateway as I mentioned in the answer and then consider the injectable IUserContext which is propagated to all services (as this is cross cutting, it's something you develop once for the whole system). Regarding if it's possible or not to design fully separated microservices, I'd say you should work with the assumption that it is possible and that you simply haven't come up with the solution yet. Just don't give up at the first obstacle. – Francesc Castells Sep 3 at 13:11
  • Also note that a user or client (through an api gateway) is allowed to call multiple services obviously, so it's perfectly acceptable that a single api request triggers queries or triggers operations on multiple services. What is not good and goes against the microservices architecture is creating a service that calls another service that calls another service. This happens when you create services like UserProfile, because then all other services will depend on this service to perform their job, which means they are not autonomous anymore. – Francesc Castells Sep 3 at 13:16

The point of microservices - or as I call them focussed services - is dealing with one topic on one logial service (which could be several physical instances).

The kind of architecture you describe could be put in the following services:

  • Auth
  • User
  • Application
  • Video
  • (Payment ...)

Both services save user data.

From what you write, it is not clear, what "user data" means. If it means something like information correlated to a user identifier, this would be fine. If you are storing some kind of "user"-object, that would be subject to change. Everything user related would be best kept in the User-Service.

As you distribute your application, you distribute your User so to say. Every service has a perspective on what a user is. If you need a summary, you have to aggregate one.


The problem is that the user registers on the authorization service. Therefore, he still needs to be registered at the 2 other services. How should this be done?

It follows an admittedly very simplistic description, but you should get the point:

From what was wirtten above. The job of the auth-Service is simply to build a single point of trust.

The auth service is something like a "box office" offering tickets to enter.

The other services trust valid tickets offered by the auth service. Their only responsibility is, checking the validity of the ticket the visitor has.

There is no need for the single services to know, whether a specific user exists. They only have to trust the ticket. Or to put it in another way: The user has not to be registered at any other service than the auth service.

The more interesting question would be, how to distribute the information that a basically valid ticket should get invalidated. But that is another topic.

I recommend for further reading:

Auth as a Service:

On Premise

TL DR; do the security job at the API Gateway and route the request to microservice if everything is OK.


You should use the API Gateway approach for your microservice architecture.

Let's say we have an API Gateway (zuul, etc.) You can connect your Auth Server(UAA, keycloak, etc.) directly to that gateway. And define a pre filter that checks the inbound request needs auth. If yes check the token at the gateway level(by asking the Auth Server directly that the token is valid and have a valid authority to do the particular job) and route the request to the microservice that you want to consume.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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