{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/18","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Enum is a typed constant that is specified for the new data form of Enumeration. An effective way to describe a set of named integral…","fields":{"slug":"/engineering/enum-csharp/"},"html":"<p>Enum is a typed constant that is specified for the new data form of Enumeration. An effective way to describe a set of named integral constants assigned to a variable is to include a Typesafe enumeration. Enums make the code more readable and less vulnerable to mistakes. If you have a set of functionally important and unchanged values, Enums are useful for developers.</p>\n<p>Enums' key benefit is to make it possible in the future to adjust values. Enums are a robust alternative to the short String or Int constants used to describe sets of similar objects in far older APIs.</p>\n<p>Sometimes we must use the constant variable in our application to not be changed throughout the application. One of the methods to declare the continuous variables are <code>Enum.</code> Let's discuss it.</p>\n<h2 id=\"using-enum-in-c-sharp\" style=\"position:relative;\"><a href=\"#using-enum-in-c-sharp\" aria-label=\"using enum in c sharp permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using Enum in C Sharp</h2>\n<p>Enum is the short form of Enumeration. Enum consumes less memory and space because they are value types, which means they store memory value. Also, Enums are strongly typed named constants. </p>\n<p>Enums written by developers are used in the <a href=\"https://en.wikipedia.org/wiki/.NET_Framework\">.NET system</a> to develop numeric constants. A numeric value must be allocated to all the members of an enum. Here are the main points about Enums:</p>\n<ul>\n<li>In C#, Keyword Enums build enumerated types of data</li>\n<li>Enums are made for developers</li>\n<li>Enums are strongly typed constants, as described above.</li>\n<li>An enum of one form cannot be allocated automatically to another type of enum.</li>\n<li>Enum values are fixed</li>\n</ul>\n<p><strong>Enums are of two types in C#</strong></p>\n<p><strong>Simple Enum</strong> - The members of this enum contain a single value.</p>\n<p><strong>Flags Enum</strong> - The members of this enum contain multiple values or multiple values combined using a bitwise OR operator. These enums are often used for bitwise operators.</p>\n<p>Here we will talk about the Simple Enum only.</p>\n<h2 id=\"how-to-declare-an-enum\" style=\"position:relative;\"><a href=\"#how-to-declare-an-enum\" aria-label=\"how to declare an enum permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to declare an Enum</h2>\n<p>Enum is declared by the <strong>enum</strong> keyword followed by the enum name and then its enum members. Like an example below</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk4\">enum</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Vehicle</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Car</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Bike</span><span class=\"mtk1\">=</span><span class=\"mtk7\">3</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Truck</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Taxi</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>In the above code, an enum for the Vehicle is created. The enum values are started from <code>0</code> by default if we do not assign them the values and incremented by 1 for the next enum member. </p>\n<p>That means the <code>Car</code> enum has the value <code>0</code> and the <code>Bike</code> enum assigned the value <code>3</code> that means the <code>Bike</code> enum now has the value <code>3</code> and the next enums are incremented by 1 means <code>Truck</code> and <code>Taxi</code> enum have the value <code>4</code> and <code>5</code> respectively.</p>\n<p>By default, the type for enum elements is <strong>int</strong>. We can set different type by adding a colon like an example below. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk4\">enum</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">: </span><span class=\"mtk4\">byte</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Car</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Bike</span><span class=\"mtk1\">=</span><span class=\"mtk7\">3</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Truck</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Taxi</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The different types which can be set are sbyte, byte, short, ushort, uint, ulong, and long.</p>\n<h2 id=\"get-the-value-of-an-enum\" style=\"position:relative;\"><a href=\"#get-the-value-of-an-enum\" aria-label=\"get the value of an enum permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Get the value of an Enum</h2>\n<p>To get the value of enum we can simply typecast it to its type. In the first example, the default type is int so we have to typecast it to int. Also, we can get the string value of that enum by using the <code>ToString()</code> method as below.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">((</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)</span><span class=\"mtk12\">VehicleEnum</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Car</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">string</span><span class=\"mtk1\"> </span><span class=\"mtk12\">vehicle</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">Vehicle</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Bike</span><span class=\"mtk1\">.</span><span class=\"mtk11\">ToString</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">vehicle</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Output: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">0</span>\n<span class=\"grvsc-line\">Bike</span></code></pre>\n<h2 id=\"parse-the-string-value-into-an-enum\" style=\"position:relative;\"><a href=\"#parse-the-string-value-into-an-enum\" aria-label=\"parse the string value into an enum permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parse the string value into an Enum</h2>\n<p>For parsing the string value into enum we have 2 methods</p>\n<ol>\n<li><em>Enum.Parse(Type enumType,string value)</em> - This method directly parses the string representation of the name or numeric value of enum member into enumType object. If the string representation of the name is not found, then it will give the exception.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Parse</span><span class=\"mtk1\">(</span><span class=\"mtk4\">typeof</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">),</span><span class=\"mtk8\">&quot;Car&quot;</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>Output:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Car</span></code></pre>\n<ol start=\"2\">\n<li><em>Enum.TryParse(string? value,out enumType result)</em> - This method gives the result in bool value. if the string representation of the name or numeric value of enum member into enumType object is parsed, then the result will be true, and the parsed value will be in the <code>out</code> variable. If the string value is not parsed, then the result will be false.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">TryParse</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;0&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk4\">out</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">value</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Output:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Car</span></code></pre>\n<p><strong>Note</strong> - Both the methods also have overload methods.</p>\n<h2 id=\"check-if-a-string-value-is-defined-in-the-enum\" style=\"position:relative;\"><a href=\"#check-if-a-string-value-is-defined-in-the-enum\" aria-label=\"check if a string value is defined in the enum permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Check if a string value is defined in the Enum</h2>\n<p>We can check if a given integral value, or its name as a string, exists in a specified enum.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">IsDefined</span><span class=\"mtk1\">(</span><span class=\"mtk4\">typeof</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">), </span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>OR</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">IsDefined</span><span class=\"mtk1\">(</span><span class=\"mtk4\">typeof</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">), </span><span class=\"mtk8\">&quot;car&quot;</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>Output:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">True</span></code></pre>\n<h2 id=\"loop-through-all-the-enum\" style=\"position:relative;\"><a href=\"#loop-through-all-the-enum\" aria-label=\"loop through all the enum permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Loop through all the Enum</h2>\n<p>For looping through the enums you can write the below code -</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">foreach</span><span class=\"mtk1\"> (</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk15\">in</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">GetNames</span><span class=\"mtk1\">(</span><span class=\"mtk4\">typeof</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">)))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">+</span><span class=\"mtk8\">&quot; - &quot;</span><span class=\"mtk1\">+ (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)</span><span class=\"mtk12\">Enum</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Parse</span><span class=\"mtk1\">(</span><span class=\"mtk4\">typeof</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">), </span><span class=\"mtk12\">data</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Here <em>Enum.GetNames(Type enumType)</em> method is used, which retrieves an array of the names from the specified enum.</p>\n<p>Output:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Car - 0</span>\n<span class=\"grvsc-line\">Bike - 3</span>\n<span class=\"grvsc-line\">Truck - 4</span>\n<span class=\"grvsc-line\">Taxi - 5</span></code></pre>\n<h2 id=\"call-an-enum-by-the-integral-value\" style=\"position:relative;\"><a href=\"#call-an-enum-by-the-integral-value\" aria-label=\"call an enum by the integral value permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Call an enum by the integral value</h2>\n<p>We can call the enum member by its integral value. If there is no corresponding value related to that integral value, then it will print that integral value.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">((</span><span class=\"mtk10\">Vehicle</span><span class=\"mtk1\">)</span><span class=\"mtk7\">3</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Output</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Bike</span></code></pre>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>The advantages of using enums are that they are very easy to use and represented as strings but processed as integers. Enums are easy to maintain and improve code readability because they provide symbolic named constants, which means you need to remember the names, not the integer values.</p>\n<p>If you want to learn more about C programming, here is another article written on C# <a href=\"https://www.loginradius.com/blog/engineering/exception-handling-in-csharp/\">Exceptions and Exception Handling in C#</a> I hope you learn something new today and will going to try it out, if you have any questions feel free to drop a comment below.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"December 18, 2020","updated_date":null,"description":"Would you like to become more proficient in your C# programming in the use of enums? To learn the basics and use cases for Enum in C#, read this post.","title":"How to Use Enum in C#","tags":["C#","Enum"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4730f4a49850d621c2969f5405e589e1/58556/coverimage.webp","srcSet":"/static/4730f4a49850d621c2969f5405e589e1/61e93/coverimage.webp 200w,\n/static/4730f4a49850d621c2969f5405e589e1/1f5c5/coverimage.webp 400w,\n/static/4730f4a49850d621c2969f5405e589e1/58556/coverimage.webp 800w,\n/static/4730f4a49850d621c2969f5405e589e1/210c1/coverimage.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Hemant Manwani","github":"hemant404","avatar":null}}}},{"node":{"excerpt":"The goal of this post is to learn about the various ways of data migration in MongoDB that can help us to write scripts that change your…","fields":{"slug":"/engineering/live-data-migration-mongodb/"},"html":"<p>The goal of this post is to learn about the various ways of data migration in MongoDB that can help us to write scripts that change your database by adding new documents, modifying existing ones.</p>\n<p>If you're coming here for the first time, please take a look at the prequel <a href=\"https://www.loginradius.com/blog/engineering/self-hosted-mongo/\">Self-Hosted MongoDB</a>.</p>\n<p>Alright then, picking from where we left off, let's get started with the data migration in MongoDB.</p>\n<p>Now, the basic steps to migrate data from one MongoDB to another would be:</p>\n<ol>\n<li>Create a zipped backup of the existing data</li>\n<li>Dump the data in a new DB</li>\n</ol>\n<p>This is very straight forward when the source database is not online because we know that there won't be any new documents created/updated during the migration process.\nLet's look at simple migration first before diving into the live scenario.</p>\n<hr />\n<h1 id=\"migrating-from-an-offline-database-in-mongodb\" style=\"position:relative;\"><a href=\"#migrating-from-an-offline-database-in-mongodb\" aria-label=\"migrating from an offline database in mongodb permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Migrating from an offline database in MongoDB</h1>\n<h2 id=\"creating-a-backup\" style=\"position:relative;\"><a href=\"#creating-a-backup\" aria-label=\"creating a backup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a backup</h2>\n<p>We're going to use an existing utility program <a href=\"https://docs.mongodb.com/database-tools/mongodump/\">mongodump</a> for creating the database backup.</p>\n<p>Run this command in the source database server</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mongodump --host=&quot;hostname:port&quot; \\</span>\n<span class=\"grvsc-line\">  --username=&quot;username&quot; --password=&quot;password&quot; \\</span>\n<span class=\"grvsc-line\">  --authenticationDatabase &quot;admin&quot; \\</span>\n<span class=\"grvsc-line\">  --db=&quot;db name&quot; --collection=&quot;collection name&quot; --query=&#39;json&#39; \\</span>\n<span class=\"grvsc-line\">  --forceTableScan -v --gzip --out ./dump</span></code></pre>\n<p><strong><code>--host</code></strong>: The source MongoDB hostname along with the port. It defaults to <code>localhost:27017</code>. If it is a connection string you can use this option <code>—-uri=\"mongodb://username:password@host1[:port1]...\"</code></p>\n<p><strong><code>--username</code></strong>: Specifies a username to authenticate to a MongoDB database that uses authentication.</p>\n<p><strong><code>--password</code></strong>: Specifies a password to authenticate to a MongoDB database that uses authentication.</p>\n<p><strong><code>--authenticationDatabase</code></strong>: Specifies the authentication database where the specified <code>--username</code> has been created.</p>\n<blockquote>\n<p>If you do not specify an authentication database or a database to export, mongodump assumes the admin database holds the user's credentials.</p>\n</blockquote>\n<p><strong><code>--db</code></strong>: Specifies the database to take a backup from. If you do not specify a database, mongodump collects from all databases in this instance.</p>\n<blockquote>\n<p>Alternatively, you can also specify the database directly in the <a href=\"https://docs.mongodb.com/database-tools/mongodump/#cmdoption-mongodump-uri\">URI connection string</a> i.e. <code>mongodb://username:password@uri/dbname</code>. <br /> Providing a connection string while also using <code>--db</code> and specifying conflicting information <strong>will result in an error</strong>.</p>\n</blockquote>\n<p><strong><code>--collection</code></strong>: Specifies a collection to backup. If you do not specify a collection, this option copies all collections in the specified database or instance to the dump files.</p>\n<p><strong><code>--query</code></strong> : Provides a <a href=\"https://docs.mongodb.com/manual/reference/glossary/#term-json-document\">JSON document</a> as a query that optionally limits the documents included in the output of mongodump. <br />\nYou must enclose the query document in single quotes <code>('{ ... }')</code> to ensure that it does not interact with your  environment.<br />\nThe query must be in <a href=\"https://docs.mongodb.com/manual/reference/mongodb-extended-json\">Extended JSON v2 format (either relaxed or canonical/strict mode)</a>, including enclosing the field names and operators in quotes e.g. <code>'{ \"created_at\": { \"\\$gte\": ISODate(...) } }'</code>.</p>\n<blockquote>\n<p>To use the <code>--query</code> option, you must also specify the <a href=\"https://docs.mongodb.com/database-tools/mongodump/#cmdoption-mongodump-collection\"><code>--collection</code></a> option.</p>\n</blockquote>\n<p><strong><code>--forceTableScan</code></strong>: Forces mongodump to scan the data store directly. Typically, mongodump saves entries as they appear in the index of the <code>_id</code> field. <br /></p>\n<blockquote>\n<p>If you specify a query <code>--query</code>, mongodump will use the most appropriate index to support that query. <br /><strong>Hence , you cannot use <a href=\"https://docs.mongodb.com/database-tools/mongodump/#cmdoption-mongodump-forcetablescan\"><code>--forceTableScan</code></a> with the <a href=\"https://docs.mongodb.com/database-tools/mongodump/#cmdoption-mongodump-query\"><code>--query</code></a> option</strong>.</p>\n</blockquote>\n<p><strong><code>--gzip</code></strong>: Compresses the output. If mongodump outputs to the dump directory, the new feature compresses the individual files. The files have the suffix <code>.gz</code>.</p>\n<p><strong><code>--out</code></strong>: Specifies the directory where mongodump will write <a href=\"https://docs.mongodb.com/manual/reference/glossary/#term-bson\"><code>BSON</code></a> files for the dumped databases. By default, mongodump saves output files in a directory named dump in the current working directory.</p>\n<h2 id=\"restoring-the-backup\" style=\"position:relative;\"><a href=\"#restoring-the-backup\" aria-label=\"restoring the backup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Restoring the backup</h2>\n<p>We will use a utility program called <a href=\"https://docs.mongodb.com/database-tools/mongorestore/\"><code>mongorestore</code></a> for restoring the database backup.</p>\n<p>Copy the backup directory dump to the new Database instance and run the following command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mongorestore --uri=&quot;mongodb://user:password@host:port/?authSource=admin&quot; \\</span>\n<span class=\"grvsc-line\">  --drop --noIndexRestore --gzip -v ./dump</span></code></pre>\n<p>Replace the credentials with the new database credentials. Unline in the previous step, the <code>--authenticationDatabase</code> option is specified in the URI string.</p>\n<p>Also, use <code>--gzip</code> if used while creating the backup.</p>\n<p><strong><code>--drop</code></strong>: Before restoring the collections from the dumped backup, drops the collections from the target database. It does not drop collections that are not in the backup.\n<strong><code>--noIndexRestore</code></strong>: Prevents mongorestore from restoring and building indexes as specified in the corresponding mongodump output.</p>\n<blockquote>\n<p>If you want to change name of the database while restoring, you can do so using <br /><code>--nsFrom=\"old_name.*\" --nsTo=\"new_name.*\"</code> options.<br /><br />However, it won’t work if you were to migrate with <code>oplogs</code> which is a requirement in migration from an online instance.</p>\n</blockquote>\n<hr />\n<h1 id=\"migrating-from-an-online-database-in-mongodb\" style=\"position:relative;\"><a href=\"#migrating-from-an-online-database-in-mongodb\" aria-label=\"migrating from an online database in mongodb permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Migrating from an online database in MongoDB</h1>\n<p>The only challenge with migrating from an online database is not able to pause the updates during migration. So here is the overview of the steps,</p>\n<ol>\n<li>Run an initial bulk migration with <code>oplogs</code> capture</li>\n<li>Run a sync job to mitigate the database connection switch latency</li>\n</ol>\n<blockquote>\n<p>Now, to capture <code>oplogs</code>, a replica set must be initialized in the source and destination databases. This is because the <code>oplogs</code> are captured from <strong><code>local.oplog.rs</code></strong> namespace, which is created after initializing a replica set. <br /><br />You can follow <a href=\"https://medium.com/swlh/self-hosted-mongodb-deployment-7f1b6fb4973f#1cdf\">this guide</a> to configure a replica set.</p>\n</blockquote>\n<h2 id=\"initial-migration-with-oplog-capture\" style=\"position:relative;\"><a href=\"#initial-migration-with-oplog-capture\" aria-label=\"initial migration with oplog capture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Initial Migration with Oplog Capture</h2>\n<p>Oplogs, in simple words, are the operation logs created per operation in the database. They represent a partial document state or, in other words, the database state. So we are going to capture any updates in our old database during the migration process using these <code>oplogs</code>.</p>\n<p>Run the mongodump program with the following options,</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mongodump --uri=&quot;.../?authSource=admin&quot; \\</span>\n<span class=\"grvsc-line\">  --forceTableScan --oplog \\</span>\n<span class=\"grvsc-line\">  --gzip -v --out ./dump</span></code></pre>\n<p><strong><code>--oplog</code></strong>: Creates a file named <code>oplog.bson</code> as part of the <code>mongodump</code> output. The <code>oplog.bson</code> file, located in the top level of the output directory, contains <code>oplog</code> entries that occur during the mongodump operation. This file provides an effective point-in-time snapshot of the state of our database instance.</p>\n<h2 id=\"restore-the-data-with-oplog-replay\" style=\"position:relative;\"><a href=\"#restore-the-data-with-oplog-replay\" aria-label=\"restore the data with oplog replay permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Restore the data with oplog replay</h2>\n<p>In order to replay the oplogs, a special role is required. Let's create and assign the role to the database user being used for migration.</p>\n<h3 id=\"create-the-role\" style=\"position:relative;\"><a href=\"#create-the-role\" aria-label=\"create the role permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create the role</h3>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">db.createRole({</span>\n<span class=\"grvsc-line\">  role: &quot;interalUseOnlyOplogRestore&quot;,</span>\n<span class=\"grvsc-line\">  privileges: [</span>\n<span class=\"grvsc-line\">    {</span>\n<span class=\"grvsc-line\">      resource: { anyResource: true },</span>\n<span class=\"grvsc-line\">      actions: [ &quot;anyAction&quot; ] </span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">  ],</span>\n<span class=\"grvsc-line\">  roles: []</span>\n<span class=\"grvsc-line\">})</span></code></pre>\n<h3 id=\"assign-the-role\" style=\"position:relative;\"><a href=\"#assign-the-role\" aria-label=\"assign the role permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Assign the role</h3>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">db.grantRolesToUser(</span>\n<span class=\"grvsc-line\">  &quot;admin&quot;,</span>\n<span class=\"grvsc-line\">  [{ role:&quot;interalUseOnlyOplogRestore&quot;, db:&quot;admin&quot; }]</span>\n<span class=\"grvsc-line\">);</span></code></pre>\n<p>Now you can restore using the mongorestore program with the following options,</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mongorestore --uri=&quot;mongodb://admin:.../?authSource=admin&quot; \\</span>\n<span class=\"grvsc-line\">  --oplogReplay </span>\n<span class=\"grvsc-line\">  --gzip -v ./dump</span></code></pre>\n<p>In the above command, using the same user <strong><code>admin</code></strong> with whom the role was associated.</p>\n<p><strong><code>--oplogReplay</code></strong>: After restoring the database dump, replays the oplog entries from a bson file and restores the database to the point-in-time backup captured with the mongodump <code>--oplog</code> command.</p>\n<h2 id=\"mitigating-database-connection-switch-latency\" style=\"position:relative;\"><a href=\"#mitigating-database-connection-switch-latency\" aria-label=\"mitigating database connection switch latency permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Mitigating database connection switch latency</h2>\n<p>Alright, so far we are done with most of the heavy lifting. The only thing that remains is maintaining consistency between the databases during the connection switch in our application servers.</p>\n<blockquote>\n<p>If you're running MongoDB version 3.6+, it's better to go for the Change Stream approach, which is a event-based mechanism introduced to capture changes in your database in an optimized way. Here is an article that covers it : <a href=\"https://www.mongodb.com/blog/post/an-introduction-to-change-streams\">An Introduction to Change Streams</a></p>\n</blockquote>\n<p>Check out the <a href=\"https://gist.github.com/cnp96/7be1756f7eb76ea78c9b832966e84dbf#file-delta-sync-sh\">generic sync script</a>, which you can run as a CRON job every minute.</p>\n<p>Update the variables in this script and run as</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">$ ./delta-sync.sh from_epoch_in_milliseconds</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"># from_epoch_in_milliseconds is automatically picked with every iteration if not supplied</span></code></pre>\n<p>Or you can set up a cron job to run this every minute.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">* * * * * ~/delta-sync.sh</span></code></pre>\n<p>The output can be monitored with the following command (I'm running RHEL 8, refer to your OS guide for cron output)</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">$ tail -f /var/log/cron | grep CRON</span></code></pre>\n<p>This is a sample sync log.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">CMD (~/cron/dsync.sh)</span>\n<span class=\"grvsc-line\">CMDOUT (INFO: Updated log registry to use new timestamp on next run.)</span>\n<span class=\"grvsc-line\">CMDOUT (INFO: Created sync directory: /home/ec2-user/cron/dump/2020-11-03T19:01:01Z)</span>\n<span class=\"grvsc-line\">CMDOUT (Fetching oplog in range [2020-11-03T19:00:01Z - 2020-11-03T19:01:01Z])</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:02.319+0000#011dumping up to 1 collections in parallel)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:02.334+0000#011writing local.oplog.rs to /home/ec2-user/cron/dump/2020-11-03T19:01:01Z/local/oplog.rs.bson.gz)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:04.943+0000#011local.oplog.rs  0)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:04.964+0000#011local.oplog.rs  0)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:04.964+0000#011done dumping local.oplog.rs (0 documents))</span>\n<span class=\"grvsc-line\">CMDOUT (INFO: Dump success!)</span>\n<span class=\"grvsc-line\">CMDOUT (INFO: Replaying oplogs...)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.030+0000#011using write concern: &{majority false 0})</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.054+0000#011will listen for SIGTERM, SIGINT, and SIGKILL)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011connected to node type: standalone)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011mongorestore target is a directory, not a file)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011preparing collections to restore from)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011found collection local.oplog.rs bson to restore to local.oplog.rs)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011found collection metadata from local.oplog.rs to restore to local.oplog.rs)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011restoring up to 4 collections in parallel)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011replaying oplog)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#011applied 0 oplog entries)</span>\n<span class=\"grvsc-line\">CMDOUT (2020-11-03T19:01:05.055+0000#0110 document(s) restored successfully. 0 document(s) failed to restore.)</span>\n<span class=\"grvsc-line\">CMDOUT (INFO: Restore success!)</span></code></pre>\n<p>You can stop this script after verifying that no more <code>oplogs</code> are being created, i.e., when source DB went offline.</p>\n<p>This concludes the complete self-hosted MongoDB data migration guide. If you want to learn more about MongoDB here is a useful resource on <a href=\"https://www.loginradius.com/blog/engineering/mongodb-as-datasource-in-golang/\">how to use MongoDB as datasource in goLang</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"December 14, 2020","updated_date":null,"description":"This article covers the guide to migrate data from offline or live MongoDB instance using oplog replay alongside mitigate connection switch latency with existing utilities.","title":"How to Migrate Data In MongoDB","tags":["MongoDB"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.4184397163120568,"src":"/static/358a76df2469bd65a47d7ec0a70675d7/58556/index.webp","srcSet":"/static/358a76df2469bd65a47d7ec0a70675d7/61e93/index.webp 200w,\n/static/358a76df2469bd65a47d7ec0a70675d7/1f5c5/index.webp 400w,\n/static/358a76df2469bd65a47d7ec0a70675d7/58556/index.webp 800w,\n/static/358a76df2469bd65a47d7ec0a70675d7/e30b5/index.webp 1000w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Chinmaya Pati","github":"cnp96","avatar":null}}}},{"node":{"excerpt":"This guide uses LoginRadius API for authenticating React apps. It provides React developers with a more straightforward way to add user…","fields":{"slug":"/engineering/user-authentication-react-application/"},"html":"<p>This guide uses LoginRadius API for authenticating React apps. It provides React developers with a more straightforward way to add user authentication to react apps. To handle a lot of authentication implementation information, LoginRadius offers a high-level API. Using security best practices, now you can protect your response apps while writing less code.</p>\n<p>This article <a href=\"/react-hooks-guide/\">focuses on helping developers</a> learn how to integrate user authentication in the React application. Practice the following security principles to improve authentication on React applications:</p>\n<ul>\n<li>Add user login and user login.</li>\n<li>User information retrieval.</li>\n<li>Attach a tab for sign-up.</li>\n</ul>\n<p>In the React application, we can <a href=\"/react-context-api/\">easily and quickly</a> add authentication by using LoginRadius. If you already have a customized login/registration page ready, then I'll guide you to the next step of adding authentication in react apps.</p>\n<h2 id=\"configure-loginradius-for-react-application\" style=\"position:relative;\"><a href=\"#configure-loginradius-for-react-application\" aria-label=\"configure loginradius for react application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Configure LoginRadius for React Application</h2>\n<p>A new application was created for you when you <a href=\"https://accounts.loginradius.com/auth.aspx?action=register&#x26;return_url=https://dashboard.loginradius.com/login\">signed up</a> for LoginRadius. From here, you get some essential information.</p>\n<ol>\n<li>API Key  <a href=\"https://www.loginradius.com/developers/\">How to get API Key?</a></li>\n<li>Sott  <a href=\"https://www.loginradius.com/developers/\">Work with Sott</a></li>\n</ol>\n<h2 id=\"add-following-loginradius-js-library-into-your-application\" style=\"position:relative;\"><a href=\"#add-following-loginradius-js-library-into-your-application\" aria-label=\"add following loginradius js library into your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add following LoginRadius JS library into your application</h2>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&lt;script type=&quot;text/javascript&quot; src=&quot;https://auth.lrcontent.com/v2/LoginRadiusV2.js&quot;&gt;&lt;/script&gt;</span></code></pre>\n<h2 id=\"add-authentication-when-you-have-customized-login-page\" style=\"position:relative;\"><a href=\"#add-authentication-when-you-have-customized-login-page\" aria-label=\"add authentication when you have customized login page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add Authentication when you have customized Login Page</h2>\n<h3 id=\"add-login-to-your-react-application\" style=\"position:relative;\"><a href=\"#add-login-to-your-react-application\" aria-label=\"add login to your react application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add Login to your react application</h3>\n<p>We will use an API framework to call LoginRadius APIs for authentication.  Create a new file <strong>LoginPage.js</strong>, and add the following code.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">import</span><span class=\"mtk1\">  </span><span class=\"mtk12\">React</span><span class=\"mtk1\">, { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;react&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">apiKey:</span><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;*************************&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//LoginRadius API key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk12\">LoginRadiusV2</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\">  </span><span class=\"mtk10\">window</span><span class=\"mtk1\">.</span><span class=\"mtk10\">LoginRadiusV2</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk11\">LoginButton</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk11\">loginButtonHandler</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">login</span><span class=\"mtk1\">({</span><span class=\"mtk12\">emailid:</span><span class=\"mtk1\">  </span><span class=\"mtk12\">emailValue</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">password:</span><span class=\"mtk1\">  </span><span class=\"mtk12\">passwordValue</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      (</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk3\">//Here you will get the access Token of </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      (</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">emailValue</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateEmailValue</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">passwordValue</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updatePasswordValue</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\">  </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">emailValue</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span><span class=\"mtk11\">updateEmailValue</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)}</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk4\">}</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\">  </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">passwordValue</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span><span class=\"mtk11\">updatePasswordValue</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)}</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">  </span><span class=\"mtk11\">loginButtonHandler</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Log In</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">export</span><span class=\"mtk1\">  </span><span class=\"mtk15\">default</span><span class=\"mtk1\">  </span><span class=\"mtk12\">LoginButton</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>In the above code, you will see the <code>lrConfig</code> object, which has apikey that you will get from the LoginRadius account. After calling <code>loginradius.api.login</code>, you will get the response in which you will get the access Token. Through this access token, you can get the user profile.</p>\n<h3 id=\"add-logout-to-your-react-application\" style=\"position:relative;\"><a href=\"#add-logout-to-your-react-application\" aria-label=\"add logout to your react application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add Logout to your react application</h3>\n<p>Create <strong>LogoutPage.js</strong> file and add following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">React</span><span class=\"mtk1\">, { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;react&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">apiKey:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;*************************&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//LoginRadius API key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk12\">LoginRadiusV2</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">window</span><span class=\"mtk1\">.</span><span class=\"mtk10\">LoginRadiusV2</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">LogoutButton</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">token</span><span class=\"mtk1\">  = </span><span class=\"mtk8\">&#39;************&#39;</span><span class=\"mtk1\">; </span><span class=\"mtk3\">// Access Token that you got after login</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">logoutButtonHandler</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">//Note: Call invalidate token api to invalidate the token.**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">invalidateToken</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">               </span><span class=\"mtk12\">token</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">               (</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">           </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">           },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">               (</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                 </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">               }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk11\">logoutButtonHandler</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Logout</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">LogoutButton</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>In the above code, we have called invalidated token api, which expires your access token.</p>\n<h3 id=\"add-signup-to-your-react-application\" style=\"position:relative;\"><a href=\"#add-signup-to-your-react-application\" aria-label=\"add signup to your react application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Add Signup to your react application</h3>\n<p>Create <strong>SignupPage.js</strong> file and add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">import</span><span class=\"mtk1\">  </span><span class=\"mtk12\">React</span><span class=\"mtk1\">, { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;react&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">apiKey:</span><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;*************************&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//LoginRadius API key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">sott:</span><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;***************************&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk3\">//Secure Token for signup functionality</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk12\">LoginRadiusV2</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\">  </span><span class=\"mtk10\">window</span><span class=\"mtk1\">.</span><span class=\"mtk10\">LoginRadiusV2</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">init</span><span class=\"mtk1\">(</span><span class=\"mtk12\">lrconfig</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk11\">SignupButton</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\">  </span><span class=\"mtk11\">signupButtonHandler</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">loginradius</span><span class=\"mtk1\">.</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">registration</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">email:</span><span class=\"mtk1\"> [{ </span><span class=\"mtk12\">type:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Primary&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">value:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">emailValue</span><span class=\"mtk1\"> }],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">password:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">passwordValue</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      (</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk3\">//Here you will get the response after registration</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">successResponse</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      (</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">errors</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">emailValue</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateEmailValue</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">passwordValue</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updatePasswordValue</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\">  </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">emailValue</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span><span class=\"mtk11\">updateEmailValue</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)}</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk4\">}</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\">  </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">  </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">passwordValue</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span><span class=\"mtk11\">updatePasswordValue</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)}</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk4\">}</span><span class=\"mtk1\">  </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\">  </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">  </span><span class=\"mtk11\">signupButtonHandler</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Log In</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">React.Fragment</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">export</span><span class=\"mtk1\">  </span><span class=\"mtk15\">default</span><span class=\"mtk1\">  </span><span class=\"mtk12\">SignupButton</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>In the above code, You will get a success/error response after calling the registration api.</p>\n<h2 id=\"wrap-up\" style=\"position:relative;\"><a href=\"#wrap-up\" aria-label=\"wrap up permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrap up</h2>\n<p>The most common authentication use case for a React application gets covered in this tutorial: quick login and logout. However, LoginRadius is an expandable and versatile platform that can help you accomplish much more. In this guide, We have used the LoginRadius API Framework. If you want to incorporate our hosted page into your application, follow this <a href=\"https://www.loginradius.com/developers/\">documentation</a>.</p>\n<p>Let me know what you think of this tutorial in the comments below. Thanks for reading :)</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk17 { color: #808080; }\n</style>","frontmatter":{"date":"December 10, 2020","updated_date":null,"description":"This article focuses on helping developers learn how to integrate user authentication in React applications and determine the basic principles of authentication with React.","title":"A Guide To React User Authentication with LoginRadius","tags":["Authentication","LoginRadius","React"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/a877f5fa04ac6dd24b63bb101cc8302d/58556/authentication-main.webp","srcSet":"/static/a877f5fa04ac6dd24b63bb101cc8302d/61e93/authentication-main.webp 200w,\n/static/a877f5fa04ac6dd24b63bb101cc8302d/1f5c5/authentication-main.webp 400w,\n/static/a877f5fa04ac6dd24b63bb101cc8302d/58556/authentication-main.webp 800w,\n/static/a877f5fa04ac6dd24b63bb101cc8302d/99238/authentication-main.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Versha Gupta","github":"vershagupta","avatar":null}}}},{"node":{"excerpt":"Web authentication or WebAuthn is a new standard for authentication published by the World Wide Web Consortium and supported by the FIDO…","fields":{"slug":"/engineering/webauthn-authentication-application/"},"html":"<p>Web authentication or WebAuthn is a new standard for authentication published by the World Wide Web Consortium and supported by the <a href=\"https://fidoalliance.org/fido2/fido2-web-authentication-webauthn/\">FIDO alliance</a>. The standard works by providing a way for users to authenticate through a third-party authenticator. These authenticators can be built into the operating system software, like Windows Hello or Android biometrics, or through external authenticators, like a USB authenticator.</p>\n<p>This article will cover a high-level description of how WebAuthn works and two different ways an application can be set up to use the WebAuthn standard to authenticate users. One is through a basic registration flow where the authenticator data is stored upon registration and must be used to log in. The other is a flow where the authenticator can be used as a second-factor authentication method, prompted after a user logs in. For more information on this, resources like the <a href=\"https://www.w3.org/TR/webauthn-2/\"><code>World Wide Web Consortium documentation</code></a> can be useful.</p>\n<h2 id=\"webauthn-introduction\" style=\"position:relative;\"><a href=\"#webauthn-introduction\" aria-label=\"webauthn introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>WebAuthn Introduction</h2>\n<p>The WebAuthn authentication process involves the interaction between three entities: The relying party, which is the server that handles the credentials of the authenticator and verifies it, a web browser that should support the <a href=\"/website-authentication-protocols/\">web authentication protocol</a>, and the authenticator itself.</p>\n<p>The registration process begins when the client generates some sort of identifying information about themselves. Typically, this would be a user name or an email from the user but could be another identifier sent from the client, such as a randomly generated GUID. Using the Web Authentication APIs with JavaScript, the client can request the relying party to register the authenticator credentials.</p>\n<p><img src=\"/edf508fc06c12e6ed0eba68501a97ea2/webauthn-flow.webp\" alt=\"WebAuthn Flow\"></p>\n<p>After receiving the request from the client, the relying party generates a challenge based on the options provided by the client. The client receives the response and attempts to get the user to verify the authenticator being used. For example, with Windows Hello as the authenticator, the user can enter their PIN. After verifying the authenticator, it signs the challenge-response back with identifying details and returns it to the relying party, which validates the authenticator and registers the user.</p>\n<p>When the registration begins, options are set from the relying party that changes how the flow will work. You can find a list of the options in this document on <a href=\"https://www.w3.org/TR/webauthn/#dictionary-makecredentialoptions\">W3C</a>. Here are some examples of the significant options that one might set for their flows:</p>\n<ul>\n<li><strong>Authenticator Attachment</strong> - The authenticator being used can be set to a platform authenticator or a cross-platform authenticator. Platform authenticators are limited to the usage of a single device to authenticate. Windows Hello and the fingerprint scanner on a smartphone are examples of platform authenticators, as the user is identified through the device being used to authenticate with. Cross-platform authenticators are external devices that can be used with a device to authenticate. Things like USB authenticators are an example of cross-platform authenticators. Depending on the implementation, USB authenticators can also set up multiple platform authenticators to work on their device, but this won't be covered in this blog.</li>\n<li><strong>Resident Key Required Boolean</strong> - By default, this value is set to false, which means that private key and authentication credentials are stored on the relying party server. However, if this option is set to true, the authenticator will store the private key credentials instead. With certain flows, by setting the resident key to required, only the authenticator's ids will be stored on the relying party server. This would allow for authentication systems to validate a user via the authenticator and identify them.</li>\n<li><strong>User Verification</strong> - This field can hold three values: Preferred by default, Discouraged, or Required. User verification is when the user can be identified to be one that is attempting the authentication request. If an authenticator supports user verification, the authenticator must set a flag during validation and sent to the relying party. When the authenticator attempts verification, it can be done through different means, such as password, PIN, or biometrics.</li>\n<li><strong>Attestation</strong> - Attestation certificates have the option to be created through this option. As a result, the certificate will contain details about the hardware being used as an authenticator and ensure that the device used for authentication is trustworthy. If the authentication flow does not require this, you can set it to None to reduce the workload done by the relying party to validate the attestation certificate. By setting the option to Indirect, the relying party allows the attestation certificate to be generated by a third party. This could allow the relying party to receive less private information surrounding the actual authenticator and use only what is needed. Lastly, if set to direct, the authenticator itself must generate the attestation certificate to be verified.</li>\n</ul>\n<p>The authentication or login process is similar to the registration process. Using the <a href=\"/write-a-javascript-library-using-webpack-and-babel/\">JavaScript libraries</a>, the authenticator passes identifying information to the relying party. The relying party returns a challenge, which should be validated by the user, processed by the authenticator, and finally validated by the relying party. User verification is checked from the options, but a majority of the options have been reduced as no credentials are generated or saved on either end.</p>\n<h2 id=\"setting-up-webauthn-for-your-application\" style=\"position:relative;\"><a href=\"#setting-up-webauthn-for-your-application\" aria-label=\"setting up webauthn for your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up WebAuthn for your Application</h2>\n<p>When setting up WebAuthn as an authentication method for your application, two considerations are to use the standard as a primary registration and authentication method or as a second-factor authentication method.</p>\n<p>As a primary authentication method, the authenticator identification and credentials are stored by the server at the same time the user account is created.</p>\n<p>To begin, use the Web Authentication API to initiate the flow:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">Let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">publicKeyCredentialCreationOptions</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">user:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> “</span><span class=\"mtk7\">1234</span><span class=\"mtk1\">”,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;example@example.com&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">displayName:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;example&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">authenticatorSelection:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">authenticatorAttachment:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;platform&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">attestation:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;direct&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">credential</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">navigator</span><span class=\"mtk1\">.</span><span class=\"mtk12\">credentials</span><span class=\"mtk1\">.</span><span class=\"mtk11\">create</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">publicKey:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">publicKeyCredentialCreationOptions</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>For this section, the creation options are generated by the client. In other scenarios, including this blog's example, the options are generated from the relying party by retrieving them via an API call.</p>\n<p>After the browser triggers this code, the authenticator will be prompted for validation. Since the authenticatorAttachment is set to 'platform', it would use the device's authenticator, like Windows Hello or an Android fingerprint scan.</p>\n<p>The data returned from the creation of the credentials will have a structure like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">PublicKeyCredential</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    id: </span><span class=\"mtk8\">&#39;ADSUllKQmbqdGtpu4sjseh4cg2TxSvrbcHDTBsv4NSSX9...&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    rawId: </span><span class=\"mtk10\">ArrayBuffer</span><span class=\"mtk1\">(</span><span class=\"mtk7\">59</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    response: </span><span class=\"mtk12\">AuthenticatorAttestationResponse</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        clientDataJSON: </span><span class=\"mtk10\">ArrayBuffer</span><span class=\"mtk1\">(</span><span class=\"mtk7\">121</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        attestationObject: </span><span class=\"mtk10\">ArrayBuffer</span><span class=\"mtk1\">(</span><span class=\"mtk7\">306</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    type: </span><span class=\"mtk8\">&#39;public-key&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>This object should be passed to the relying party to complete the registration. The relying party verifies that the credentials passed in are correct and stores the identifier and credentials in the data store. In addition to storing the credentials object, any other registration variables should be passed in this step to register on your data store.</p>\n<p>To use this flow as part of a second-factor authentication process, the user account should be created before initiating this process with an already existing authentication method, like a <a href=\"/password-security-best-practices-compliance/\">password system</a>. After the user account is created, running this flow should update the current user in the data store with the credential data. This will allow the second-factor authentication credentials to be configured and triggered after a password login.</p>\n<p>Most programming languages have a library built that supports WebAuthn for a relying party server. For example, Duo has created them for <a href=\"https://github.com/duo-labs/py_webauthn\"><code>Python</code></a> and <a href=\"https://github.com/duo-labs/webauthn\"><code>Go</code></a>. Using one of these libraries during the development of the relying party server will simplify the process. These resources also provide demos on how to implement their libraries to handle the credential data generated by the JavaScript Web Authentication APIs.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Although the usage of WebAuthn is not widespread at the moment, the potential to <a href=\"https://www.loginradius.com/blog/identity/2019/10/passwordless-authentication-the-future-of-identity-and-security/\">authenticate a user passwordless</a> or with the extra security of an authenticator allows it to be a strong contender in the future over regular password authentication flows. Hopefully, this blog helps you get started on your authentication apps with WebAuthn.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"December 09, 2020","updated_date":null,"description":"Web authentication, or WebAuthn in short. A go-to guide for developers to learn more about WebAuthn API, and how to set it up in their services..","title":"WebAuthn: A Guide To Authenticate Your Application","tags":["WebAuthn","FIDO","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/23998a17044eadfc099cb67908b28ac8/58556/webauthn-logo.webp","srcSet":"/static/23998a17044eadfc099cb67908b28ac8/61e93/webauthn-logo.webp 200w,\n/static/23998a17044eadfc099cb67908b28ac8/1f5c5/webauthn-logo.webp 400w,\n/static/23998a17044eadfc099cb67908b28ac8/58556/webauthn-logo.webp 800w,\n/static/23998a17044eadfc099cb67908b28ac8/99238/webauthn-logo.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Chris Yee","github":null,"avatar":null}}}},{"node":{"excerpt":"Let's walk through how to build and push Docker images programmatically using Go. To do this, we need to talk to the Docker daemon via the…","fields":{"slug":"/engineering/build-push-docker-images-golang/"},"html":"<p>Let's walk through how to build and push Docker images programmatically using Go. To do this, we need to talk to the Docker daemon via the <a href=\"https://docs.docker.com/engine/api/\">Docker Engine API</a>. This is similar to how the Docker CLI works, but instead of entering commands through a CLI, we'll be writing code with Docker's Go SDK.</p>\n<p>At the time of writing, the official Docker Go SDK <a href=\"https://docs.docker.com/engine/api/sdk/examples/\">docs</a> provide great examples of running basic Docker commands with Go. However, it's missing examples on building and pushing Docker images, so we'll go over those in this blog.</p>\n<p>Before we begin, this blog assumes you have a working knowledge of Docker and Go. We'll go over the following:</p>\n<ul>\n<li>Building an image from local source code</li>\n<li>Pushing an image to a remote registry</li>\n</ul>\n<h2 id=\"environment-setup\" style=\"position:relative;\"><a href=\"#environment-setup\" aria-label=\"environment setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Environment Setup</h2>\n<p>First, we need to set up the environment. Create a project and include the app we want to containerize:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mkdir docker-go-tutorial && cd docker-go-tutorial && mkdir node-hello</span></code></pre>\n<p>We'll add a simple Node.js app:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// node-hello/app.js</span>\n<span class=\"grvsc-line\">console.log(&quot;Hello From LoginRadius&quot;);</span></code></pre>\n<p>with the Dockerfile:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// node-hello/Dockerfile</span>\n<span class=\"grvsc-line\">FROM node:12</span>\n<span class=\"grvsc-line\">WORKDIR /src</span>\n<span class=\"grvsc-line\">COPY . .</span>\n<span class=\"grvsc-line\">CMD [ &quot;node&quot;, &quot;app.js&quot; ]</span></code></pre>\n<p>Next, install the <a href=\"https://docs.docker.com/engine/api/sdk/\">Go SDK</a>. These are the Docker related imports we will be using:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&quot;github.com/docker/docker/api/types&quot;</span>\n<span class=\"grvsc-line\">&quot;github.com/docker/docker/client&quot;</span>\n<span class=\"grvsc-line\">&quot;github.com/docker/docker/pkg/archive&quot;</span></code></pre>\n<h2 id=\"build-docker-image\" style=\"position:relative;\"><a href=\"#build-docker-image\" aria-label=\"build docker image permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build Docker Image</h2>\n<p>One way to build a Docker image from our local files is to compress those files into a tar archive first.</p>\n<p>We use the archive package provided by Docker:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&quot;github.com/docker/docker/pkg/archive&quot;</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">tar, err := archive.TarWithOptions(&quot;node-hello/&quot;, &archive.TarOptions{})</span>\n<span class=\"grvsc-line\">if err != nil {</span>\n<span class=\"grvsc-line\">    return err</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>Now, we can call the ImageBuild function using the Go SDK:</p>\n<ul>\n<li>\n<p>Note that the image tag includes our Docker registry user ID, so we can push this image to our registry later.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">opts := types.ImageBuildOptions{</span>\n<span class=\"grvsc-line\">Dockerfile:  &quot;Dockerfile&quot;,</span>\n<span class=\"grvsc-line\">Tags:        []string{dockerRegistryUserID + &quot;/node-hello&quot;},</span>\n<span class=\"grvsc-line\">Remove:      true,</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\">res, err := dockerClient.ImageBuild(ctx, tar, opts)</span>\n<span class=\"grvsc-line\">if err != nil {</span>\n<span class=\"grvsc-line\">return err</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n</li>\n</ul>\n<p>To print the response, we use a scanner to go through line by line:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">scanner := bufio.NewScanner(res.Body)</span>\n<span class=\"grvsc-line\">for scanner.Scan() {</span>\n<span class=\"grvsc-line\">    lastLine = scanner.Text()</span>\n<span class=\"grvsc-line\">    fmt.Println(scanner.Text())</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>This prints the following:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 1/4 : FROM node:12&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e e4f1e16b3633\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 2/4 : WORKDIR /src&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e b298b8519669\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 3/4 : COPY . .&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e 1ff6a87e79d9\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Step 4/4 : CMD [ \\&quot;node\\&quot;, \\&quot;app.js\\&quot; ]&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e Using cache\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot; ---\\u003e 6ca44f72b68d\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;aux&quot;:{&quot;ID&quot;:&quot;sha256:238a923459uf28h80103eb089804a2ff2c1f68f8c&quot;}}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Successfully built 6ca44f72b68d\\n&quot;}</span>\n<span class=\"grvsc-line\">{&quot;stream&quot;:&quot;Successfully tagged lrblake/node-hello:latest\\n&quot;}</span></code></pre>\n<p>The last step would be checking the response for errors, so if something went wrong during the build, we could handle it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">errLine := &ErrorLine{}</span>\n<span class=\"grvsc-line\">json.Unmarshal([]byte(lastLine), errLine)</span>\n<span class=\"grvsc-line\">if errLine.Error != &quot;&quot; {</span>\n<span class=\"grvsc-line\">    return errors.New(errLine.Error)</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>For example, the following error can occur during build:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{&quot;errorDetail&quot;:{&quot;message&quot;:&quot;COPY failed: stat /var/lib/docker/tmp/docker-builder887191115/z: no such file or directory&quot;},&quot;error&quot;:&quot;COPY failed: stat /var/lib/docker/tmp/docker-builder887191115/z: no such file or directory&quot;}</span></code></pre>\n<p>All together, the file looks like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"go\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">package</span><span class=\"mtk1\"> main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;bufio&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;context&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;encoding/json&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;errors&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;io&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;time&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/api/types&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/client&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/docker/docker/pkg/archive&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dockerRegistryUserID</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ErrorLine</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tError       </span><span class=\"mtk10\">string</span><span class=\"mtk1\">      </span><span class=\"mtk8\">`json:&quot;error&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tErrorDetail ErrorDetail </span><span class=\"mtk8\">`json:&quot;errorDetail&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ErrorDetail</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tMessage </span><span class=\"mtk10\">string</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`json:&quot;message&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">cli</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := client.</span><span class=\"mtk11\">NewClientWithOpts</span><span class=\"mtk1\">(client.FromEnv, client.</span><span class=\"mtk11\">WithAPIVersionNegotiation</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err.</span><span class=\"mtk11\">Error</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">imageBuild</span><span class=\"mtk1\">(cli)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(err.</span><span class=\"mtk11\">Error</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">imageBuild</span><span class=\"mtk1\">(dockerClient *client.Client) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">cancel</span><span class=\"mtk1\"> := context.</span><span class=\"mtk11\">WithTimeout</span><span class=\"mtk1\">(context.</span><span class=\"mtk11\">Background</span><span class=\"mtk1\">(), time.Second*</span><span class=\"mtk7\">120</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk11\">cancel</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">tar</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := archive.</span><span class=\"mtk11\">TarWithOptions</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;node-hello/&quot;</span><span class=\"mtk1\">, &archive.TarOptions{})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">opts</span><span class=\"mtk1\"> := types.ImageBuildOptions{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tDockerfile: </span><span class=\"mtk8\">&quot;Dockerfile&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tTags:       []</span><span class=\"mtk10\">string</span><span class=\"mtk1\">{dockerRegistryUserID + </span><span class=\"mtk8\">&quot;/node-hello&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tRemove:     </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">res</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := dockerClient.</span><span class=\"mtk11\">ImageBuild</span><span class=\"mtk1\">(ctx, tar, opts)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">defer</span><span class=\"mtk1\"> res.Body.</span><span class=\"mtk11\">Close</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(res.Body)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(rd io.Reader) </span><span class=\"mtk10\">error</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lastLine</span><span class=\"mtk1\"> </span><span class=\"mtk10\">string</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">scanner</span><span class=\"mtk1\"> := bufio.</span><span class=\"mtk11\">NewScanner</span><span class=\"mtk1\">(rd)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">for</span><span class=\"mtk1\"> scanner.</span><span class=\"mtk11\">Scan</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">lastLine</span><span class=\"mtk1\"> = scanner.</span><span class=\"mtk11\">Text</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tfmt.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(scanner.</span><span class=\"mtk11\">Text</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">errLine</span><span class=\"mtk1\"> := &ErrorLine{}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tjson.</span><span class=\"mtk11\">Unmarshal</span><span class=\"mtk1\">([]</span><span class=\"mtk11\">byte</span><span class=\"mtk1\">(lastLine), errLine)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> errLine.Error != </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> errors.</span><span class=\"mtk11\">New</span><span class=\"mtk1\">(errLine.Error)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> := scanner.</span><span class=\"mtk11\">Err</span><span class=\"mtk1\">(); err != </span><span class=\"mtk4\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> err</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The equivalent Docker CLI command would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker build -t &lt;dockerRegistryUserID&gt;/node-hello .</span></code></pre>\n<h2 id=\"push-docker-image\" style=\"position:relative;\"><a href=\"#push-docker-image\" aria-label=\"push docker image permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Push Docker Image</h2>\n<p>We'll push the Docker image we created to Docker Hub. But, we need to authenticate with Docker Hub by providing credentials encoded in base64.</p>\n<ul>\n<li>In practice, don't hardcode your credentials in your source code.</li>\n<li>\n<p>If you don't want to use your Docker Hub password, you can set up an access token and provide that in the Password field instead.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">var authConfig = types.AuthConfig{</span>\n<span class=\"grvsc-line\">Username:      &quot;Your Docker Hub Username&quot;,</span>\n<span class=\"grvsc-line\">Password:      &quot;Your Docker Hub Password or Access Token&quot;,</span>\n<span class=\"grvsc-line\">ServerAddress: &quot;https://index.docker.io/v1/&quot;,</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\">authConfigBytes, _ := json.Marshal(authConfig)</span>\n<span class=\"grvsc-line\">authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)</span></code></pre>\n</li>\n</ul>\n<p>Now, call the ImagePush function in the Go SDK, along with your encoded credentials:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">opts := types.ImagePushOptions{RegistryAuth: authConfigEncoded}</span>\n<span class=\"grvsc-line\">rd, err := dockerClient.ImagePush(ctx, dockerRegistryUserID + &quot;/node-hello&quot;, opts)</span></code></pre>\n<p>Together, this looks like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">func imagePush(dockerClient *client.Client) error {</span>\n<span class=\"grvsc-line\">\tctx, cancel := context.WithTimeout(context.Background(), time.Second*120)</span>\n<span class=\"grvsc-line\">\tdefer cancel()</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\tauthConfigBytes, _ := json.Marshal(authConfig)</span>\n<span class=\"grvsc-line\">\tauthConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\ttag := dockerRegistryUserID + &quot;/node-hello&quot;</span>\n<span class=\"grvsc-line\">\topts := types.ImagePushOptions{RegistryAuth: authConfigEncoded}</span>\n<span class=\"grvsc-line\">\trd, err := dockerClient.ImagePush(ctx, tag, opts)</span>\n<span class=\"grvsc-line\">\tif err != nil {</span>\n<span class=\"grvsc-line\">\t\treturn err</span>\n<span class=\"grvsc-line\">\t}</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\tdefer rd.Close()</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\terr = print(rd)</span>\n<span class=\"grvsc-line\">\tif err != nil {</span>\n<span class=\"grvsc-line\">\t\treturn err</span>\n<span class=\"grvsc-line\">\t}</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">\treturn nil</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>The equivalent Docker CLI command (after docker login) would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker push &lt;dockerRegistryUserID&gt;/node-hello</span></code></pre>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"December 08, 2020","updated_date":null,"description":"Guide on how to build and push Docker images programmatically using Go.","title":"Build and Push Docker Images with Go","tags":["Docker","Go"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.680672268907563,"src":"/static/2f998a173a852a0b3670b1ac58fba74e/58556/cover.webp","srcSet":"/static/2f998a173a852a0b3670b1ac58fba74e/61e93/cover.webp 200w,\n/static/2f998a173a852a0b3670b1ac58fba74e/1f5c5/cover.webp 400w,\n/static/2f998a173a852a0b3670b1ac58fba74e/58556/cover.webp 800w,\n/static/2f998a173a852a0b3670b1ac58fba74e/e30b5/cover.webp 1000w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Andy Yeung","github":null,"avatar":null}}}},{"node":{"excerpt":"What is Istio? Istio is an Open Source service mesh (developed in partnership between teams from Google, IBM, and Lyft), providing a…","fields":{"slug":"/engineering/istio-service-mesh/"},"html":"<h2 id=\"what-is-istio\" style=\"position:relative;\"><a href=\"#what-is-istio\" aria-label=\"what is istio permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Istio?</h2>\n<p>Istio is an Open Source service mesh (developed in partnership between teams from Google, IBM, and Lyft), providing a dedicated infrastructure layer for creating service-to-service communication that is safe, fast, and reliable. Having such a fanatical communication layer can provide various advantages, like providing observability into communications, providing secure connections, or automating retries and backoff for failed requests.</p>\n<p>A service mesh also often has more complex operational requirements, like A/B testing, canary rollouts, rate limiting, access control, and end-to-end authentication.</p>\n<p>Istio does this by adding a sidecar proxy which intercepts all network communication between microservices, then configures and manages Istio using its control plane functionality, which incorporates:</p>\n<ol>\n<li>Granular control over the service-to-service communication and its routing with the additional functionality of retries, fault injection, circuit breakers.</li>\n<li>Providing secure mTLS without any changes in the application code.</li>\n<li>Cluster to cluster communication using ingress and egress gateways.</li>\n</ol>\n<h2 id=\"istio-architecture\" style=\"position:relative;\"><a href=\"#istio-architecture\" aria-label=\"istio architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Istio Architecture</h2>\n<p>An Istio service mesh is logically split into a data plane and a control plane.</p>\n<p>The data plane is composed of Envoy proxy deployed as sidecars. Envoy itself is an L7 proxy and communication bus designed for modern microservices-based architecture. These proxies intercept and control all network communication between microservices. They also collect and report telemetry on all mesh traffic.</p>\n<p>The control plane manages and configures the proxies to route traffic.</p>\n<p><img src=\"https://istio.io/latest/docs/ops/deployment/architecture/arch.webp\" alt=\"Istio Architecture\"></p>\n<h2 id=\"istio-core-components\" style=\"position:relative;\"><a href=\"#istio-core-components\" aria-label=\"istio core components permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Istio Core Components</h2>\n<h3 id=\"pilot\" style=\"position:relative;\"><a href=\"#pilot\" aria-label=\"pilot permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Pilot</h3>\n<p>Istio Pilot manages and configures all the Envoy proxy instances deployed. It takes the rules for traffic behavior provided by the control plane and converts them into configurations applied by Envoy.</p>\n<h3 id=\"citadel\" style=\"position:relative;\"><a href=\"#citadel\" aria-label=\"citadel permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Citadel</h3>\n<p>Responsible for controlling the authentication and identity management between services. Allow developers to build a zero-trust network based on service identity.</p>\n<h3 id=\"mixer\" style=\"position:relative;\"><a href=\"#mixer\" aria-label=\"mixer permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Mixer</h3>\n<p>Responsible for enforcing access control and usage policies across the service mesh and collects telemetry data from the Envoy proxy and other services.</p>\n<h2 id=\"istio-features\" style=\"position:relative;\"><a href=\"#istio-features\" aria-label=\"istio features permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Istio Features</h2>\n<h3 id=\"traffic-management\" style=\"position:relative;\"><a href=\"#traffic-management\" aria-label=\"traffic management permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Traffic Management</h3>\n<p>It is the basic feature of Istio, which facilitates the routing between services. Istio simplifies the configuration of service-level properties like circuit breakers, timeouts, and retries.\nAll traffic that your mesh services send and receive (data plane traffic) is proxied through Envoy, making it easy to direct and control traffic around your mesh without making any changes to your services.</p>\n<p>For discovering all the services in the ecosystem, Istio connects to the Service discovery System and populates its service registry. The Envoy sidecar proxy then uses this registry to route traffic to the correct service.</p>\n<p>Here are a few resources you can add for your deployment apart from the basic service discovery and load balancing:</p>\n<h3 id=\"virtual-services\" style=\"position:relative;\"><a href=\"#virtual-services\" aria-label=\"virtual services permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Virtual Services</h3>\n<p>Virtual services play a key role in making Istio's traffic management flexible and powerful. They do this by strongly decoupling where clients send their requests from the destination workloads that actually implement them.<br>\nSo, instead of sending requests directly to a service data plane, you send traffic through this virtual service. Using virtual service, you can route requests to different versions of the same service or different hostnames based on particular endpoints. This helps us to do various other things like A/B testing or doing canary rollouts.  </p>\n<p>A typical example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">networking.istio.io/v1alpha3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">VirtualService</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">bookinfo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">hosts</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk8\">bookinfo.com</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">http</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">match</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk4\">uri</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">prefix</span><span class=\"mtk1\">: </span><span class=\"mtk8\">/reviews</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">route</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk4\">destination</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">host</span><span class=\"mtk1\">: </span><span class=\"mtk8\">reviews  &lt;-- Resolves to reviews.&lt;namespace&gt;.svc.cluster.local</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">match</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk4\">uri</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">prefix</span><span class=\"mtk1\">: </span><span class=\"mtk8\">/ratings</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">route</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk4\">destination</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">host</span><span class=\"mtk1\">: </span><span class=\"mtk8\">ratings</span></span></code></pre>\n<h3 id=\"destination-rule\" style=\"position:relative;\"><a href=\"#destination-rule\" aria-label=\"destination rule permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Destination Rule</h3>\n<p>We use destination rules to configure what happens to traffic for that destination. Destination rules are applied after virtual service routing rules are evaluated, so they apply to the traffic's real destination.<br>\nUsing destination rules, we specify the subsets of the service using labels, which are then used by the virtual service to route requests to a particular subset. In addition to that, we can also customize traffic policy, load balancing policy, connection pool settings, mTLS, etc.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">networking.istio.io/v1alpha3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">DestinationRule</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">my-destination-rule</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">host</span><span class=\"mtk1\">: </span><span class=\"mtk8\">my-svc</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">trafficPolicy</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">loadBalancer</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">simple</span><span class=\"mtk1\">: </span><span class=\"mtk8\">RANDOM</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">subsets</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">#### This will work only if we have defined version label in the deployment</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v1</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">labels</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">version</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v1</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v2</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">labels</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">version</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v2</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">trafficPolicy</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">loadBalancer</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">simple</span><span class=\"mtk1\">: </span><span class=\"mtk8\">ROUND_ROBIN</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">labels</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">version</span><span class=\"mtk1\">: </span><span class=\"mtk8\">v3</span></span></code></pre>\n<p>Here we have defined destination rule for service <strong>my-svc</strong> and defined subsets and traffic policy global and per subset.</p>\n<h3 id=\"gateway\" style=\"position:relative;\"><a href=\"#gateway\" aria-label=\"gateway permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Gateway</h3>\n<p>It is used to manage inbound and outbound traffic for your mesh, letting you specify which traffic you want to enter or leave the mesh. Gateway configurations are applied to standalone Envoy proxies running at the edge of the mesh, rather than sidecar Envoy proxies running alongside your service workloads. Using this, we can expose our services to the internet.  </p>\n<p>A typical example would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">networking.istio.io/v1alpha3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">Gateway</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">my-svc-gateway</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">namespace</span><span class=\"mtk1\">: </span><span class=\"mtk8\">test</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">selector</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">istio</span><span class=\"mtk1\">: </span><span class=\"mtk8\">ingressgateway</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">servers</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">port</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">number</span><span class=\"mtk1\">: </span><span class=\"mtk7\">80</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">http</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">protocol</span><span class=\"mtk1\">: </span><span class=\"mtk8\">HTTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">hosts</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk8\">my-svc.example.com</span></span></code></pre>\n<p><strong>istio: ingressgateway</strong> is the gateway which is enabled by default after installation. We can create our custom gateway. Here, the hosts <strong>my-svc.example.com</strong> will resolve to the load balancer provided by the Istio by default. To use this gateway, one has to add config in the virtual service like for example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">networking.istio.io/v1alpha3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">VirtualService</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">my-svc</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">hosts</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk8\">my-svc</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk8\">my-svc.example.com   &lt;-- The host should match</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">gateways</span><span class=\"mtk1\">:               </span><span class=\"mtk8\">&lt;--- gateway config</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk8\">my-svc-gateway</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">http</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">route</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    - </span><span class=\"mtk4\">destination</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">host</span><span class=\"mtk1\">: </span><span class=\"mtk8\">my-svc.test.svc.cluster.local</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">port</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk4\">number</span><span class=\"mtk1\">: </span><span class=\"mtk7\">80</span><span class=\"mtk1\"> </span></span></code></pre>\n<h3 id=\"network-resilience\" style=\"position:relative;\"><a href=\"#network-resilience\" aria-label=\"network resilience permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Network Resilience</h3>\n<p>This feature provides network configuration dynamically at runtime, which includes retries, fault injection, circuit breakers, and timeouts.</p>\n<h3 id=\"service-entries\" style=\"position:relative;\"><a href=\"#service-entries\" aria-label=\"service entries permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Service Entries</h3>\n<p>This object is used to add an external service as part of the service mesh, including a service running in a VM or other K8s cluster in case of multi-cluster installation.</p>\n<p>A typical example would be connecting a service to a database cluster that is not part of the mesh.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">networking.istio.io/v1alpha3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">ServiceEntry</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">elasticsearch</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">namespace</span><span class=\"mtk1\">: </span><span class=\"mtk8\">test</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">hosts</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk8\">elasticsearch.elasticsearch.svc.cluster.local</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">location</span><span class=\"mtk1\">: </span><span class=\"mtk8\">MESH_INTERNAL</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">ports</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  - </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">https</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">number</span><span class=\"mtk1\">: </span><span class=\"mtk7\">9200</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">protocol</span><span class=\"mtk1\">: </span><span class=\"mtk8\">TCP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">resolution</span><span class=\"mtk1\">: </span><span class=\"mtk8\">DNS</span></span></code></pre>\n<p>The Service Entry should be in the same namespace as that of the calling service. This is helpful, especially in the case where the service is not exposed to a public endpoint and can be accessed using internal service DNS like the above example.</p>\n<h3 id=\"security\" style=\"position:relative;\"><a href=\"#security\" aria-label=\"security permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Security</h3>\n<p>Istio provides security features that will help us to establish a zero-trust network. Istio enables security by default and provides various authentication and authorization policy to regulate security.</p>\n<p>For example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"yaml\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">apiVersion</span><span class=\"mtk1\">: </span><span class=\"mtk8\">security.istio.io/v1beta1</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">kind</span><span class=\"mtk1\">: </span><span class=\"mtk8\">PeerAuthentication</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">metadata</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">name</span><span class=\"mtk1\">: </span><span class=\"mtk8\">dsl-es</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">namespace</span><span class=\"mtk1\">: </span><span class=\"mtk8\">pdp-test</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">spec</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">selector</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">matchLabels</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">app</span><span class=\"mtk1\">: </span><span class=\"mtk8\">dsl-es</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">mtls</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">mode</span><span class=\"mtk1\">: </span><span class=\"mtk8\">STRICT</span></span></code></pre>\n<p>Here we define a peer authentication object for a service labeled <strong>my-svc</strong>, which tells that any service that needs to talk to <strong>my-svc</strong> will communicate using mtls. The service will accept only TLS connection. By default, Istio enables <strong>PERMISSIVE</strong> mode, which accepts both plaintext and encrypted communication. </p>\n<p>We can define peer authentication on the mesh, namespace, and pod level.</p>\n<p>That is all for the introduction to Istio. In the next part, we will look at installing Istio and configuring services to use Istio.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"December 07, 2020","updated_date":null,"description":"This post will give a high-level introduction to Istio and its related concepts and terminologies.","title":"Istio Service Mesh: A Beginners Guide","tags":["Istio","Service Mesh"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/d8ff8c7b29395837a840c4013f351290/58556/Istio.webp","srcSet":"/static/d8ff8c7b29395837a840c4013f351290/61e93/Istio.webp 200w,\n/static/d8ff8c7b29395837a840c4013f351290/1f5c5/Istio.webp 400w,\n/static/d8ff8c7b29395837a840c4013f351290/58556/Istio.webp 800w,\n/static/d8ff8c7b29395837a840c4013f351290/210c1/Istio.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Piyush Kumar","github":"kpiyush17","avatar":null}}}}]},"markdownRemark":{"excerpt":"Introduction Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT…","fields":{"slug":"/engineering/how-to-integrate-jwt/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT, or JSON Web Tokens, a compact, stateless method for securely transmitting user identity and session data across services.</p>\n<p>With JWT token authentication, identity information is embedded in a signed token, allowing you to maintain user sessions without server-side storage. This approach is highly scalable and ideal for modern architectures like SPAs, mobile apps, and microservices.</p>\n<p>In this blog, we’ll walk you through what is JWT, why use it, and how to implement JWT authentication using LoginRadius. </p>\n<p>You’ll learn what JWT is, why it’s effective, and how it works in real-world applications. We'll cover both integration methods (IDX and Direct API), generating your signing key, managing sessions, storing the JWT token securely, and applying best practices throughout.</p>\n<p>Whether you're a developer, product manager, or IAM architect, this guide offers a complete foundation for implementing JWT token authentication into your application stack.</p>\n<h2 id=\"what-is-jwt\" style=\"position:relative;\"><a href=\"#what-is-jwt\" aria-label=\"what is jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is JWT?</h2>\n<p><a href=\"https://www.loginradius.com/blog/engineering/jwt/\">JSON Web Token (JWT)</a> is an open standard (RFC 7519) used to transmit information securely between parties as a JSON object. It’s compact, self-contained, and digitally signed, making it a reliable format for authentication and authorization across modern applications.</p>\n<p>A JWT consists of three parts:</p>\n<ol>\n<li><strong>Header –</strong> Contains metadata like the type of token and signing algorithm (e.g., HS256).</li>\n<li><strong>Payload –</strong> Stores the actual data or “claims,” such as user ID, roles, and token expiry.</li>\n<li><strong>Signature –</strong> A cryptographic hash that ensures the token hasn’t been tampered with.</li>\n</ol>\n<p><em>Example of a token structure:</em></p>\n<p>&#x3C;base64Header>.&#x3C;base64Payload>.&#x3C;signature></p>\n<h2 id=\"why-use-jwt\" style=\"position:relative;\"><a href=\"#why-use-jwt\" aria-label=\"why use jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Use JWT?</h2>\n<ul>\n<li><strong>Stateless Authentication</strong>: No server-side session storage is needed — the token holds all necessary user info. </li>\n<li><strong>Portable</strong>: Works seamlessly across domains, services, and APIs. </li>\n<li><strong>Scalable</strong>: Ideal for microservices, SPAs, mobile apps, and serverless functions. </li>\n<li><strong>Interoperable</strong>: JWTs are supported across many languages and frameworks.</li>\n</ul>\n<h2 id=\"how-jwt-works\" style=\"position:relative;\"><a href=\"#how-jwt-works\" aria-label=\"how jwt works permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How JWT Works?</h2>\n<p><img src=\"/f29edbf2978577390c7ffa02e9bc4dda/lr-JWT-authentication.webp\" alt=\"Flowchart illustrating LoginRadius JWT authentication via Identity Provider (IDP), showing user redirection from login icon to login page, authentication with IDP, JWT token validation, and subsequent redirection to the customer&#x27;s website or error page based on validation results.\"></p>\n<ol>\n<li>A user logs in with credentials. </li>\n<li>Your app (or identity provider like LoginRadius) issues a signed JWT. </li>\n<li>The client stores the token and sends it with each request (usually in the Authorization header). </li>\n<li>The server validates the token’s signature and claims. </li>\n<li>If valid, access is granted — without any session stored on the backend.</li>\n</ol>\n<p>JWT simplifies identity verification, especially when you're building apps that talk to APIs or need to scale without centralized session storage.</p>\n<h2 id=\"jwt-authentication-with-loginradius-overview\" style=\"position:relative;\"><a href=\"#jwt-authentication-with-loginradius-overview\" aria-label=\"jwt authentication with loginradius overview permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>JWT Authentication with LoginRadius: Overview</h2>\n<p>LoginRadius provides robust support for JWT (JSON Web Token) authentication, which allows for flexible and secure access control across different digital platforms. Whether you're building a fully custom identity flow or using a pre-built interface, the platform supports various integration approaches depending on your architecture.</p>\n<p>If you're looking to understand how to implement JWT token authentication effectively, LoginRadius offers two primary implementation models that cater to different levels of customization and control:</p>\n<h3 id=\"1-idx-implementation--jwt-through-a-hosted-login-page\" style=\"position:relative;\"><a href=\"#1-idx-implementation--jwt-through-a-hosted-login-page\" aria-label=\"1 idx implementation  jwt through a hosted login page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. IDX Implementation – JWT through a Hosted Login Page</h3>\n<p>The IDX-hosted login approach enables secure, standards-compliant, JWT-based authentication without requiring you to build a custom login interface. This is a strategic option for fast, compliant, and user-friendly deployments.</p>\n<ul>\n<li>The Identity Experience Framework (IDX) comes with a fully custom branded hosted login page.</li>\n<li>Once the user logs in and gets enrolled, the user’s JWTs are automatically generated and issued. These tokens can be utilized for managing user sessions and accessing the APIs.</li>\n<li>This approach simplifies deployment without compromising on user experience and security standards.</li>\n</ul>\n<h3 id=\"configuration-steps\" style=\"position:relative;\"><a href=\"#configuration-steps\" aria-label=\"configuration steps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Configuration Steps:</strong></h3>\n<ol>\n<li>Enable JWT Login</li>\n<li>Go to <a href=\"https://console.loginradius.com/authentication/authentication-configuration\">authentication configuration settings</a> and enable JWT Login in the Admin Console.</li>\n</ol>\n<p><img src=\"/9fb19dd9c88c7916aeebd03ab6e661b7/lr-admin-console.webp\" alt=\"Screenshot of LoginRadius Admin Console showing JWT Custom IDP configuration interface with options for provider name, algorithm (HS256), key entry, clock skew, and expiration time settings.\"></p>\n<ol start=\"2\">\n<li>Specify your signing algorithm and expiry policy, and define your JWT Secret Key.</li>\n<li>Input a secure JWT signing key.</li>\n<li>Specify token expiry duration (e.g., 15–60 minutes)</li>\n<li>Select the desired algorithm —HS256 for symmetric signing (same key signs and verifies)</li>\n<li>RS256 for asymmetric signing, where LoginRadius securely stores the private key used to sign the JWT.</li>\n<li>Your app or backend service uses the public key to validate the token signature.</li>\n<li>LoginRadius provides a JWKS (JSON Web Key Set) endpoint to dynamically fetch and rotate public keys, ensuring trust without key exposure.</li>\n<li>Update IDX Template for Callback</li>\n<li>Modify your IDX login page template to retrieve the JWT post-login. You can access the token via redirect URL parameters or secure JavaScript callbacks.</li>\n</ol>\n<h3 id=\"example-response\" style=\"position:relative;\"><a href=\"#example-response\" aria-label=\"example response permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example Response:</h3>\n<p>{</p>\n<p>  \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR...\",</p>\n<p>  \"expires_in\": 1800</p>\n<p>}</p>\n<p>This integration approach works best for all teams that want effective identity workflows without the complexity of building proprietary login screens, something that is crucial for customer portals, onboarding of mobile applications, and even managing access for business partners.</p>\n<h3 id=\"2-direct-api-implementation--self-managed-login\" style=\"position:relative;\"><a href=\"#2-direct-api-implementation--self-managed-login\" aria-label=\"2 direct api implementation  self managed login permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Direct API Implementation – Self Managed Login</h3>\n<p>If you’re building a custom login UI or working in a headless environment, LoginRadius lets you generate and handle JWTs directly through its <a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/\">Authentication APIs</a>. Here’s how you can programmatically perform token authentication using the classic method:</p>\n<ul>\n<li>For custom front-end applications, LR offers an API to authenticate users and issue JWT tokens.</li>\n<li>In response to the login request, the developers are provided with signed tokens that can be validated on the client’s side or by downstream services.</li>\n<li>This method is best fit for enterprise applications that have complex custom workflows or are designed to be embedded into other applications.</li>\n</ul>\n<h3 id=\"configuration-steps-1\" style=\"position:relative;\"><a href=\"#configuration-steps-1\" aria-label=\"configuration steps 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Configuration Steps:</strong></h3>\n<h4 id=\"step-1-authenticate-via-api\" style=\"position:relative;\"><a href=\"#step-1-authenticate-via-api\" aria-label=\"step 1 authenticate via api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Authenticate via API:</h4>\n<ul>\n<li>\n<p>Send a POST login request to the LR Authentication URL: </p>\n<p>POST /identity/v2/auth/login</p>\n</li>\n</ul>\n<p>Include the user’s credentials (email + password) in the request body.</p>\n<h4 id=\"step-2-get-jwt-in-response\" style=\"position:relative;\"><a href=\"#step-2-get-jwt-in-response\" aria-label=\"step 2 get jwt in response permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Get JWT in Response</h4>\n<ul>\n<li>If the user credentials are authentic, then the JWT token will be available in response.</li>\n</ul>\n<p>{</p>\n<p> \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",</p>\n<p> \"expires_in\": 3600</p>\n<p>}</p>\n<h4 id=\"step-3-jwt-decoding-and-validation\" style=\"position:relative;\"><a href=\"#step-3-jwt-decoding-and-validation\" aria-label=\"step 3 jwt decoding and validation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: JWT Decoding and Validation</h4>\n<ul>\n<li>Use any JWT library (e.g., jsonwebtoken for Node.js or pyjwt for Python) to decode the token.</li>\n<li>Validate the signature using your configured secret key.</li>\n<li>Confirm claims like exp, iat, aud, and iss.</li>\n</ul>\n<h4 id=\"step-4-set-custom-claims-optional\" style=\"position:relative;\"><a href=\"#step-4-set-custom-claims-optional\" aria-label=\"step 4 set custom claims optional permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Set Custom Claims (Optional)</h4>\n<p>With LoginRadius, it is possible to customize the payload to include user roles and/or any additional metadata. You can set custom JWT claims on the Admin Console.</p>\n<p>With this method, you have complete customization over login flows while using LoginRadius to issue signed JWTs for user session management.</p>\n<p><strong>NOTE-</strong> With either method, LoginRadius ensures that JWTs are securely signed, optionally short-lived, and compatible with standard token validation libraries, making integration seamless for everyone.</p>\n<p>To get started with JWT implementation, you can<a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\"> read our complete developer documentation</a>. </p>\n<h2 id=\"hosted-login-vs-direct-api\" style=\"position:relative;\"><a href=\"#hosted-login-vs-direct-api\" aria-label=\"hosted login vs direct api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Hosted Login vs Direct API</h2>\n<p><img src=\"/15ec02ac98d24a9f1f28e5d0f06b9174/IDX-vs-Direct-API-JWT.webp\" alt=\"Illustration showing IDX vs Direct API JWT flow diagram comparing LoginRadius JWT authentication methods via Hosted Login Page (IDX) and Custom Login UI using Direct API, illustrating user login, JWT issuance, and token return process.\"></p>\n<h2 id=\"what-is-session-management-and-how-it-works-with-jwt\" style=\"position:relative;\"><a href=\"#what-is-session-management-and-how-it-works-with-jwt\" aria-label=\"what is session management and how it works with jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Session Management and How It Works with JWT</h2>\n<p><a href=\"https://www.loginradius.com/blog/identity/user-session-management/\">Session management </a>is how your app keeps track of a user after they log in so they don’t have to prove who they are with every request.</p>\n<p>In traditional apps, sessions are stored on the server using session IDs. Every time a request comes in, the server checks that session ID to verify the user.</p>\n<p>In modern apps, especially SPAs and APIs, JWTs are used to manage sessions without needing server-side storage; this is called stateless session management. The token itself carries the user’s identity, roles, and expiration details. As long as the token is valid, the user stays logged in.</p>\n<p>Good session management ensures:</p>\n<ul>\n<li>Security against session hijacking</li>\n<li>Fast user validation without hitting a database</li>\n<li>Smooth experiences with token refresh strategies</li>\n</ul>\n<h2 id=\"how-loginradius-handles-session-management-with-jwt\" style=\"position:relative;\"><a href=\"#how-loginradius-handles-session-management-with-jwt\" aria-label=\"how loginradius handles session management with jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How LoginRadius Handles Session Management with JWT:</h2>\n<ol>\n<li>\n<p>User Logs In </p>\n<ul>\n<li>LoginRadius returns an access token (JWT) and, optionally, a refresh token.</li>\n</ul>\n</li>\n<li>\n<p>Client Stores the Token </p>\n<ul>\n<li>Access tokens are stored in memory, sessionStorage, or secure cookies. </li>\n<li>They’re sent on every request via the Authorization: Bearer header. </li>\n</ul>\n</li>\n<li>\n<p>Access Token Expiry </p>\n<ul>\n<li>These tokens are short-lived by design (e.g., 15–30 minutes). </li>\n<li>Once expired, the client can use the refresh token to request a new access token. </li>\n</ul>\n</li>\n<li>\n<p>Token Renewal </p>\n<ul>\n<li>LoginRadius validates the refresh token and issues a new JWT, i.e., no user re-authentication is needed. </li>\n<li>Refresh tokens can be revoked at any time.</li>\n</ul>\n</li>\n<li>Logout and Token Revocation Strategy</li>\n</ol>\n<p>When the user logs out, both the access token and refresh token should be cleared from client storage.</p>\n<ul>\n<li>The refresh token can be explicitly revoked via the LoginRadius API, terminating the ability to renew sessions. </li>\n<li>\n<p>However, access tokens are stateless and cannot be revoked mid-lifecycle unless: </p>\n<ul>\n<li>You maintain a blacklist of token IDs (jti claims) and check them on each request. </li>\n<li>You use short-lived access tokens to limit exposure naturally. </li>\n<li>Or, you rotate your JWT signing key, invalidating all previously issued tokens. </li>\n</ul>\n</li>\n</ul>\n<p>Combining these strategies gives you greater control over token misuse and enables a robust, enterprise-grade logout flow. </p>\n<p><a href=\"https://www.loginradius.com/resource/whitepaper/secure-api-using-oauth2\"><img src=\"/e55ae4bbc8ce62e13f03e46e29ebe7cc/api-economy.webp\" alt=\"illustration showing LoginRadius free downloadable resource named API economy is transforming digitization: how to secure it using oauth 2.0.\"></a></p>\n<h2 id=\"how-to-store-jwt-tokens\" style=\"position:relative;\"><a href=\"#how-to-store-jwt-tokens\" aria-label=\"how to store jwt tokens permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to Store JWT Tokens?</h2>\n<p>When you implement JWT-based authentication, the client (browser or mobile app) needs a way to store the access token and, optionally, the refresh token after they are issued by the authentication server. This stored token is then attached to every subsequent request to prove the user's identity.</p>\n<p>Choosing where to store the JWT is a crucial security decision. The most common storage options are:</p>\n<ul>\n<li>localStorage</li>\n<li>sessionStorage</li>\n<li>HTTP-only cookies</li>\n</ul>\n<p>Each option has trade-offs between security, accessibility, and persistence, and the right choice depends on your application's architecture and threat model.</p>\n<h4 id=\"recommended-storage-strategy\" style=\"position:relative;\"><a href=\"#recommended-storage-strategy\" aria-label=\"recommended storage strategy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Recommended Storage Strategy</h4>\n<ul>\n<li>\n<p>Access Tokens </p>\n<ul>\n<li>For SPAs: store in memory or sessionStorage for short-term access </li>\n<li>If stored in the browser, protect against XSS </li>\n</ul>\n</li>\n<li>\n<p>Refresh Tokens</p>\n<ul>\n<li>Always store the JWT refresh token in HTTP-only secure cookies to prevent JavaScript access. This adds a critical layer of protection against XSS attacks.</li>\n<li>Combine with SameSite=Strict or SameSite=Lax attributes to mitigate CSRF risks and ensure the JWT refresh token is only sent in intended contexts.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"best-practices-for-storing-jwts\" style=\"position:relative;\"><a href=\"#best-practices-for-storing-jwts\" aria-label=\"best practices for storing jwts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Best Practices for Storing JWTs</h2>\n<ol>\n<li>Never store sensitive tokens (like refresh tokens) in localStorage or sessionStorage.</li>\n<li>Use Secure and HttpOnly flags with cookies to prevent JavaScript access and ensure transmission only over HTTPS.</li>\n<li>Set the SameSite=Strict or Lax attribute on cookies to protect against CSRF.</li>\n<li>Use short-lived access tokens and rotate refresh tokens regularly.</li>\n<li>Implement CSP (Content Security Policy) to reduce XSS risk.</li>\n<li>Avoid storing any tokens in frontend code (e.g., hardcoded in JS files).</li>\n</ol>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>JWT authentication with LoginRadius offers a modern, stateless approach to managing sessions across distributed systems. The IDX integration is ideal for rapid deployment, while the Direct API model is best for organizations needing deep customization and integration flexibility.</p>\n<p>With robust token signing, refresh capabilities, and centralized control, LoginRadius provides a future-ready foundation for secure, scalable identity architecture. <a href=\"https://www.loginradius.com/contact-us?utm_source=blog&#x26;utm_medium=web&#x26;utm_campaign=how-to-integrate-jwt\">Contact us</a> to know more about JWT authentication and implementation guide. </p>\n<h2 id=\"faqs\" style=\"position:relative;\"><a href=\"#faqs\" aria-label=\"faqs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>FAQs</h2>\n<h3 id=\"1-what-is-jwt-authentication-used-for\" style=\"position:relative;\"><a href=\"#1-what-is-jwt-authentication-used-for\" aria-label=\"1 what is jwt authentication used for permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. What is JWT authentication used for?</h3>\n<p><strong>A:</strong> JWT authentication securely verifies user identities, enabling stateless session management across web, mobile apps, and microservices without server-side session storage.</p>\n<h3 id=\"2-how-does-loginradius-simplify-jwt-integration\" style=\"position:relative;\"><a href=\"#2-how-does-loginradius-simplify-jwt-integration\" aria-label=\"2 how does loginradius simplify jwt integration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. How does LoginRadius simplify JWT integration?</h3>\n<p><strong>A:</strong> LoginRadius simplifies JWT integration by offering hosted <a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\">IDX login pages </a>and direct API-based authentication methods, enabling rapid deployment and deep customization.</p>\n<h3 id=\"3-is-jwt-authentication-secure\" style=\"position:relative;\"><a href=\"#3-is-jwt-authentication-secure\" aria-label=\"3 is jwt authentication secure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Is JWT authentication secure?</h3>\n<p><strong>A:</strong> Yes, JWT authentication is secure when implemented with best practices like short-lived tokens, secure storage methods, signature validation, and refresh token rotation.</p>\n<h3 id=\"4-can-jwt-tokens-be-revoked-with-loginradius\" style=\"position:relative;\"><a href=\"#4-can-jwt-tokens-be-revoked-with-loginradius\" aria-label=\"4 can jwt tokens be revoked with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Can JWT tokens be revoked with LoginRadius?</h3>\n<p><strong>A:</strong> Yes, LoginRadius allows<a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/refresh-token/revoke-refresh-token/?q=revoke+jwt\"> revocation of JWT</a> refresh tokens explicitly, and supports strategies like short-lived tokens and key rotation to manage token lifecycles securely.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"April 15, 2025","updated_date":null,"description":"Discover JWT (JSON Web Token) authentication, its advantages, and how to integrate it seamlessly using LoginRadius' hosted IDX and Direct API methods for secure, scalable identity management.","title":"JWT Authentication with LoginRadius: Quick Integration Guide","tags":["JWT","JSON Web Token","Authentication","Authorization"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":0.7782101167315175,"src":"/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp","srcSet":"/static/4cedb7829f98208cbc6d5a9aea4e983d/61e93/how-to-integrate-jwt.webp 200w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1f5c5/how-to-integrate-jwt.webp 400w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp 800w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1cc9f/how-to-integrate-jwt.webp 896w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},"pageContext":{"limit":6,"skip":102,"currentPage":18,"type":"//engineering//","numPages":53,"pinned":"5c425581-f474-5ae9-abe7-cf5342db2aaa"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}