• About Blog

    What's Blog?

    A blog is a discussion or informational website published on the World Wide Web consisting of discrete, often informal diary-style text entries or posts.

  • About Cauvery Calling

    Cauvery Calling. Action Now!

    Cauvery Calling is a first of its kind campaign, setting the standard for how India’s rivers – the country’s lifelines – can be revitalized.

  • About Quinbay Publications

    Quinbay Publication

    We follow our passion for digital innovation. Our high performing team comprising of talented and committed engineers are building the future of business tech.

Tuesday, April 20, 2021

Spring Boot Admin Server - Helps to Monitor Spring Boot Applications via Vue JS UI

 

Spring Boot Admin Server
Image Source: Sprint Boot Admin - Community Project

If you are in a micro services architecture, you will have lot of services and monitoring all of them by using Spring Boot Actuator Endpoint is quite difficult.

The CodeCentric Team provides a Spring Boot Admin Server UI to manage and monitor all your Spring Boot application Actuator endpoints at one place.

The applications register with Admin Server using Spring Boot Admin Client (via HTTP) or are discovered using Spring Cloud (e.g. Eureka, Consul). The Spring Boot Admin UI is a Vue JS application on top of the Spring Boot Actuator endpoints.

Let’s create a spring boot application which acts as a admin server. We will re-use one of the existing project as client, which registers with the admin server and we should be able to see all the information of the client on admin user interface.

Building a Spring Boot Admin Application

Let’s use the spring initializr to generate a spring boot application. Unzip the downloaded project and import it to your IDE.

For building a Spring Boot Admin Server, we need the below dependencies in the build configuration file.

<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-server</artifactId>
   <version>2.3.1</version>
</dependency>
<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-server-ui</artifactId>
   <version>2.3.1</version>
</dependency>

Next step is to add the EnableAdminServer annotation in your main Spring Boot application class file. This annotation is used to tell spring boot to make our application as Admin Server to monitor all other micro services.

@EnableAdminServer
@SpringBootApplication
public class AdminConsoleApplication {

   public static void main(String[] args) {
      SpringApplication.run(AdminConsoleApplication.class, args);
   }

}

Let’s define some of the server properties in application.properties

# Admin Server Properties
spring.application.name=admin-console
server.servlet.context-path=/
server.port=9090

We are almost ready with Spring Boot Admin service, let’s build and deploy the application. Once the application comes up, type in the URL http://localhost:9090/ on the web browser to access the Spring Boot Admin Server UI.

Sprint Boot Admin Dashboard

Now that we have admin server ready, let’s deploy another spring boot application so that we can monitor and manage it. I am taking an existing project rest-producer application for the exercise.

First, add the following dependencies in the build configuration file.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-starter-client</artifactId>
   <version>2.3.1</version>
</dependency>

Let’s configure the admin server URL and enable the actuator end points in application.properties.

# Admin Server URL
spring.boot.admin.client.url=http://localhost:9090
# Actuator Properties
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

Now build and deploy the rest-producer application. Once the application, comes up go back to the Admin Server UI and refresh the page. You should be able to see hystrix-rest-producer service registered and visible in admin server. Click on the service name, to get complete details of the service.

Sprint Boot Admin Dashboard

The Spring Boot Admin Server provides the following features for any registered applications:
  • Show Health Status
  • Show details like JVM & Memory, Datasource, Cache Metrics etc.
  • Show build-info number
  • Follow and Download Log file
  • View JVM System & Environmental properties
  • Easy Log Level Management
  • View thread dump, http-traces, audit events, http-endpoints etc.
  • View and Delete Active Sessions (using spring-session)
  • View Flyway / Liquibase Database Migrations
  • Download Heap Dump
  • Event Journal of Status Changes

Please note, the Spring Boot Admin Server has access to the application’s sensitive endpoints, so it’s recommended to add security configurations to both admin and client services. Enable the Spring Security, so that only with valid credentials the admin UI can be accessed and the client services can register with admin service with it.

