The motivation to build microservices architecture as opposed to a monolith may come from different reasons.
- Take advantage of scalability
- Deploy smaller changes more frequently
- Break out different domains to different teams
How to implement microservices architecture while presenting a single web application to the customer ?
Use OAuth2 Authorization Code Flow grant type.
Use Node/Express in the gateway layer to handle OAuth2 interaction with an OAuth2 server such as Cognito or FusionAuth.
Here is an excellent article from FusionAuth that will help you implement OAuth2 interaction in Gateway layer, in literally 5 minutes.
Perform aggregation of data from multiple microservices, when needed, in the Gateway layer. Avoid having a microservice call another microservice directly.
Pass token obtained from authorization server as bearer token in the header when invoking REST backend microservices. User identity attributes in the token will allow your microservices to incorporate fine grained authorization checks.
When deploying Gateway Orchestrator along with the microservices to the same Kubernetes Cluster, You can refer to the Microservices using Kubernetes service domain urls. Then, only your gateway orchestrator will need to be exposed via Ingress, not your microservices.
Configure your backend microservices to validate the token. If you are using Java, spring-oauth2 libraries will help you implement this very easily.
Configure your Gateway application to perform cert validation when making https calls to the REST microservices.
Use Lambda Authorizer if you need to inject custom user attributes, not configured within AWS cognito, into the token created by AWS Cognito
when designing Domain driven Microservices, you will immediately find out that although your domains may look independent at the outset, there will be common entities needed in different domains.
For example, you may have a domain driven microservice to manage customers that is responsible for adding new customer customer accounts and updating them. But your orders system will also need some basic customer information to display past orders, etc.
A simple approach to this problem is to allow duplicate entities across domains to exist. Otherwise, the microservice developer cannot fetch related data using a simple join and you would be introducing a REST call from one microservice to another.
When duplicate entities across domains exist, clearly identify the service owner for that entity and ensure that the service is responsible for sending out notifications on any new entities or updates to existing entities. The other services will need to subscribe to these notifications and update themselves.
You may also have a situation where your web application is pulling that small slice of common data from different services. Hence, an update made to customer address will reflect immediately to the consumers of customer service but may not show without some sort of refresh action in another area of the web application where the customer address information is fetched as secondary data from another microservice.
- Allows UI devs to focus on the front-end angular development and not worry about the middle and backend layers.
- Let Java Devs be Java Devs and not have them worry about UI.
- Quicker build and deploy Pipeline runs.