{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/45","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Delete A Node Click to View the Orginal Question To remove the given node，which means whoever is asking the value for this node should get…","fields":{"slug":"/engineering/delete-a-node-is-same-tree-move-zeroes/"},"html":"<h3 id=\"delete-a-node\" style=\"position:relative;\"><a href=\"#delete-a-node\" aria-label=\"delete a node 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>Delete A Node</h3>\n<p><a href=\"https://leetcode.com/problems/delete-node-in-a-linked-list/\">Click to View the Orginal Question</a></p>\n<p>To remove the given node，which means whoever is asking the value for this node should get the value of the next node. Plus, the next node of this removing one should be the next next node.</p>\n<p>In diagram, with the following node list, we want to remove node 2.</p>\n<p>1 -> 2 -> 3 -> 4</p>\n<p>We update original Node 2 to Node 3 and skip the original Node 3, which gives out the list after removing node 2.</p>\n<p>1 -> 3 ------> 4</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=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* Definition for singly-linked list.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* function ListNode(val) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* this.val = val;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* this.next = null;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{ListNode}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">node</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{void}</span><span class=\"mtk3\"> Do not return anything, modify node in-place instead.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">deleteNode</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">node</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">node</span><span class=\"mtk1\">.</span><span class=\"mtk12\">val</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">node</span><span class=\"mtk1\">.</span><span class=\"mtk12\">next</span><span class=\"mtk1\">.</span><span class=\"mtk12\">val</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">node</span><span class=\"mtk1\">.</span><span class=\"mtk12\">next</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">node</span><span class=\"mtk1\">.</span><span class=\"mtk12\">next</span><span class=\"mtk1\">.</span><span class=\"mtk12\">next</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"is-same-tree\" style=\"position:relative;\"><a href=\"#is-same-tree\" aria-label=\"is same tree 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>Is Same Tree</h3>\n<p><a href=\"https://leetcode.com/problems/same-tree/\">Click to View the Original Question</a></p>\n<p><strong>Note</strong>: My solution is not efficient enough based on the performance, but I think it's fairly clean.</p>\n<p>I use recursion to solve the problem, first to define the basic cases, and recursively loop through both trees from left to right. If it hits one <code>false</code>, the whole result will be <code>false</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=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* Definition for a binary tree node.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* function TreeNode(val) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* this.val = val;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* this.left = this.right = null;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{TreeNode}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">p</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{TreeNode}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">q</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{boolean}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">isSameTree</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">p</span><span class=\"mtk1\">, </span><span class=\"mtk12\">q</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\">p</span><span class=\"mtk1\"> === </span><span class=\"mtk12\">q</span><span class=\"mtk1\"> ) </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</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\">p</span><span class=\"mtk1\"> || !</span><span class=\"mtk12\">q</span><span class=\"mtk1\"> || </span><span class=\"mtk12\">p</span><span class=\"mtk1\">.</span><span class=\"mtk12\">val</span><span class=\"mtk1\"> !== </span><span class=\"mtk12\">q</span><span class=\"mtk1\">.</span><span class=\"mtk12\">val</span><span class=\"mtk1\">) </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</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 class=\"mtk11\">isSameTree</span><span class=\"mtk1\">(</span><span class=\"mtk12\">p</span><span class=\"mtk1\">.</span><span class=\"mtk12\">left</span><span class=\"mtk1\">, </span><span class=\"mtk12\">q</span><span class=\"mtk1\">.</span><span class=\"mtk12\">left</span><span class=\"mtk1\">) ? </span><span class=\"mtk11\">isSameTree</span><span class=\"mtk1\">(</span><span class=\"mtk12\">p</span><span class=\"mtk1\">.</span><span class=\"mtk12\">right</span><span class=\"mtk1\">, </span><span class=\"mtk12\">q</span><span class=\"mtk1\">.</span><span class=\"mtk12\">right</span><span class=\"mtk1\">) : </span><span class=\"mtk4\">false</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"move-zeroes\" style=\"position:relative;\"><a href=\"#move-zeroes\" aria-label=\"move zeroes 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>Move Zeroes</h3>\n<p><a href=\"https://leetcode.com/problems/move-zeroes/\">Click to View the Original Question</a></p>\n<p>Here I have create two indices one called <code>z</code> to index the position for zeroes, another is <code>i</code> to loop through the nums array. They both increment by one when they see a non-zero value, but when it is zero, z stays at position and get ready to swap the position with next non-zero value <code>i</code> meets. By keep doing it, it will fill a consecutive row of zeroes, till the end.</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\">&lt;!--</span><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number[]}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">nums</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{void}</span><span class=\"mtk3\"> Do not return anything, modify nums in-place instead.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">moveZeroes</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">nums</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">z</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">for</span><span class=\"mtk1\">(</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> </span></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 .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\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 22, 2015","updated_date":null,"description":null,"title":"Delete a Node, Is Same Tree, Move Zeroes","tags":["Data Structure","JavaScript","Linked List"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/5d9e9ee1d8ffc4932a01a1c72fc15ab7/403a4/code-js-300x300.webp","srcSet":"/static/5d9e9ee1d8ffc4932a01a1c72fc15ab7/61e93/code-js-300x300.webp 200w,\n/static/5d9e9ee1d8ffc4932a01a1c72fc15ab7/403a4/code-js-300x300.webp 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Lucius Yu","github":null,"avatar":null}}}},{"node":{"excerpt":"What's one thing virtually every website has? If you said navigation (you did) you're absolutely right! Go ahead and enjoy that wonderful…","fields":{"slug":"/engineering/csshtml-animated-dropdown-navigation/"},"html":"<p>What's one thing virtually every website has? If you said navigation (you did) you're absolutely right! Go ahead and enjoy that wonderful feeling of being right for a moment... and now that we're feeling like a champ, let's get to it.</p>\n<p>Navigation buttons, depending on your site of course, are likely going to be some of the most commonly used items on your web site. Typically they're found near the top so people can quickly and easily... well navigate of course! With this in mind it's worth it to make sure your navigation is both visually appealing and provides an enjoyable user experience.</p>\n<p>A common featured for navigation menus is the drop down functionality for displaying sub options. This can be achieved through Javascript if you really feel like it (you don't), but why bother with that when CSS3 offers a much more elegant solution!</p>\n<p>First we start out building a simple un-ordered list, and give it some list items each of which contain a link that point nowhere in particular.<br>\n<img src=\"/fbd7cd5e46da11bb5f044d594bea4b5f/dropdownScreen1.webp\" alt=\"dropdownscreen1\"></p>\n<p>By the way, if you're on Sublime Text there's a great shortcut for making lists: ul>li+li+li+li and then \"Tab\" creates an un-ordered list with 4 list item tags inside of it. For more excellent Sublime tips check out my amigo Lucius' <a href=\"/beginners-guide-for-sublime-text/\">blog post</a> on the topic.</p>\n<p>Now that we've got the bare bones, let's give this skeleton a spine. We're now going to put another ul inside of those list items, and once again more list items inside of those lists which contain, you guessed it, links to nowhere.<br>\n<img src=\"/70d61bff91bfcfcadb8d955c3fc03b44/dropdownScreen2.webp\" alt=\"dropdownscreen2\"></p>\n<p>That's all the HTML we have to write for this example, so now we move on to the CSS.</p>\n<p>The first few things on the ul's and links are just to remove some default styles that I don't care for.</p>\n<p>The first actually relevant style is the inline-block display property on the list items to make them spread out horizontally. If you're unfamiliar with using inline-block for positioning I highly recommend reading up on it because it's an awesome alternative to floats or sometimes even flex-box. Next up we give these list items a relative position, so that the later absolutely positioned sub menu will use this as a reference point.</p>\n<p><img src=\"/0d7ee91a636d3734c5151b472f165f46/dropdownScreen3.webp\" alt=\"dropdownscreen3\"></p>\n<p>To quote every MTV cribs star ever, here's where the magic happens. We put a max-height (that is at least as tall as all of the list items on the sub menu) and a height of auto on the sub menu. Note the ul li:hover, meaning these styles only apply when the first level of list items are hovered over. This might seem weird now, but it'll hopefully make sense with the styles we make use of in a bit.<br>\n<img src=\"/77e842c9eed15677fb29682214ee71c8/dropdownScreen4.webp\" alt=\"dropdownscreen4\"></p>\n<p>Next up we just give the links some padding, which is highly preferable to giving the list item padding because then you can end up with a small hitbox for the actual link and a bunch of dead space around it. Only other thing to note here is the display block on the link which is required for the absolute positioning used later.</p>\n<p>The .sub-menu styles are pretty basic, just give it a position of absolute and then top: 100%, left: 0 and width: 100% to make it sit flush below the first level of list items. Finally throw on a transition to really allow the animation to shine, and fine tune the timing if you'd like.</p>\n<p>Still on the .sub-menu we give it a max-height of 0 and overflow: hidden. What this does is it hides the element from our view, similar to display:none or visibility:hidden... but for our animation we have to do it this way!</p>\n<p>Lastly we give the sub menu list items and links a display of block and some colors because pretty.</p>\n<p>That's it, you've now got a simple dropdown navigation with a neat little animation! You can add a height of 0 to the ul .sub-menu as well for a slightly different effect, or play around with the transition time and effect. Much to the same effect, increasing the value of the max-height on the sub menu hover will have an effect on the time it takes the dropdowns to make it to the end.</p>\n<p><a href=\"https://codepen.io/anon/pen/bVKEwK\">Check it out on Codepen.</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</style>","frontmatter":{"date":"December 15, 2015","updated_date":null,"description":null,"title":"CSS/HTML Animated Dropdown Navigation","tags":["HTML","CSS","UI","CSS Animation"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/de68b801e2b33e38132380ed5dfa2f87/403a4/drop-anim-300x300.webp","srcSet":"/static/de68b801e2b33e38132380ed5dfa2f87/61e93/drop-anim-300x300.webp 200w,\n/static/de68b801e2b33e38132380ed5dfa2f87/403a4/drop-anim-300x300.webp 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Zakary Hughes","github":null,"avatar":null}}}},{"node":{"excerpt":"In this tutorial I will demonstrate how to build a custom login form scratch. This time instead of using the default function call Wordpress…","fields":{"slug":"/engineering/part-2-creating-a-custom-login-form/"},"html":"<p>In this tutorial I will demonstrate how to build a custom login form scratch. This time instead of using the default function call Wordpress provides us, we will create this login form and the styling from scratch, making it a very customized form. I will be providing the CSS I am using, however you may style this however you wish.</p>\n<h2 id=\"building-a-custom-login-form\" style=\"position:relative;\"><a href=\"#building-a-custom-login-form\" aria-label=\"building a custom login form 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>Building a Custom Login Form</h2>\n<p><img src=\"/de62cef1a8e9b1e555aa0ccb212c95d6/wp-login-boring.webp\" alt=\"wp-login-boring\"></p>\n<p>This is what WordPress gives us out of the box.. Boring, right?</p>\n<p>I am going to show this part once again because it is probably the easiest to implement for beginners. I covered this in Part 1, but we'll go through it again just in case you're skipping ahead</p>\n<p>To start our page theme you will need to do the following</p>\n<p>1. Install WordPress\n2. Navigate to your wp-content/themes folder and choose a theme to edit or install a new one\n3. create a file called page-login-custom.php in the theme directory (Notice we are now making a new Page Theme)\n4. Next open that file with a text editor of your choosing and add the following at the top of the php file</p>\n<p>--></p>\n<p>To initialize this page template make sure to activate the theme you've selected and then navigate to a page or post. On the right hand side of your page/post editor you should now see a dropdown available for template. Change your template to Login Custom and that will attach that page theme to this page/post.</p>\n<p>Now for the custom code. Below I have provided an example of some code that I have customized to make my custom login form.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk1\"> </span><span class=\"mtk12\">method</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;post&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">action</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;wp-user-form&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><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\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;log&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">size</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;20&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;user_login&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tabindex</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;11&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"></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\">Remember me</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><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;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;user-submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tabindex</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;14&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;user-submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><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;hidden&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;redirect_to&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span></code></pre>\n<p><img src=\"/056be2feb51f0d6db967dbd19ed17b74/login-2-custom.webp\" alt=\"login-2-custom\"></p>\n<p>Let's take a look at that custom form</p>\n<h2 id=\"handling-the-login-form-response\" style=\"position:relative;\"><a href=\"#handling-the-login-form-response\" aria-label=\"handling the login form 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>Handling the Login Form response</h2>\n<p>To handle the Login Form response use the exact same method we used in part 1. Remember to place that function within your functions.php file within your theme unless you're building a plugin.</p>\n<p>In this example we have built a custom WordPress login form that you could customize and style to your desire. In the next section I will be demonstrating how to build a lost password form that is fully customized. Our custom lost password form will send an email to the user as well as handle creating a new password for the user.</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 .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n</style>","frontmatter":{"date":"December 08, 2015","updated_date":null,"description":null,"title":"Part 2 - Creating a Custom Login Form","tags":["Engineering","Login"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/c77161283a52150af28cf97603d842a3/e7487/cust-login-2-150x150.webp","srcSet":"/static/c77161283a52150af28cf97603d842a3/e7487/cust-login-2-150x150.webp 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Zoie Carnegie","github":null,"avatar":null}}}},{"node":{"excerpt":"Authentication systems are the backbone of many websites. It allows users to log in to your site and preserving data between visits. It is…","fields":{"slug":"/engineering/website-authentication-protocols/"},"html":"<p>Authentication systems are the backbone of many websites. It allows users to log in to your site and preserving data between visits. It is crucial in offering a robust user experience, which rewards your users for providing their details. Authentications often provide access to personal private data which if made public, it could harm your user. To prevent these, authentication protocols were created to secure the requests while allowing users to still safely login to your system from any environment.</p>\n<p><strong>Basic SSL Auth</strong></p>\n<p>Basic auth is the simplest form of web authentication. It utilizes standard HTTP headers in place of more complicated solutions that rely on cookies, session identifiers, and login pages. There is very little security built into the basic auth system. Credentials are transmitted with only Base64 encoding and are not encrypted or hashed. Due to the ingrained insecurities in the system, these requests are most often made via HTTPS.</p>\n<p>The authorization information should be compiled into the following format and included in the header:</p>\n<p>Format:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"http\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">&lt;!--Authorization: Basic --&gt;</span></code></pre>\n<p>Full details on the Basic Authentication protocol can be found here: <a href=\"http://www.w3.org/Protocols/HTTP/1.0/spec.html#AA\">Authentication Protocol</a></p>\n<p><strong>Digest Auth</strong></p>\n<p>Digest Auth works similar to basic SSL authentication with the exception that the password is encrypted using a one-way hash. It utilizes MD5 cryptographic hashing with a nonce(a server-generated value that prevents replay attacks).</p>\n<p>The typical flow of a Digest Auth request is :</p>\n<ol>\n<li>A user navigates to a page that requires user authentication.</li>\n<li>The server responds with a 401 message that signifies that a user is not currently authorized to access the content. In the response, it also includes the nonce which will be used during the authorization to prevent replay attacks,</li>\n<li>The site then displays an authentication interface to gather the required details( username and password )</li>\n<li>The provided details are re-sent to the server with an authentication header included in the request that has a response code.</li>\n<li>The server would then verify the provided credentials and accept the authentication or return a 401 message if the credentials are incorrect, which would cause the user to be again prompted with the authentication interface.</li>\n</ol>\n<p>You can find full details on the Digest Auth protocol can be found here: <a href=\"https://www.ietf.org/rfc/rfc2617.txt\">Digest Auth Protocol</a></p>\n<p><strong>OAuth 1.0</strong></p>\n<p>The OAuth 1.0 protocol relies on having a shared secret between the server and the site. This shared secret is used to generate a signature that is included in the request. The generated signature is used to verify the validity of the authentication request on the server-side. The process for authorizing the user is generally handled in three steps (3-legged OAuth):</p>\n<ol>\n<li>Site obtains Request Token.</li>\n<li>User authorizes the Request Token.</li>\n<li>Site exchanges Request token for Access Token.</li>\n</ol>\n<p>The process of completing a 3-legged OAuth request will generally be handled as follows:</p>\n<ol>\n<li>\n<p>The site will send a signed request for the Request token. This request should contain the following parameters:</p>\n<ol>\n<li>oauth_consumer_key</li>\n<li>oauth_timestamp</li>\n<li>oauth_nonce</li>\n<li>oauth_signature</li>\n<li>oauth_signature_method</li>\n<li>oauth_version</li>\n<li>oauth_callback</li>\n</ol>\n</li>\n</ol>\n<p>This request will be validated on the server.  If validated, it will return the request token in the following format:</p>\n<ol>\n<li>oauth_token</li>\n<li>oauth_token_secret</li>\n<li>and any other additional parameters returned by your server.</li>\n<li>The next step after retrieving the request token is to prompt your user to input their login credentials. These are then formatted into a signature with the oauth_token request token. Then they are sent with a request back to the server for validation. Upon successful validation from this request, the server will return the following:</li>\n<li>oauth_token</li>\n<li>oauth_verifier</li>\n</ol>\n<p>These will be used in the next step to retrieve an access token.</p>\n<ol>\n<li>The final step is exchanging the retrieved details from step 2 for an access token, which will be used to access the server's resources. To exchange your request token for an access token, you can make a request to the server with the following signed request</li>\n<li>oauth_token -returned from step 2</li>\n<li>oauth_consumer_key</li>\n<li>oauth_nonce</li>\n<li>oauth_signature</li>\n<li>oauth_signature_method</li>\n<li>oauth_version</li>\n<li>oauth_verifier -returned from step 2</li>\n</ol>\n<p>This will return you an access token to be used in conjunction with your secret in order to make requests for information from the server.</p>\n<p>You can find full details on the OAuth 1.0 protocol here: <a href=\"https://tools.ietf.org/html/rfc5849\">OAuth 1.0 protocol</a></p>\n<p><strong>OAuth 2.0</strong></p>\n<p>This is similar to the OAuth 1.0 protocol, it relies on a client id and secret in order to format request, but simplifies much of the complicated signing process that is inherent in the OAuth 1.0 system. The process for authorizing a user using the 3-legged OAuth 2.0 protocol is as follows:</p>\n<ol>\n<li>\n<p>User is directed to the service for authorization with the following details included in the authorization URL:</p>\n<ol>\n<li>client_id</li>\n<li>redirect_uri</li>\n<li>response_type</li>\n<li>scope</li>\n</ol>\n</li>\n<li>\n<p>The user would then authenticate with the service and grant the application access to their details. On successful authentication, the user is redirected back to the redirect_uri with the following parameters:</p>\n<ol>\n<li>code</li>\n<li>state</li>\n</ol>\n</li>\n<li>\n<p>The code returned in step 2 is then used by the application to make a request for an access token. Included in this request should be:</p>\n<ol>\n<li>client_id</li>\n<li>client_secret</li>\n<li>code</li>\n<li>redirect_uri</li>\n<li>grant_type - This should be set to “authorization_code”</li>\n</ol>\n</li>\n</ol>\n<p>The server will verify these details and then return an access token with an expiration time if they are valid. These get generally returned in the following format:</p>\n<ol>\n<li>access_token</li>\n<li>expires_in</li>\n<li>refresh_token</li>\n</ol>\n<p>You can find full details on the OAuth 2.0 protocol here: <a href=\"http://oauth.net/2/\">OAuth 2.0 protocol</a></p>\n<p>Authentication protocols allow you to secure your data with varying levels of security. Depending on the data being accessed and your desired level of security, implementing one of the above protocols allows you to be confident that your data is safe and can only being accessed by users that are permitted to your system.</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 01, 2015","updated_date":null,"description":null,"title":"Website Authentication Protocols","tags":["Authentication","Oauth"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5625,"src":"/static/148a460add8a46784c528ade826702d3/58556/server-proc-150x150.webp","srcSet":"/static/148a460add8a46784c528ade826702d3/61e93/server-proc-150x150.webp 200w,\n/static/148a460add8a46784c528ade826702d3/1f5c5/server-proc-150x150.webp 400w,\n/static/148a460add8a46784c528ade826702d3/58556/server-proc-150x150.webp 800w,\n/static/148a460add8a46784c528ade826702d3/99238/server-proc-150x150.webp 1200w,\n/static/148a460add8a46784c528ade826702d3/7c22d/server-proc-150x150.webp 1600w,\n/static/148a460add8a46784c528ade826702d3/34181/server-proc-150x150.webp 2256w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"1. Nim Game Click to View Original Question This question is very easy once you figure out the trick behind the game.\nSince each time you…","fields":{"slug":"/engineering/nim-game-add-digits-maximum-depth-of-binary-tree/"},"html":"<h3 id=\"1-nim-game\" style=\"position:relative;\"><a href=\"#1-nim-game\" aria-label=\"1 nim game 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. Nim Game</h3>\n<p><a href=\"https://leetcode.com/problems/nim-game/\">Click to View Original Question</a></p>\n<p>This question is very easy once you figure out the trick behind the game.\nSince each time you can only pick 3 stones at most, if there are 4 stones originally on the table, no matter how many you take ... your hopefully non-stupid friend can easily beat you. The same logic also applies when the number of stones is more than 4.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">n</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{boolean}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">canWinNim</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">n</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 class=\"mtk12\">n</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">4</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> ? </span><span class=\"mtk4\">false</span><span class=\"mtk1\"> : </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"\" style=\"position:relative;\"><a href=\"#\" aria-label=\" 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></h3>\n<p>2. Add Digits</p>\n<p><a href=\"https://leetcode.com/problems/add-digits/\">Click to View Original Question</a></p>\n<p>This is a tricky question, the key is trying to find the repetitive pattern of the Digits Sum. If you can't get the pattern by observation then we can do some math to find the pattern.</p>\n<p>So assume we have a 4 digit number \"abcd\" or 1234, and we want to find out the sum of the digits which in expression is:</p>\n<p>var digitSum = a + b + c + d</p>\n<p>We still can't figure out the answer from this alone, so we need to find something else to help us to get the value. Then we can consider the actual value of \"abcd\" = 1000a + 100b + 10c + d.</p>\n<p>- If you're familiar with Ring Theory (pretty sure it's Ring Theory.. I could be wrong..) then perfect! Under Ring 9, the actual value of abcd === a + b + c + d.\n- And if you don't know about Ring Theory, think of this as getting the remainder of \"abcd\" divided by 9</p>\n<p>> (1000a + 100b + 10c + d) % 9 => (999a + a + 99b + b + 9c + c + d) % 9 => a + b + c + d</p>\n<p>So whatever the reminder is equals to the sum of the digits and that is more than enough information to solve the question.</p>\n<p><strong>Be careful with the number 0 !!</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span><span class=\"mtk3\"> </span><span class=\"mtk12\">num</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@return</span><span class=\"mtk3\"> </span><span class=\"mtk10\">{number}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addDigits</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">num</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\">num</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\">) </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">num</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 class=\"mtk12\">num</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">9</span><span class=\"mtk1\"> === </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> ? </span><span class=\"mtk7\">9</span><span class=\"mtk1\"> : </span><span class=\"mtk12\">num</span><span class=\"mtk1\"> % </span><span class=\"mtk7\">9</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"-1\" style=\"position:relative;\"><a href=\"#-1\" aria-label=\" 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></h3>\n<p>3. Maximum Depth of Binary Tree</p>\n<p><a href=\"https://leetcode.com/problems/maximum-depth-of-binary-tree/\">Click to View Original Question</a></p>\n<p>This is very typical of recursion problems, and recursion is always hard to explain in words</p>\n<p>(╯‵□′)╯︵┻━┻</p>\n<p>Regardless I will try my very best to describe it.</p>\n<p>1. You have a tree node, and check if it is an empty tree, if so return 0\n2. If it is not empty, use recursion to find the value\n3. The recursion will start with the left node of root, and iterate through the tree, and keep checking the depth of each node till reaching out to the leaves. Each node (small root) records its maximum depth value by a record count called \"\"currentLength\"\".\n4. Until the whole tree is traversed, the root will compare its leftLength and rightLength and return the answer!</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">rightLength</span><span class=\"mtk1\"> ? </span><span class=\"mtk12\">leftLength</span><span class=\"mtk1\"> : </span><span class=\"mtk12\">rightLength</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 class=\"mtk12\">rootLength</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}--&gt;</span></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 .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\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":"November 24, 2015","updated_date":null,"description":null,"title":"Nim Game, Add Digits, Maximum Depth of Binary Tree","tags":["Nim","JavaScript"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/3d4aded531cc491994ddf29e4caf94a0/e7487/nim-blog-150x150.webp","srcSet":"/static/3d4aded531cc491994ddf29e4caf94a0/e7487/nim-blog-150x150.webp 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Lucius Yu","github":null,"avatar":null}}}},{"node":{"excerpt":"As a preface to this article: preprocessors can be used for a variety of file types, but this article is going to focus solely on CSS…","fields":{"slug":"/engineering/the-truth-about-css-preprocessors-and-how-they-can-help-you/"},"html":"<p>As a preface to this article: preprocessors can be used for a variety of file types, but this article is going to focus solely on CSS preprocessors. Additonally I'm going to try and avoid my personal bias and give a very generic description of CSS preprocessors rather than my preferred preprocessor.</p>\n<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>First off what is a preprocessor? To give you a simple analogy think of speaking with someone, in a language you understand, who has a strong accent or is speaking in a different dialect. They're technically speaking the same language as you, but actually understanding what they're saying can be next to impossible.</p>\n<p>In the context of CSS, the \"normal\" or unaccented language would be CSS and the accented version would be the preprocessor! What this means in practice is that you're writing out expressions that resemble standard CSS, but with some very distinct differences with regards to its syntax.</p>\n<p>As with regular spoken language, there's not a whole lot we can do with something we can't understand. Luckily there are translators, and the same is true of preprocessors. The preprocessor code can be processed (there are a number of different ways to accomplish this), and then out pops an understandable standard-syntax CSS file ready to be used.</p>\n<p>Now why would we want to write CSS in some weird way you might ask? An excellent question! Because our nonsense can be translated into regular CSS, this allows us to write some very robust and even dynamic CSS expressions.</p>\n<h2 id=\"new-toys\" style=\"position:relative;\"><a href=\"#new-toys\" aria-label=\"new toys 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>New Toys</h2>\n<p>With preprocessors we've got a bundle of features now available to be used along with all the standard CSS rules we're accustomed to writing.</p>\n<p>To name a few features supported by preprocessors we've got: functions, mixins, math, variables, operators, conditionals, iteration and more to help you be more organized and write less overall.</p>\n<h3 id=\"variables\" style=\"position:relative;\"><a href=\"#variables\" aria-label=\"variables 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>Variables</h3>\n<p>Variables increase your maintainability drastically by making it so you only have to change a value in one place to affect it everywhere it was used. Imagine for example you want to add a Halloween theme to your site's colors.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> </span><span class=\"mtk6\">p</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">black</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementTwo</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">h3</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">black</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">a:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">:</span><span class=\"mtk8\">orange</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Changing them back would require you to go and change each instance of black or orange. However; with variables you can do something like this.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">$</span><span class=\"mtk4\">theme-color-1</span><span class=\"mtk1\">: orange;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">$</span><span class=\"mtk4\">theme-color-2</span><span class=\"mtk1\">: black;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementOne</span><span class=\"mtk1\"> </span><span class=\"mtk6\">p</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-2;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.elementTwo</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">h3</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-2;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">a:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: $theme-color-1;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Define the value of the variable in one place, and everywhere it gets used will be a reference to that value. Want to change all instances of black back to grey? Just change the variable definition and you're done.</p>\n<h3 id=\"functions--friends\" style=\"position:relative;\"><a href=\"#functions--friends\" aria-label=\"functions  friends 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>Functions &#x26; Friends</h3>\n<p>Another one of the biggest features would be functions. With these you can set up one well written function definition and then sit back and let it do all the heavy lifting for you!</p>\n<p>Functions combined with math, variables, iteration, and conditionals allows you to write some very dynamic style rules. Think of sprite sheets where the value of the background position is being incremented with each statement. Instead of writing out each one by hand, make a function that uses math and iteration to change the background position.</p>\n<p>That's a very simple example, but I've seen some truly impressive and complicated designs created with the use of functions!</p>\n<h3 id=\"selectors\" style=\"position:relative;\"><a href=\"#selectors\" aria-label=\"selectors 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>Selectors</h3>\n<p>One of my favorite features of preprocessors are the new selectors. The parent reference (&#x26;) allows you to group your rules so that everything pertaining to a specific element can be grouped together nicely.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    &amp;:hover {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">color</span><span class=\"mtk1\">: some-color;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Compiles to...</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.someElement:hover</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: some-color;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The parent selector takes whatever follows it immediately and tacks it on to the parent that it is nested under. In this case hover will be appended to .someElement. Another great one to check out is the root reference!</p>\n<h2 id=\"nesting-and-general-aesthetic\" style=\"position:relative;\"><a href=\"#nesting-and-general-aesthetic\" aria-label=\"nesting and general aesthetic 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>Nesting and General Aesthetic</h2>\n<p>CSS's default format is ugly as sin. An endless tide of barely indented rules, hopefully organized in some meaningful way. With CSS preprocessors nesting is an awesome feature that helps your rules become more intuitive/logically grouped and increases readability. Nesting can give your CSS a much more distinct visual hierarchy not unlike HTML.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    .someOtherElement {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        some-rule: another-value</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Compiles to...</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: some-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.someElement</span><span class=\"mtk1\"> </span><span class=\"mtk6\">.someOtherElement</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    some-rule: another-value;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Full disclosure, your resulting CSS file will still likely look like someone dropped their bowl of Alphaghetti in their bowl of Alphabits and then threw that bowl at a wall. However; the file you actually work in will be considerably prettier, and that's all we care about.</p>\n<p>Some people have beef with preprocessors because of over done selectors which are a result of going a little too hard with nesting. An easy way to avoid this is by limiting your nesting to 3 levels deep. Any further than that gets pretty ugly, but hey I'm not your supervisor... if you feel it's necessary then you do what you gotta do.</p>\n<h2 id=\"processing-dependant\" style=\"position:relative;\"><a href=\"#processing-dependant\" aria-label=\"processing dependant 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>Processing dependant</h2>\n<p>Now depending on how you choose to have your preprocessor code processed these features may or may not be more/less accessible. That being said I still feel they are worth mentioning.</p>\n<p>Auto updating the page you're working on is a small perk but I remember being quite happy to find out I could just save my project and not have to spam F5 like my little sister trying to buy front row Justin Bieber tickets online. Just save and it will update your project automatically.</p>\n<p>Another one is vendor prefixes. There are a handful of ways to stop writing these things out by hand each time. Whether it's via mixins, functions or a built in feature of the processor itself you can avoid writing out these dreadfully monotonous prefixes for good.</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>At first it might seem like a bunch of new stuff you have to learn and implement... but really if you already know CSS you're over halfway there. All you need to do is learn the specific syntax and familiarize yourself with the new features available to you with the preprocessor of your choice. It's a gentle learning curve with a surplus of benefits to integrate preprocessors into your workflow.</p>\n<p>This article is by no means all encompassing, but rather a sampler to create enough interest to try it out and learn more about preprocessors.</p>\n<p>On that note there are <a href=\"http://csspre.com/compile/\">resources</a> for comparing the preprocessors as well as trying them online. Each one has its own perks so try 'em out and find the one that fits your style!</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 .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n</style>","frontmatter":{"date":"November 17, 2015","updated_date":null,"description":null,"title":"The truth about CSS preprocessors and how they can help you","tags":["CSS"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/c1a3c2e9cd169b0cb2976078dc054b7b/e7487/desdev-150x150.webp","srcSet":"/static/c1a3c2e9cd169b0cb2976078dc054b7b/e7487/desdev-150x150.webp 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Zakary Hughes","github":null,"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":264,"currentPage":45,"type":"//engineering//","numPages":53,"pinned":"5c425581-f474-5ae9-abe7-cf5342db2aaa"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}