As usual, the source code for the above spring boot admin server is available over on GitHub.


Thursday, April 8, 2021

Internationalization of Web Application using Spring Boot

Internationalization Globe Image

Internationalization (i18n) is the process of designing and preparing the application to be usable in different locales around the world. Localization (l10n) is the process of building versions of your app for different locales, including extracting text for translation into different languages, and formatting data for particular locales.

A locale identifies a region (such as a country) in which people speak a particular language or language variant. The locale determines the formatting and parsing of dates, times, numbers, and currencies as well as measurement units and the translated names for time zones, languages, and countries.


Building a SpringBoot Application for i18n

Let’s use the spring initializr to generate a spring boot application with dependency of spring web module. Unzip the downloaded project and import it to your IDE.

The end goal of this application is to create a web page that displays a welcome message for the user “Welcome to SpringBoot Internationalization!” on the home page. And user will be presented with an option to switch the locale or language of his/her choice. 


Resource Bundles

For an application to support internationalization (i18n), it requires the capability of resolving text messages for different locales. Spring’s application context is able to resolve text messages for a target locale by their keys.

Typically, the messages for each locale should be stored in separate properties file. This properties file is called a resource bundle, they should be added in resources folder of the spring boot application.

If we are supporting multiple locales then we will have multiple resource bundles so we need to follow a naming convention so that it’s easy for spring to lookup the values as well as easy for us to maintain it.

For example, messages_en.properties / messages_fr.properties. As you can see from the name itself we can make out first one is for English and next on is for French.


Message Source

MessageSource is an interface that defines several methods for resolving messages. The ApplicationContext interface extends this interface so that all application contexts are able to resolve text messages.

An application context delegates the message resolution to a bean with the exact name messageSource. ResourceBundleMessageSource is the most common MessageSource implementation that resolves messages from resource bundles for different locales.

Here is the bean declaration for ResourceBundleMessageSource for our application.

@Bean
public ResourceBundleMessageSource messageSource() {
   ResourceBundleMessageSource source = 
         new ResourceBundleMessageSource();
   source.setDefaultEncoding("UTF-8");
   source.setBasename("messages");
   source.setCacheSeconds(600);
   return source;
}


Application Properties

Let’s add some of the important configurations related to the resource bundle message source into the application.properties file.

I have added an explanation for each of the configuration which is easy to understand, hence am not going to details.

# Whether to always apply the MessageFormat rules, parsing even messages without arguments.

spring.messages.always-use-message-format=false

# Whether to fall back to the system default Locale, if no files for a specific Locale have been found.

spring.messages.fallback-to-system-locale=true

# Whether to use the message code as the default message instead of throwing a "NoSuchMessageException". Recommended during development only.

spring.messages.use-code-as-default-message=false


Interceptor

Next, we will add an interceptor to intercept the request and identify whether user has requested a locale change or not. It will come handy when user want to change the language of the application explicitly.

@Bean
public LocaleResolver localeResolver() {
    return new SessionLocaleResolver();
}

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
    return new LocaleChangeInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(localeChangeInterceptor());
}

The LocalChangeInterceptor looks for a request parameter name locale by default. If you are not interested to use that parameter, you can override it by giving your own parameter name.

We will add a controller that returns a web page as a response by adding the required keys into the model so that it can be access in the html page.

@Controller
public class DefaultController {
    @Autowired
    private MessageSource messageSource;
    @GetMapping("/")
    public ModelAndView getIndex(
            Map<String, Object> model, Locale locale) {
        model.put("greetMessage", messageSource
                .getMessage("welcomeText", null, locale));
        model.put("languageSupported", messageSource
                .getMessage("languageSupport", null, locale));
        return new ModelAndView("index", model);
    }
}

If you see am trying to read two keys from the messageSource, one is welcomeText and another one is languageSupport. We need to make sure whatever locales we are going to support, it has these two keys in respective locale resource bundle.

