Migrating from monolithic to microservices!?

In this article, I wanna share my thought about migrating a system from monolithic architecture to microservices architecture. Is it easy game or not. Let’s start!

Monolith Architecture

A monolithic application has single code base with multiple modules. Modules are divided as either for business features or technical features. It has single build system which build entire application. It also has single executable or deployable binary.

Microservices Architecture

A microservices architecture consists of a collection of small, autonomous services. Each service is self-contained and should implement a single business capability.

When do migration?

  • The system has high requirements related to reliability and scalability
  • The expected product development requires involving more than one team
  • The product needs quick and independent deployment because microservices allow for fast, independent delivery of individual parts within a larger, integrated system

How much the cost to do migration?

  • Complexity: the entire system as a whole is more complex especially when the number of services increases.
  • Development and Test: refactoring across service boundaries can be difficult. It is also challenging to test service dependencies.
  • Data Integrity: with each microservice responsible for its own data persistence. As a result, data consistency can be a challenge.
  • Network congestion and latency: when one business requires involving a lot of services dependencies, the latency can become a problem.
  • Management & Versioning: It could have problems with backward or forward compatibility when updating version of services.
  • Development team Skillset

Let’s try doing sample to migrate from monolithic to microservices. Take a look the exchange usecase below

  • Multiple users are using exchange for trading
  • Exchange receives buy/sell orders
  • Exchange matches orders between buyers and sellers
  • Exchange broadcasts updated order book to all users
Exchange Use Case

The monolithic architecture should be

Exchange Monolithic Architecture

To migrate to microservices architecture, we should do something below

  • Separate API to multiple smaller APIs
  • Using Event Bus (Publish–Subscribe pattern) to communicate all services
  • Using Api Gateway to aggregate as a single entry point into a system

The system now should be like this

Exchange Microservices Architecture

Sample

https://github.com/trietdvn/ExchangeNetCore

Summary

From simple sample, it takes much effort to do migration and quite hard for testing and deployment.

Microservices are the latest software architecture trend, it can make more valuable but not a God. Personally I wanna recommend undertaking on a careful consideration process before diving in. Migrating monolithic to microservices could be more shit than we think.

ASPNet Core Identity Server 4 – Resource Owner Password Customization

Overview: Identity Server 4 & Resource Owner Password

Most modern applications look more or less like this:

IdentityServer is middleware that adds the spec compliant OpenID Connect and OAuth 2.0 endpoints to an arbitrary ASP.NET Core application.

Grant types are a way to specify how a client wants to interact with IdentityServer. There are many types you can take a look here. I wanna focus on 2 common types almost applications applied.

  • Resource owner password: the grant type allows to request tokens on behalf of a user by sending the user’s name and password to the token endpoint. This is always used for Server App.
  • Client credentials: the simplest grant type and is used for server to server communication – tokens are always requested on behalf of a client, not a user. This is often used for Native App.

Scenario

I need to develop an application meets requirements below:

  • Back Office: Admin User can access via username/password.
  • Mobile App: Navative App User can access via phone number and passcode.
  • All requests to Resource Server must be authenticated via token from Identity Server issued.
  • Resource Server must identify users made requests.

The problem is Identity Server uses Client Credential grant type to authenticate with Native App User, the Resource Server will not identify who user is. Identity Server issues token without user information due to using Client Credential.

To identify user the Identity Server have to use Resource Owner Password grant type as treated with back office users.

Customization

Implementing ResourceOwnerPasswordValidator

namespace IdentityServer
{
    public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            TestUser user = null;

            // verify username password
            user = Config.GetUsers().FirstOrDefault(p => p.Username == context.UserName && p.Password == context.Password);
            if (user != null)
            {
                context.Result = new GrantValidationResult(user.SubjectId, OidcConstants.AuthenticationMethods.Password);
            } 
            else
            {
                // verify phone number and auth code
                var authCode = context.Request.Raw["AuthCode"];
                var phoneNumber = context.Request.Raw["PhoneNumber"];

                user = Config.GetUsers().FirstOrDefault(p => p.Claims.Any(k => k.Type == "AuthCode" && k.Value == authCode) 
                    && p.Claims.Any(k => k.Type == ClaimTypes.MobilePhone && k.Value == phoneNumber));
                if (user != null)
                    context.Result = new GrantValidationResult(user.SubjectId, OidcConstants.AuthenticationMethods.Password);
            }

            return Task.FromResult(0);
        }
    }
}

Customizing request from client

// using token client to request token
var clientId = "ro.client";
var clientSecret = "secret";
var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, clientSecret);

// get token by phone/authcode
var extra = new Dictionary<string, string> { { "AuthCode", "1111" }, { "PhoneNumber", "0901111111" } };
var tokenClientResponse = await tokenClient.RequestResourceOwnerPasswordAsync("xxx", "xxx", extra: extra);

//// get token by username/password
//var tokenClientResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password");

Full sample source code: https://github.com/trietdvn/custom-resource-owner-password

You can also take a look some samples here
https://github.com/IdentityServer/IdentityServer4.Samples/tree/master/Quickstarts