messages_en.properties
welcomeText=Welcome to SpringBoot Internationalization!
languageSupport=Language Options

messages_kn.properties
welcomeText=ಸ್ಪ್ರಿಂಗ್‌ಬೂಟ್ ಅಂತರರಾಷ್ಟ್ರೀಕರಣಕ್ಕೆ ಸುಸ್ವಾಗತ!
languageSupport=ಭಾಷಾ ಆಯ್ಕೆಗಳು

messages_fr.properties
welcomeText=Bienvenue dans SpringBoot Internationalization!
languageSupport=Options de langue

Last but not the least is to create a html page which can display the welcome message as well as provides an option to switch the locale or language.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Springboot Internationalization Demo</title>
</head>
<body>
<h1>{{greetMessage}}</h1>
<br/>
<b>{{languageSupported}}:</b>
<a href="/?locale=en">English</a>&nbsp;|&nbsp;
<a href="/?locale=hi">Hindi</a>&nbsp;|&nbsp;
<a href="/?locale=kn">Kannada</a>&nbsp;|&nbsp;
<a href="/?locale=te">Telugu</a>&nbsp;|&nbsp;
<a href="/?locale=ta">Tamil</a>&nbsp;|&nbsp;
<a href="/?locale=ar">Arabic</a>&nbsp;|&nbsp;
<a href="/?locale=zh">Chinese</a>&nbsp;|&nbsp;
<a href="/?locale=fr">French</a>&nbsp;|&nbsp;
<a href="/?locale=in">Indonesia</a>
</body>
</html>

In the above html code you can see the place holders {{greetMessage}} and {{languageSupported}}, they will be replaced with the actual messages based on the locale.

The languages supported can be returned as a list from the controller and we can loop through it and render them but for now am skipping it and hard-coding the languages supported.

Now if we compile the code and deploy our springboot application, we should be able to see the output on the web browser.

Open the browser and type in the URL — http://localhost:8181/

Internationalization English Image

Now if the user clicks on any other language options, the page should change to that specific locale or language. Let’s say I click on Kannada language, then the same web page will be rendered in that language.

Internationalization Kannada Image

Using the cURL command, you can make the request and get the response.

$ curl -X GET -H 'Accept-Language: fr' 'http://localhost:8181/'
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>Springboot Internationalization Demo</title>
</head><body><h1>Bienvenue dans SpringBoot Internationalization!</h1>
<br/><b>Options de langue:</b>
<a href="/?locale=en">English</a>&nbsp;|&nbsp;
<a href="/?locale=hi">Hindi</a>&nbsp;|&nbsp;
<a href="/?locale=kn">Kannada</a>&nbsp;|&nbsp;
<a href="/?locale=te">Telugu</a>&nbsp;|&nbsp;
<a href="/?locale=ta">Tamil</a>&nbsp;|&nbsp;
<a href="/?locale=ar">Arabic</a>&nbsp;|&nbsp;
<a href="/?locale=zh">Chinese</a>&nbsp;|&nbsp;
<a href="/?locale=fr">French</a>&nbsp;|&nbsp;
<a href="/?locale=in">Indonesia</a></body>
</html>

With Localization (l10n), we should be able to manage other customization like date and time format, currency, number formatting as these things varies from locale to locale.

As usual, the source code for the above spring boot implementation is available over on GitHub.

Wednesday, March 24, 2021

Latency and Fault Tolerance for Distributed System

Hystrix by Netflix Image

Microservices

Also known as the microservices architecture, is an architectural style that structures an application as a collection of services that are

  • Highly Maintainable and Testable
  • Loosely Coupled
  • Independently Deployable
  • Organized around Business Capabilities
  • Owned by a Small Team

The microservices architecture enables the rapid, frequent and reliable delivery of large, complex applications. It also enables an organization to evolve its technology stack.

The decentralization of business logic increases the flexibility and most importantly decouples the dependencies between two or more components, this being one of the major reasons as to why many companies are moving from monolithic architecture to a microservices architecture.

What's Hystrix?

  • Hystrix is designed to do the following:
  • Give protection from and control over latency and failure from dependencies accessed (typically over the network) via third-party client libraries.
  • Stop cascading failures in a complex distributed system.
  • Fail fast and rapidly recover.
  • Fallback and gracefully degrade when possible.
  • Enable near real-time monitoring, alerting, and operational control.

In simple terms, it isolates external dependencies so that one may not affect the other.

Hystrix provides 2 isolation strategies, thread and semaphore based isolation, but it’s left to one to decide which one works based on the requirements.

Thread Based Isolation

In this isolation method; the external call gets executed on a different thread (non-application thread), so that the application thread is not affected by anything that goes wrong with the external call.

Hystrix uses the bulkhead pattern. In general, the goal of the bulkhead pattern is to avoid faults in one part of a system to take the entire system down. The term comes from ships where a ship is divided in separate watertight compartments to avoid a single hull breach to flood the entire ship; it will only flood one bulkhead.

Hystrix Thread Isolation Image

Hystrix uses per dependency thread-pool for isolation. So, for every call only the threads from the pool of corresponding dependency are utilized. This ensures that only the pool of the dependency which fails get exhausted and leaving the others unaffected. The number of maximum concurrent requests allowed are based on the thread-pool size defined.

It’s very important to set the right thread-pool size for each of the dependency. A very small pool size may result in requests going into fallback although the downstream may be responding timely. On the other hand a very large one may cause all the threads to be blocked in case the downstream is running with high latencies, thereby degrading the application performance.

How to find the thread-pool size?

As mentioned in hystrix documentation, the correct thread-pool size can be computed with the given formula:

RPS = Requests per second at which we are calling the downstream.
P99 = The 99th percentile latency of downstream.
Pool Size = (RPS * P99) + some breathing room to cater spikes in RPS.

Let’s take an example, the cart service is dependent on product service to get the product details. Assume cart is calling product service at 30 RPS. The product service latencies P99 is 200 ms, P99.5 is 300 ms and Median is 50 ms.

30 rps x 0.2 seconds = 6 + breathing room = 10

In above case thread-pool size is defines as 10. It is sized at 10 to handle a burst of 99th percentile requests, but when everything is healthy this thread-pool will typically only have 1 or 2 active threads at any given time to serve mostly 50 ms median calls. Also it is ensured that only 10 requests are processed concurrently at any point of time, any concurrent requests after the 10th will directly go into the fallback mechanism.

Hystrix also provides an option to configure the queue size, where requests are queued up-to a certain number after the thread-pool is filled. The queued requests will be processed as soon as the threads become free. If the requests cross the queue size then it will directly go into the fallback mechanism.

Thread based isolation also gives an added protection from timing out. If, a thread in the hystrix thread-pool is waiting for response for more than a specified time(read timeout), the request corresponding to that thread is served by the fallback mechanism. So thread based isolation provides 2 layers of protection — concurrency and timeout.

To summarise, the concurrency limit is defined such that, if the incoming requests exceed the limit, it implies that the downstream is not in a healthy state and it is suffering high latencies. Also, if the requests are taking more time than the read timeout to respond, again it’s an indication that the downstream is not in a healthy state as the latency is high.

Semaphore Based Isolation

In this method, the external call runs on the application thread and the number of concurrent calls are limited by the semaphore count defined in the configuration.

The “time out” functionality is not allowed in this method, since the external call is running on application thread and hystrix will not interfere with the thread-pool that doesn’t belong to it. Hence, there is only one level of protection, i.e., the concurrency limit.

You might wonder, what is the advantage of using semaphore based isolation?

The limiting of concurrency is nothing but a way of throttling the load in case a downstream is running with high latencies and semaphore based isolation allows us that. Please note, the thread based isolation adds an inherent computational overhead. Each command execution involves the queueing, scheduling and context switching is involved in running a command on a separate thread. All of these are not required in case of semaphores, making them computationally much lighter as compared to threads.

Generally, semaphore isolation should be used when the external call rate is so high that the overhead of thread creation comes out to be very costly, or when the downstream is trusted to respond or fail quickly, so it will ensure our application threads are not stuck. The logic for setting up the semaphore size is same as the one which use for setting thread-pool size, but the overhead when using semaphores is much less and will result in faster execution.

Catch with Thread Isolation

As you know by now, if a downstream application call takes more than the defined timeout to return the result, the caller is served using the fallback defined. Please note this fallback is not served by the hystrix thread that was created for the external call, infact it will keep waiting until it gets a response or an exception from the downstream application. We can’t force the latent thread to stop the work; the best hystrix can do is to throw an InterruptedException. If the implementation wrapped by hystrix doesn’t respect InterruptedException, then thread will continue it’s work though the caller would have received the response from the fallback.

We can handle this situation by defining the read timeout as close as possible with hystrix thread timeout. Once the thread timeout is pass, the external call receives an exception which will mark the task of hystrix thread as completed and is returned to the thread-pool.

To validate the above scenarios, I have created two microservices one is named as rest-producer and other one is rest-consumer.

rest-producer microservice

This service exposes a simple API which takes username as a path variable, prefix Welcome to it and returns back to the caller.

@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{username}")
    public String getWelcomeMessage(@PathVariable("username") String userName) {
        try {
            Thread.sleep(4000);
        } catch(Exception ex) {
            ex.printStackTrace();
        }
        StringBuilder stringBuilder = new StringBuilder()
                .append("Welcome ").append(userName).append(" !\n");
        return stringBuilder.toString();
    }
}

As usual, you can find the source on github for rest-producer service.

rest-consumer microservice

This service exposes a simple API /api/greet/{username} which internally calls a service that will invoke the rest-producer service API /api/users/{username} using the restTemplate.

@Slf4j
@RestController
@RequestMapping("/api/greet")
public class GreetingController {
    @Autowired
    private GreetingService greetingService;
    @GetMapping("/{username}")
    public String getGreetingMessage(@PathVariable("username") String userName) {
        try {
            log.warn("Main Thread: {} ({})",
                    Thread.currentThread().getName(),
                    Thread.currentThread().getId());
            return greetingService.getMessage(userName);
        } finally {
            log.warn("Main Thread: {} ({})",
                    Thread.currentThread().getName(),
                    Thread.currentThread().getId());
        }
    }
}

RestTemplate Bean

@Bean
public RestTemplate restTemplate() {
   HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory
         = new HttpComponentsClientHttpRequestFactory();
   httpComponentsClientHttpRequestFactory.setConnectTimeout(5000);
   httpComponentsClientHttpRequestFactory.setReadTimeout(5000);
   return new RestTemplate(httpComponentsClientHttpRequestFactory);
}

GreetingService Implementation

@Slf4j
@Service
public class GreetingService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "fallback_getMessage", 
            commandProperties = { 
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") 
    })
    public String getMessage(String userName) {
        log.warn("Hystrix Thread: {} ({})",
                Thread.currentThread().getName(),
                Thread.currentThread().getId());
        String greetMessage = restTemplate.exchange("http://localhost:9191/api/users/{username}",
                HttpMethod.GET, null,
                new ParameterizedTypeReference<String>() {}, userName).getBody();
        log.warn("Hystrix Thread: {} ({}), Msg: {}",
                Thread.currentThread().getName(),
                Thread.currentThread().getId(), greetMessage);
        return greetMessage;
    }

    public String fallback_getMessage(String userName) {
        log.warn("Hystrix Fallback Thread: {} ({})",
                Thread.currentThread().getName(),
                Thread.currentThread().getId());
        return "Fallback Message " + userName + " !";
    }

}

If you notice, I have given connection timeout as 5 secs, read timeout as 5 secs and hystrix thread timeout as 3 secs. The downstream API has been intentionally made to respond after 4 secs. So it will demonstrate that the call from rest-consumer will be served with fallback because the hystrix thread timeout is set to 3 secs. It’s time to hit the rest-consumer API either from cURL or Postman.

curl -X GET 'http://localhost:9090/api/greet/Rogers'

You should see the response as below

Fallback Message - Rogers !

Please take a look at the log messages on the rest-consumer service.

2021-02-13 12:12:34.945  WARN 28673 --- [nio-9090-exec-1] c.b.h.controller.GreetingController      : Main Thread: http-nio-9090-exec-1 (21)
2021-02-13 12:12:35.284  WARN 28673 --- [GreetingService-1] c.b.hystrix.service.GreetingService      : Hystrix Thread: hystrix-GreetingService-1 (42)
2021-02-13 12:12:38.279  WARN 28673 --- [ HystrixTimer-1] c.b.hystrix.service.GreetingService      : Hystrix Fallback Thread: HystrixTimer-1 (41)
2021-02-13 12:12:38.283  WARN 28673 --- [nio-9090-exec-1] c.b.h.controller.GreetingController      : Main Thread: http-nio-9090-exec-1 (21)
2021-02-13 12:12:39.394  WARN 28673 --- [GreetingService-1] c.b.hystrix.service.GreetingService      : Hystrix Thread: hystrix-GreetingService-1 (42), Msg: Welcome Rogers !

As you can see, the main thread ID is 21 which is working in controller and hystrix spawns a thread with ID 42 to make an external call to the downstream service. Now the thread 42 will be on waiting state till it gets response from the downstream service. But the thread timeout has been set to 3 secs and hystrix will launch another thread with ID 41 which will give a fallback message to the controller and you see that main thread with ID 21 returns the fallback response to the caller.

Please observe carefully, the last log statement which is printed after 4 secs which is nothing but the thread with ID 42 which was on waiting state receives the actual response from the downstream after 4 secs and it prints the response. But it’s of no use as the original request is already returned with fallback message. So it proves that the hystrix thread that’ s used to make an external call will be blocked until it gets response/exception from the downstream service. Hence it’s very important to setup the http read timeout and thread timeout as same so we can avoid blocking the hystrix thread and release it back to the pool, otherwise the hystrix thread will exhaust if we have high traffic.

As usual, you can find the source on github for rest-consumer service.

With great decentralization comes a great need of resilient fault tolerance. As Netflix says, fault tolerance is not a feature, it’s a requirement.

Conclusion

Simply wrapping Hystrix around external calls does not guarantee an effective fault tolerance. Generally, it has been observed that the hystrix configurations which we discussed above like thread-pool size, isolation strategy, max concurrency limit, read timeout etc are not configured explicitly and left to use their default values. As explained configuring them as per the requirements is very important to ensure an effective fault tolerance for an application.

Configuration Reference

Alternate for Hystirx


Monday, March 8, 2021

JSON Web Token (JWT)

JSON Web Token Image

What is JWT ? How it works ? How can it keep our applications secure?

JSON Web Tokens has become the favourite choice among modern developers when implementing user authentication. Let’s understand what JWT is and how it works, specifically in the context of securing web applications.

There is an open industry standard specification called RFC 7519 that outlines how a JWT should be structured and how to use it for exchanging the information between parties as JSON objects.

Authentication is basically what happens when users sign-in. We check the user’s identity based on credentials like username/password.

Authorization, on the other hand, checks if the above-validated user is able to access specified modules or not

There are multiple ways that web applications can manage sessions and two of the popular ways is by using the tokens.

Session Tokens

In this mechanism, the server will create a session for the user after the user is successfully authenticated. The session will have an unique identifier, which is stored as a cookie on the users browser. While the user stays logged in, the cookie would be sent along with every subsequent request.

The server parses the cookie and then compares the session id against the session information stored in the memory or data store to verify the user’s identity and provides the user context to the application.

The biggest problem with this approach is, it assumes that, there is always just one monolithic server web application. That used to be the case typically in the past. But that’s no longer the case these days as we live in micro services world.

There would be multiple servers that share the load that sit behind a load balancer. When a request comes in, the load balancer decides which server to route the request. The user could have had their login request routed to one server, but the next request goes through the load balancer and may land on a different server. Now this new server has no idea about the previous interaction.

Being a techie, we may find a solution for it. Let’s say, we introduce a shared cache that all these servers persist and look up user session information which will solve the problem.

JSON Web Tokens

In this mechanism, the authentication server will authenticate the user and generate a JWT which will have all the required information. It will be sent back to the client for later usage. This is more scalable solution as JWT is stateless, which means, the user state is never stored on the server but the state is stored inside the token itself.

If the user is making a subsequent request to the application, the JWT needs to be added with the request. The application server will be configured to be able to check whether the incoming JWT is exactly what was created by the authentication server.

Let’s look at the format of the JWT to understand it better. A JSON Web Token consists of 3 sections separated by periods.

JWT Representation Image

Header

The header section typically contains 2 details — the type of token (JWT in this case) and the hashing algorithm used by the token such as RSA, HMAC, or SHA256. The default algorithm used is HS256.

Payload

The payload section contains actual data pertaining to a user is what we call as claims. The claims can be of 3 types:

Reserved Claims

These are some pre-defined claims which are not mandatory but recommended to use it as a best practise. These claims help the application judge the authenticity of the token. Listing few of them for sample are iss (issuer), sub (subject), exp (expiration time) etc.

Public Claims

These can be defined based on the requirements by those using JWTs. As it’s a public claims, to avoid issues they should be defined in the IANA JSON Web Token Registry.

Private Claims

These are the custom claims created to share information between parties that agree on using them. Listing few of them as sample are employment type, department name etc.

If anyone is interested to read more about claims, you can read it over here.

Signature

The signature is the most important part of a JSON Web Token. It is calculated by encoding the header and payload using Base64URL Encoding and concatenating them with a period as separator, which is then run through the cryptographic algorithm. Please remember when the header or payload changes, the signature has to be calculated again.

// Signature Algorithm
jwtData = base64urlEncode(header) + "." + base64urlEncode(payload)
signature = HMAC(jwtData, secret_salt)

// Token Generation
token = encodeBase64Url(header) + "." + encodeBase64Url(payload) + "." + encodeBase64Url(signature)

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaXNzIjoiQmhhcmdhdiBJbmMuIiwiZXhwIjoxNjEzOTM4Mzg3LCJpYXQiOjE2MTM5MjAzODd9.XblnkCqOUdtjLIg2pJcN_7gXUc7nSHIuXnBwin8hSeQ


What’s next ?

Shhh! Let me tell you a secret. Go to jwo.io website, copy the above JWT and paste it in the encoded section of the online debugger. Voila, you could see all the data stored in the token. Now you will have a question on your mind, what the heck, how is this secure? 🤔

Please note that, JWT’s are encoded but not encrypted. It is a mechanism by which you can verify that the data is not tampered and has come from the trusted source.

The two open industry standards that describe the security features of JWT are RFC 7515 for JSON Web Signature and RFC 7516 for JSON Web Encryption.

JSON Web Signature

The purpose of a signature is to allow one or more parties to establish the authenticity of the JWT. Now if you remember the signature is basically the encoded header and payload concatenated with a period and then run through a hashing algorithm with a secret key.

The signature attached at the end helps us to determine if the JWT has been tampered with because for any change in the data the signature will change. A signature, however does not prevent third parties from reading the contents of the JWT.

JSON Web Encryption

JWS provides us to establish the authenticity of the JWT contents, where as JWE provides a way to keep the contents of the JWT unreadable to third parties.

An encrypted JWT, can use two cryptographic schemes — a shared secret scheme or a public/private-key scheme.

Conclusion

JWT is a modern and robust solution to authenticate and authorise users and sharing sensitive information while not maintaining state. A JWT is made of three parts — header, payload and signature. Sending JWTs in cookies instead of in the header, shortening their expiration time and using refresh tokens to issue new access tokens are some of the security measures we can take to guarantee the security of our application, its users and their data.

Monday, February 22, 2021

S.O.L.I.D — Design Principles

 

S.O.L.I.D — Design Principles Image

Software Design Principles

In today’s world, customer requirements keep changing at an unprecedented pace. It becomes essential for the technical teams to accommodate the new requirements and deliver those very quickly. To develop and deliver faster, it’s necessary to reduce software development and testing time.

At the same time, new technologies are introduced every few months. It’s common to experiment with more optimal and efficient technologies by replacing the existing ones. Thus, it’s important to write the code that is flexible and loosely coupled to introduce any changes.

Well written code is easy to grasp as new developer doesn’t have to spend more time reading the code. A well maintained software thus enhances developer’s and the team’s productivity. In addition, high test coverage increases the confidence to deploy a new change to the production.


Where do SOLID principles come from?

SOLID principles came from an essay written in 2000 by Robert Martin, known as Uncle Bob, where he discussed that a successful application will change and, without good design, can become rigid, fragile, immobile and viscous.

  • Rigid — Things are very fixed. You can’t move or change things without affecting other things, but it’s clear what will break if you make a change.
  • Fragile — Easy to move and change things but not obvious what else might break as a result.
  • Immobile — Code works fine but you can’t re-use code without duplicating or replicating it.
  • Viscous — Everything falls apart when you make a change, you quickly push it back together and get your change working. The same thing happens when somebody else comes along to make a change.

The principles that Robert Martin talks about to avoid the four design anti-patterns above have evolved to be known as the SOLID principles. Although he didn’t invent the principles, he pulled together some good coding practices that already existed around a central theme of managing dependencies and put forward a good argument for using those practices together.

In object-oriented world, S.O.L.I.D is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible, and maintainable. Let’s go through all five principles.

Single Responsibility Principle

One of the simplest principles to understand. It states that, a class should only have one responsibility. Furthermore, it should only have one reason to change.

Open/Closed Principle

Simply put, classes should be open for extension, but closed for modification. In doing so, we stop ourselves from modifying existing code and causing potential new bugs.

Liskov Substitution Principle

The principle states that, objects of the same superclass should be able to substitute each other without breaking an existing code.

Interface Segregation Principle

According to this principle, the larger interfaces should be split into smaller ones. By doing so, we can ensure that implementing classes only need to be concerned about the methods that are of interest to them.

Dependency Inversion Principle

The principle of Dependency Inversion refers to the decoupling of software modules. This way, instead of high-level modules depending on low-level modules, both will depend on abstractions.

Conclusion

The above five principles form a foundation for the best practices followed in Software Engineering. Practicing the above principles in day to day work helps improve the readability, modularity, extensibility and testability of the software.

One thing you can guarantee with any application, if it’s successful and used extensively, it will change over the time. As it changes, the complexity factor gradually increases until you hit a tipping point where it becomes more difficult and takes longer time to ship new features on top of the poorly written code that was quickly shipped once.

I’ll leave you with following questions which I’ve found useful to ask myself while writing code:
  • Is the class DRY(Don’t Repeat Yourself)?
  • Does everything in a class change at the same rate?
  • Have I abstracted out something that is likely to change?
  • Have I abstracted out something that is not used in all classes that inherit it?

Featured Post

Your AI Sidekick: How Claude took over Pritee’s Repetitive tasks

  It was a classic Wednesday morning in our Bengaluru office . Pritee, one of our sharpest Project Managers, had just stepped out of a stake...