{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/16","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Many developers overlook imagery on the websites they develop. The website design starts with image placeholders instead of images. They…","fields":{"slug":"/engineering/image-colorizer-tool-kolorizer/"},"html":"<p>Many developers overlook imagery on the websites they develop. The website design starts with image placeholders instead of images. They spend weeks creating it's structure and features. Then they spend some time on the content, and after that, the images come as the last step right before launching the website with the words \"Let's just put a random image of whatever, as long as it makes sense.\"\n</p>\n<p>When this approach works for many websites since imagery is secondary content, in many cases, you need to involve the work of a designer or a photographer to get something unique to use free of copyright. When custom work is always encouraged, there is a space for the first approach. Whether you do not have a designer to rely on, or you want to ease the load off your design team, you can find copyright-free images on the web and use them in your projects.\n</p>\n<h2 id=\"the-problem\" style=\"position:relative;\"><a href=\"#the-problem\" aria-label=\"the problem 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>The problem</h2>\n<p>All seems fair until you realize that your website is starting to look like a circus. With every image and photo having different colors, the website is like an intersection without any traffic lights - everybody is doing whatever they want. There is no uniformity or harmony between all of the imagery. This might seem like a small problem initially, but it hurts your business in the long run. </p>\n<p>As your business struggles to create a consistent unified brand, people do not sense the authority and quality of your product and in the end, they go to someone else that seems to know what they are doing. And if you think, \"Not everybody is a designer, and most people would not notice this\", while it is true, some people would not care, but in most cases, people would start noticing this. All this will be happening subconsciously. They will not tell you precisely what is wrong, but they would feel less connection with your brand, which could make them leave in the long run if they find something that feels more right.\n</p>\n<p>If your product is selling car insurance, you want people to identify you as the leader, the main place to get everything you need for car insurance. To accomplish that, you need to build a strong brand around your product.</p>\n<p>You might be thinking right now: \"Sounds like I need an expensive designer to figure all of that out!\". When a great designer could take your brand to the next level, you can do something that will not cost you a dime. A great start to building a brand is making all the colors on the website as consistent as possible. I am sure you know how to make that in CSS with the headings, paragraphs, link colors, etc., it is a little more complicated for the images.\n</p>\n<h2 id=\"the-solution\" style=\"position:relative;\"><a href=\"#the-solution\" aria-label=\"the solution 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>The solution</h2>\n<p><img src=\"/510ebc70d4d8b5985e557cf02b3e7fd2/logo.webp\" alt=\"Kolorizer Logo\" title=\"Kolorizer Logo\"></p>\n<p>This is where our little tool comes in - Kolorizer. This incredibly simple online tool will have a huge impact on your brand, whether you are kicking it off or simplifying and growing an existing one.\n</p>\n<p>The task is simple - to make colors in all the imagery on your website match your brand's colors. There are mostly two different ways of doing this in the design world: <strong>\"The overlay\" method</strong> and <strong>\"The changing of the base color\" method</strong>.</p>\n<p>In the <strong>\"The overlay\" method</strong>, the color overlay is simply applied on top of the image. While it is the easiest and quickest way of adding some brand colors to the images, it comes with some downsides. The image becomes darker and some other colors might still peek through, which is not great.</p>\n<p>![](01.webp \"Image created using \"The overlay\" method\")\n<em>Image created using \"The overlay\" method</em>\n</p>\n<p>The second, <strong>\"The changing of the base color\" method</strong>, is less common because it requires a few more steps. First, the image is converted to black and white, making every pixel in the image based on black color. So every single pixel is a percentage of black color. Now we can replace that black color with any of the dark colors you have in your brand, like dark blue or dark orange. And voila! Every pixel in our image is now based on that color, without any overlay that darkens the image and without any other colors peeking through the overlay. This does create a little problem: since we are basing our image on a dark color that is not black, the image is lighter and we have to adjust the brightness of the image a little bit to compensate for this. The amount depends on the image itself - some would be good right after the conversion, some would need to be darkened or lightened.</p>\n<p>![](02.webp \"Image created using \"The changing of the base color\" method\")\n<em>Image created using \"The changing of the base color\" method</em></p>\n<p>Kolorizer is built using the second method, and most of the steps are done automatically.</p>\n<p><img src=\"/57756050cf89ad210302cd6916a9aab0/03.webp\" title=\"Kolorizer Tool\"></p>\n<p>After you upload the image, it is converted to your selected brand color right away. Adjust the color if you need to. Maybe try a different dark color out of your brand colors. Then adjust the brightness of the image if needed and download the finished colorized image. That is it!</p>\n<p>Now in just seconds, you can have a stock image that matches your brand color and helps you build a brand vs hurting it in the long run.</p>\n<h3 id=\"a-tip\" style=\"position:relative;\"><a href=\"#a-tip\" aria-label=\"a tip 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>A Tip</h3>\n<p>Use this tool for all of the imagery in your brand materials: slideshows, handouts, posters, documents, etc., to have a consistent and recognizable brand across the board.</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":"February 09, 2021","updated_date":null,"description":"Kolorizer is a free photo coloring tool to help you align the images on a website with your brand.","title":"Image Colorizer Tool - Kolorizer","tags":["Design","Photos","Brand"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7094017094017093,"src":"/static/caf32b1ff5bb357db79f2d0c25e7daeb/58556/cover.webp","srcSet":"/static/caf32b1ff5bb357db79f2d0c25e7daeb/61e93/cover.webp 200w,\n/static/caf32b1ff5bb357db79f2d0c25e7daeb/1f5c5/cover.webp 400w,\n/static/caf32b1ff5bb357db79f2d0c25e7daeb/58556/cover.webp 800w,\n/static/caf32b1ff5bb357db79f2d0c25e7daeb/cc834/cover.webp 1024w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Max Sergeyenko","github":"maxsergeyenko","avatar":null}}}},{"node":{"excerpt":"At the dawn of \"smartphones\" in late 2007, when Apple released the iPhone, there were native apps. Apple's app framework included a native…","fields":{"slug":"/engineering/progressive-app-vs-native-app/"},"html":"<p>At the dawn of \"smartphones\" in late 2007, when Apple released the iPhone, there were native apps. Apple's app framework included a native app SDK that allows developers to take advantage of all the physical device features and topped it off with an app store that allows for distribution and monetization of the finished applications. When Google released Android in competition, they also embraced this approach with their app store and SDK, which also leveraged the entire Google platform and its services. </p>\n<p>Developers could tap into Google's search and maps services, as well as email, etc. Native applications served their purpose superbly and became the primo factor that propelled Android and iOS as the big two phone operating systems at the time, until the present day.</p>\n<p>Native smartphone applications were so common that Apple coined the tagline \"There is an app for that\" and copyrighted it in 2009. </p>\n<p>However, come the 2010s. Web technologies saw increasingly rapid growth. Server-side rendered web pages allow for the creation of full-fledged web applications that could offer business values beyond static information. The responsive design movement also enhances accessibility for these web apps across all platforms. It was also during this time that mobile applications became stagnant. Your phone started to have <em>too</em> many applications, and not all of them were equally useful. Some are thin clients to web services, which you could access using your mobile web browser instead. </p>\n<p>Recognizing this, Progressive Web Applications, or PWA, came in to bridge the gap between native and web applications.</p>\n<h2 id=\"what-are-progressive-web-apps-pwas\" style=\"position:relative;\"><a href=\"#what-are-progressive-web-apps-pwas\" aria-label=\"what are progressive web apps pwas 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 are Progressive Web Apps (PWAs)?</h2>\n<p>First and foremost, PWAs are web applications. They run in web browsers, but also usually in webviews on smartphones. Compared to traditional websites that you would visit with a conventional web browser, progressive apps tend to be a little more low key. </p>\n<p>You may see one through a direct URL, but more commonly through a desktop/home screen icon on your phone, which takes you to a webview hosting the application. By extension, PWAs are now also distributed through app stores, standing alongside native apps.</p>\n<p>The webview itself may also be without or with minimal menu bars to provide an impression close to navigating a native application. Furthermore, progressive applications usually come with some offline viewing capabilities, allowing you to interact with the app even when you are offline or in limited network availability. This is implemented using service workers that stand in between network requests and the user and handle caching as well as push notifications, providing a user experience similar to native app caching.</p>\n<p>With that in mind, the idea behind <a href=\"/build-pwa-using-vanilla-javascript/\">PWA is to create applications</a> that would be most accessible, through the web, that also offers an experience as close to native applications as possible.</p>\n<h2 id=\"why-progressive-app\" style=\"position:relative;\"><a href=\"#why-progressive-app\" aria-label=\"why progressive app 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 Progressive App?</h2>\n<h3 id=\"ease-of-development-and-distribution\" style=\"position:relative;\"><a href=\"#ease-of-development-and-distribution\" aria-label=\"ease of development and distribution 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>Ease of development and distribution</h3>\n<p>Suppose you are a new company looking to create a mobile application for your product. If you would like to distribute your app on all major mobile platforms - namely both iOS and Android - you would then have to go through the development and distribution process for both. First off, you will need to learn the language to develop Android applications (Java, Kotlin) and then iOS (Objective-C, Swift), have the correct hardware to test and develop. </p>\n<p>This process will have you relearn everything about one platform on the other. Once you finish the initial product, you will have to maintain both codebases moving forward to complete this.</p>\n<p>With a progressive app, the process becomes a lot simpler. Your application lives within a browser, and hence only needs to be supported by the browser standards. As of now, support for PWAs is available across major browsers: Google Chrome, Mozilla Firefox, Apple Safari, Microsoft Edge, and Firefox (for Android). </p>\n<p>Your language is the language of the web: JavaScript. The choice is also yours to leverage the JavaScript platform you are most familiar with, be it React, Angular, or something completely different. The JavaScript codebase will then become the only codebase you need to maintain for the app.</p>\n<p>Alongside this, you also gain the advantage in the availability of the application. With PWA, your app will be available on the web, accessible by users across many platforms, including all mobile devices that have browser support.</p>\n<h3 id=\"portability\" style=\"position:relative;\"><a href=\"#portability\" aria-label=\"portability 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>Portability</h3>\n<p>PWAs live on the web; this means you do not need to download and store many executables and assets on your device, saving you precious storage space if you are using the app on your phone. This is especially useful when the native version of the application is simply a portal to a web service, which serves to make API calls and present data based on the user data on the server only, without performing any device-specific actions. The functionality of these applications is not inhibited by the browser's sandbox and thus make for perfect PWA candidates.</p>\n<h3 id=\"user-experience\" style=\"position:relative;\"><a href=\"#user-experience\" aria-label=\"user experience 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>User Experience</h3>\n<p>PWAs are designed to be responsive. Even though this depends largely on the individual developer of the application, a well designed and developed PWA should, in theory, provide a consistent experience across devices. With native apps, a lot of effort will be required to ensure that the user experience is uniform across multiple platforms. And even then, certain platforms will impose their own set of requirements on the UI look-and-feel, as well as the functionality of the app.</p>\n<h2 id=\"so-why-not-progressive-app\" style=\"position:relative;\"><a href=\"#so-why-not-progressive-app\" aria-label=\"so why not progressive app 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>So, why not Progressive App?</h2>\n<p>Progressive apps are a creative solution to smooth out the differences between a native app and the web, but not necessarily replace native apps. While it inherits all the advantages and features of the web, there are still certain disadvantages that need to be considered when deciding between a progressive app or a traditional native app.</p>\n<h3 id=\"leveraging-device-specific-features\" style=\"position:relative;\"><a href=\"#leveraging-device-specific-features\" aria-label=\"leveraging device specific features permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Leveraging device-specific features</h3>\n<p>For one thing, progressive apps are designed to be uniform across devices. This means it is not the technology's focus to make use of specialized features that are available only on select devices. Its feature set will be the lowest common denominator of the range of devices that it supports. With how diverse the feature sets are on modern devices like smartphones and tablets, with high-resolution cameras or fingerprint sensors, to name a few, it would be amiss for applications not to take advantage of these features. It follows that progressive apps are not ideal for specialized workflows, while their strength is in general purpose applications.</p>\n<h3 id=\"browser-compatibility\" style=\"position:relative;\"><a href=\"#browser-compatibility\" aria-label=\"browser compatibility 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>Browser compatibility</h3>\n<p>Compatibility is another big-ticket item. At a baseline level, PWA should be supported by all major browsers. However, platform differences still exist, where specific features are supported by one browser but not another, which will cause inconsistencies in behavior when the user switches from one device/platform to another. A prominent example of this being push notification support on iOS, which requires jumping through some hoops to make it work, as Apple does not support this directly. With that in mind, the subtle differences between browser support become a limitation similar to the difference between native app platforms itself.</p>\n<h3 id=\"distribution\" style=\"position:relative;\"><a href=\"#distribution\" aria-label=\"distribution 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>Distribution</h3>\n<p>For applications to reach the hands of the users, it needs a distribution platform. For native applications, the answer to this is straightforward: Apps are distributed through the native app store, be it Google Play Store or iOS App Store. However, for PWAs, it is more complicated. Distribution can be as simplistic as passing around the application's URL, and anyone who knows the link can access the app. This method has the added advantage due to Google and other search engines/web crawlers naturally picking up the app URL and returning it as a search result. </p>\n<p>However, this method is passive and requires the user to know the application beforehand. Developers might prefer the more traditional way of having the app listed in an app store, which is possible but requires them to jump through the same hoops as native applications, following all of the distributor guidelines, which removes its advantage compared to traditional apps.</p>\n<h2 id=\"to-pwa-or-not-to-pwa\" style=\"position:relative;\"><a href=\"#to-pwa-or-not-to-pwa\" aria-label=\"to pwa or not to pwa 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>To PWA, or not to PWA</h2>\n<p>So with everything considered, should you go the route of the progressive app? We do not aim to give a concrete answer, but instead a suggestion: If your application can be made a PWA, it is a good idea to do so. At the current moment, progressive apps are an evolution of web apps. Compared to the feature set that users are already familiar with in native apps, progressive apps still trail behind. </p>\n<p>This means that if the scope of the application is complex enough, PWA may not provide you with enough tools to do the job. With that said, if your application can be fully implemented with the set of tools that PWA provides, then going this route may net you added benefits that are unique to progressive apps. Are progressive apps the future? It definitely has the potential, but a large part of that answer depends on whether we can leverage its platform to build productive solutions with it today.</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":"February 04, 2021","updated_date":null,"description":"How do Native Apps compare to Progressive Web Apps, and which platform does your company use to communicate with your clients? read on!","title":"PWA vs Native App: Which one is Better for you?","tags":["Progressive App","PWA","JavaScript"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/fd52b7dab79665e5aa8e0074faec8e6c/58556/index.webp","srcSet":"/static/fd52b7dab79665e5aa8e0074faec8e6c/61e93/index.webp 200w,\n/static/fd52b7dab79665e5aa8e0074faec8e6c/1f5c5/index.webp 400w,\n/static/fd52b7dab79665e5aa8e0074faec8e6c/58556/index.webp 800w,\n/static/fd52b7dab79665e5aa8e0074faec8e6c/99238/index.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Nathan Nguyen","github":"nathannguyenn","avatar":null}}}},{"node":{"excerpt":"This blog will help you get started on deploying your REST API in Kubernetes. First, we'll set up a local Kubernetes cluster, then create a…","fields":{"slug":"/engineering/rest-api-kubernetes/"},"html":"<p>This blog will help you get started on deploying your REST API in Kubernetes. First, we'll set up a local Kubernetes cluster, then create a <a href=\"https://www.loginradius.com/blog/engineering/what-is-an-api/\">simple API</a> to deploy.</p>\n<p>There are already a lot of <a href=\"https://www.quora.com/What-are-the-best-resources-to-learn-Kubernetes\">free resources available</a> explaining basic Kubernetes concepts, so go check those out first if you haven't already. This blog is intended for beginners but assumes you already have a <a href=\"https://www.loginradius.com/blog/engineering/understanding-kubernetes/\">basic understanding of Kubernetes</a> and Docker concepts.</p>\n<h2 id=\"1-set-up-local-kubernetes\" style=\"position:relative;\"><a href=\"#1-set-up-local-kubernetes\" aria-label=\"1 set up local kubernetes 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. Set Up Local Kubernetes</h2>\n<p>There's a couple options for running Kubernetes locally, with the most popular ones including <a href=\"https://github.com/kubernetes/minikube\">minikube</a>, <a href=\"https://github.com/k3s-io/k3s\">k3s</a>, <a href=\"https://github.com/kubernetes-sigs/kind\">kind</a>, <a href=\"https://github.com/ubuntu/microk8s\">microk8s</a>. In this guide, any of these will work, but we will be using k3s because of the lightweight installation.</p>\n<p>Install <a href=\"https://github.com/rancher/k3d\">k3d</a>, which is a utility for running k3s. k3s will be running in Docker, so make sure you have that installed as well. We used k3d v4.0 in this blog.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash</span></code></pre>\n<p>Set up a cluster named test:</p>\n<ul>\n<li>The port flag is for mapping port 80 from our machine to port 80 on the k3s load balancer. This is needed later when we use ingress.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">k3d cluster create test -p &quot;80:80@loadbalancer&quot;</span></code></pre>\n<p>Optionally, check that your kubeconfig got updated and the current context is correct:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl config view</span>\n<span class=\"grvsc-line\">kubectl config current-context</span></code></pre>\n<p>Optionally, confirm that k3s is running in Docker. There should be two containers up, one for k3s and the other for load balancing:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker ps</span></code></pre>\n<p>Make sure that all the pods are running. If they are stuck in pending status, it may be that there is not enough disk space on your machine. You can get more information by using the describe command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl get pods -A</span>\n<span class=\"grvsc-line\">kubectl describe pods -A</span></code></pre>\n<p>There's a lot of kubectl commands you can try, so I recommend checking out the list of resources and being aware of their short names:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl api-resources</span></code></pre>\n<h2 id=\"2-create-a-simple-api\" style=\"position:relative;\"><a href=\"#2-create-a-simple-api\" aria-label=\"2 create a simple 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>2. Create a Simple API</h2>\n<p>We will create a simple API using Express.js.</p>\n<p>Set up the project:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mkdir my-backend-api && cd my-backend-api</span>\n<span class=\"grvsc-line\">touch server.js</span>\n<span class=\"grvsc-line\">npm init</span>\n<span class=\"grvsc-line\">npm i express --save</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// server.js</span>\n<span class=\"grvsc-line\">const express = require(&quot;express&quot;);</span>\n<span class=\"grvsc-line\">const app = express();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">app.get(&quot;/user/:id&quot;, (req, res) =&gt; {</span>\n<span class=\"grvsc-line\">  const id = req.params.id;</span>\n<span class=\"grvsc-line\">  res.json({</span>\n<span class=\"grvsc-line\">    id,</span>\n<span class=\"grvsc-line\">    name: `John Doe #${id}`</span>\n<span class=\"grvsc-line\">  });</span>\n<span class=\"grvsc-line\">});</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">app.listen(80, () =&gt; {</span>\n<span class=\"grvsc-line\">  console.log(&quot;Server running on port 80&quot;);</span>\n<span class=\"grvsc-line\">});</span></code></pre>\n<p>Optionally, you can try running it if you have Node.js installed and test the endpoint /user/{id} with curl:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">node server.js</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">// request:</span>\n<span class=\"grvsc-line\">curl http://localhost:80/user/123</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">// response: {&quot;id&quot;:&quot;123&quot;,&quot;name&quot;:&quot;John Doe #123&quot;}</span></code></pre>\n<p>Next, add a Dockerfile and .dockerignore:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// Dockerfile</span>\n<span class=\"grvsc-line\">FROM node:12</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">WORKDIR /usr/src/app</span>\n<span class=\"grvsc-line\">COPY package*.json ./</span>\n<span class=\"grvsc-line\">RUN npm i</span>\n<span class=\"grvsc-line\">COPY . .</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">EXPOSE 80</span>\n<span class=\"grvsc-line\">CMD [&quot;node&quot;, &quot;server.js&quot;]</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// .dockerignore</span>\n<span class=\"grvsc-line\">node_modules</span></code></pre>\n<p>Then, build the image and push it to the Docker Hub registry:</p>\n<ul>\n<li>If you want to skip this step, you can use the existing image <a href=\"https://hub.docker.com/r/andyy5/my-backend-api\">here</a>.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">docker build -t &lt;YOUR_DOCKER_ID&gt;/my-backend-api .</span>\n<span class=\"grvsc-line\">docker push &lt;YOUR_DOCKER_ID&gt;/my-backend-api</span></code></pre>\n<h2 id=\"3-deploy\" style=\"position:relative;\"><a href=\"#3-deploy\" aria-label=\"3 deploy 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. Deploy</h2>\n<p>Now, we deploy the image to our local Kubernetes cluster. We use the default namespace.</p>\n<p>Create a deployment:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl create deploy my-backend-api --image=andyy5/my-backend-api</span></code></pre>\n<ul>\n<li>Alternatively, create a deployment with a YAML file:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl create -f deployment.yaml</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// deployment.yaml</span>\n<span class=\"grvsc-line\">apiVersion: apps/v1</span>\n<span class=\"grvsc-line\">kind: Deployment</span>\n<span class=\"grvsc-line\">metadata:</span>\n<span class=\"grvsc-line\">  name: my-backend-api</span>\n<span class=\"grvsc-line\">  labels:</span>\n<span class=\"grvsc-line\">    app: my-backend-api</span>\n<span class=\"grvsc-line\">spec:</span>\n<span class=\"grvsc-line\">  replicas: 1</span>\n<span class=\"grvsc-line\">  selector:</span>\n<span class=\"grvsc-line\">    matchLabels:</span>\n<span class=\"grvsc-line\">      app: my-backend-api</span>\n<span class=\"grvsc-line\">  template:</span>\n<span class=\"grvsc-line\">    metadata:</span>\n<span class=\"grvsc-line\">      labels:</span>\n<span class=\"grvsc-line\">        app: my-backend-api</span>\n<span class=\"grvsc-line\">    spec:</span>\n<span class=\"grvsc-line\">      containers:</span>\n<span class=\"grvsc-line\">      - name: my-backend-api</span>\n<span class=\"grvsc-line\">        image: andyy5/my-backend-api</span></code></pre>\n<p>Create a service:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl expose deploy my-backend-api --type=ClusterIP --port=80</span></code></pre>\n<ul>\n<li>Alternatively, create a service with a YAML file:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl create -f service.yaml</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// service.yaml</span>\n<span class=\"grvsc-line\">apiVersion: v1</span>\n<span class=\"grvsc-line\">kind: Service</span>\n<span class=\"grvsc-line\">metadata:</span>\n<span class=\"grvsc-line\">  name: my-backend-api</span>\n<span class=\"grvsc-line\">  labels:</span>\n<span class=\"grvsc-line\">    app: my-backend-api</span>\n<span class=\"grvsc-line\">spec:</span>\n<span class=\"grvsc-line\">  type: ClusterIP</span>\n<span class=\"grvsc-line\">  ports:</span>\n<span class=\"grvsc-line\">  - port: 80</span>\n<span class=\"grvsc-line\">    protocol: TCP</span>\n<span class=\"grvsc-line\">    targetPort: 80</span>\n<span class=\"grvsc-line\">  selector:</span>\n<span class=\"grvsc-line\">    app: my-backend-api</span></code></pre>\n<p>Check that everything was created and the pod is running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl get deploy -A</span>\n<span class=\"grvsc-line\">kubectl get svc -A</span>\n<span class=\"grvsc-line\">kubectl get pods -A</span></code></pre>\n<p>Once the pod is running, the API is accessible within the cluster only. One quick way to verify the deployment from our localhost is by doing port forwarding:</p>\n<ul>\n<li>Replace the pod name below with the one in your cluster</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl port-forward my-backend-api-84bb9d79fc-m9ddn 3000:80</span></code></pre>\n<ul>\n<li>Now, you can send a curl request from your machine</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">curl http://localhost:3000/user/123</span></code></pre>\n<p>To correctly manage external access to the services in a cluster, we need to use ingress. Close the port-forwarding and let's expose our API by creating an ingress resource.</p>\n<ul>\n<li>An ingress controller is also required, but k3d by default deploys the cluster with a Traefik ingress controller (listening on port 80).</li>\n<li>Recall that when we created our cluster, we set a port flag with the value \"80:80@loadbalancer\". If you missed this part, go back and create your cluster again.</li>\n</ul>\n<p>Create an Ingress resource with the following YAML file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"21\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">kubectl create -f ingress.yaml</span>\n<span class=\"grvsc-line\">kubectl get ing -A</span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"22\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// ingress.yaml</span>\n<span class=\"grvsc-line\">apiVersion: networking.k8s.io/v1</span>\n<span class=\"grvsc-line\">kind: Ingress</span>\n<span class=\"grvsc-line\">metadata:</span>\n<span class=\"grvsc-line\">  name: my-backend-api</span>\n<span class=\"grvsc-line\">  annotations:</span>\n<span class=\"grvsc-line\">    ingress.kubernetes.io/ssl-redirect: &quot;false&quot;</span>\n<span class=\"grvsc-line\">spec:</span>\n<span class=\"grvsc-line\">  rules:</span>\n<span class=\"grvsc-line\">  - http:</span>\n<span class=\"grvsc-line\">      paths:</span>\n<span class=\"grvsc-line\">      - path: /user/</span>\n<span class=\"grvsc-line\">        pathType: Prefix</span>\n<span class=\"grvsc-line\">        backend:</span>\n<span class=\"grvsc-line\">          service:</span>\n<span class=\"grvsc-line\">            name: my-backend-api</span>\n<span class=\"grvsc-line\">            port:</span>\n<span class=\"grvsc-line\">              number: 80</span></code></pre>\n<ul>\n<li>Now try it out!</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"23\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">curl http://localhost:80/user/123</span></code></pre>\n<p>If you want to learn more on how to deploy using a managed Kubernetes service in the cloud, such as Google Kubernetes Engine, then check out the excellent guides on the <a href=\"https://kubernetes.io/docs/tutorials/stateless-application/expose-external-ip-address/\">official Kubernetes docs</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"February 03, 2021","updated_date":null,"description":"Beginner guide on how to create and deploy a REST API in local Kubernetes.","title":"How to Deploy a REST API in Kubernetes","tags":["Kubernetes"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.492537313432836,"src":"/static/3e013df11f99b320029a3e4aadafc0ea/58556/cover.webp","srcSet":"/static/3e013df11f99b320029a3e4aadafc0ea/61e93/cover.webp 200w,\n/static/3e013df11f99b320029a3e4aadafc0ea/1f5c5/cover.webp 400w,\n/static/3e013df11f99b320029a3e4aadafc0ea/58556/cover.webp 800w,\n/static/3e013df11f99b320029a3e4aadafc0ea/99238/cover.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Andy Yeung","github":null,"avatar":null}}}},{"node":{"excerpt":"E-commerce business is growing day by day as it saves time and cost for people traveling to meet or perform businesses in person. More…","fields":{"slug":"/engineering/electronic-identity-integration/"},"html":"<p>E-commerce business is growing day by day as it saves time and cost for people traveling to meet or perform businesses in person. More people are conducting business online by creating accounts using email or phone verification. This has posed a challenge for everyone to identify the persons who we are claiming online. Online hackers have used false Identity to deceive or defraud someone else. Hence, Electronic Identity ( eID) provides a way for businesses to verify a person's identity online and reduce the chances of Identity Fraud.</p>\n<h2 id=\"what-is-an-electronic-identity\" style=\"position:relative;\"><a href=\"#what-is-an-electronic-identity\" aria-label=\"what is an electronic identity 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 an electronic identity?</h2>\n<p>Electronic identity is an electronic card or device with a unique identity number issued by either a government agency or some banks. A consumer needs to go to the government agency or some banks and show valid identity documents. After the document verification, an Electronic Identity is issued to the consumer. Examples of e-IDs are Danish NemID, Swedish BankID, and Dutch DigiD.</p>\n<p>Most service providers such as financial institutions and insurance firms provide services online and are recognizing an opportunity in implementing eID due to strict Know Your Customer (KYC) and Anti-Money Laundering (AML) requirements.</p>\n<p>eIDs are used to authenticate consumers online across multiple platforms and services. eIDs also allow the consumers to sign documents online, and the companies can trust the signature as the electronic identity is issued by the government or banks based on physical identity documents. This is fast, convenient, and secure for the consumers as they are saved from completing registration forms for multiple services. Hence, this increases the conversion for the businesses. </p>\n<h2 id=\"integrating-eid-authentication-with-loginradius\" style=\"position:relative;\"><a href=\"#integrating-eid-authentication-with-loginradius\" aria-label=\"integrating eid authentication 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>Integrating eID authentication with LoginRadius</h2>\n<p>LoginRadius supports all the major industry federated SSO methods. Hence, you can integrate eID authentication with LoginRadius using some third application like Criipto, which supports the industry-standard SSO methods. Criipto allows the integration of an eID with the LoginRadius application using JWT SSO Login flow.  Jason Web Token ( JWT) is a signed token that transfers the information from one service to another securely. </p>\n<h3 id=\"prerequisite\" style=\"position:relative;\"><a href=\"#prerequisite\" aria-label=\"prerequisite 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>Prerequisite</h3>\n<ul>\n<li>A Criipto account ( you can create a free trial account )</li>\n<li>A LoginRadius application </li>\n<li>One of the desired electronic ID</li>\n</ul>\n<h3 id=\"register-your-loginradius-app-in-your-criipto-account\" style=\"position:relative;\"><a href=\"#register-your-loginradius-app-in-your-criipto-account\" aria-label=\"register your loginradius app in your criipto account 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>Register your LoginRadius app in your Criipto account</h3>\n<hr>\n<p>Please see the following steps to register your LoginRadius app in your Criipto account.</p>\n<ol>\n<li>Login in to your <a href=\"https://manage.criipto.id/login\">Criipto account</a>.</li>\n<li>Click + sign to add an application under the Applications tab.</li>\n<li>\n<p>Add the following information:\n<img src=\"/3791e451e2ca605de23570e590ae2e39/criipto-config1.webp\" alt=\"criipto config\"></p>\n<ul>\n<li>Name: Enter a name to identify your app in the Criipto.</li>\n<li>Domain: choose an available domain</li>\n<li>Callback URLs: Enter https://<LR appname>.hub.loginradius.com/access/jwt\n<img src=\"/d7a33776d082102bdca579cd9b35966f/criipto-config2.webp\" alt=\"criipto config\"></li>\n<li>Enable the desired eIDs</li>\n<li>Enable the <strong>Enable OAuth2 Code Flow</strong> under <strong>OpenID Connect</strong></li>\n<li>Click the Re-generate client secret button to generate a client secret. </li>\n<li>Select <strong>SignedJwt</strong> under <strong>User info response strategy</strong> </li>\n<li>Select <strong>compact</strong> under <strong>JWT property format</strong></li>\n<li>Enter the desired token time in <strong>Token lifetime</strong> under <strong>Advanced Options</strong>.</li>\n</ul>\n</li>\n<li>Click the <strong>save</strong> button.</li>\n</ol>\n<h3 id=\"configure-the-criipto-settings-in-the-loginradius\" style=\"position:relative;\"><a href=\"#configure-the-criipto-settings-in-the-loginradius\" aria-label=\"configure the criipto settings in the 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>Configure the Criipto settings in the LoginRadius</h3>\n<ol>\n<li>Login into the <a href=\"https://adminconsole.loginradius.com/\">Admin Console</a></li>\n<li>Navigate to Platform Configuration>Authentication Configuration>Custom IDPs>JWT Provider\n<img src=\"/08f84d337d1d3fc37302043e1e940987/LR-JWT-Config1.webp\" alt=\"JWT config\"></li>\n<li>Click <strong>+ Add A New Provider</strong> button highlighted on the above screen, and the following JWT configuration form fields will appear:\n<img src=\"/b49eb762379da71ae766c76ec1a26497/LR-JWT-Config2.webp\" alt=\"JWT config\"></li>\n<li>\n<p>Complete the following details in the JWT provider</p>\n<ul>\n<li>Enter a unique name under the <strong>Provider Name</strong>. This name will be displayed under the social login forms in the LoginRadius IDX page and on the social login form rendered by LoginRadius V2.js library on your application if the Include In Social Schema is selected while configuring the JWT app.</li>\n<li>Select RS256 under the JWT signing <strong>Algorithm</strong> used by your application ( the selected algorithm is used in encrypting your consumers' information in the JWT).</li>\n<li>Enter the JWT secret or certificate (depending on the chosen algorithm) in the <strong>Key</strong> text box.</li>\n<li>Clock Skew(Optional): Enter 0</li>\n<li>Expiration Time Difference (Optional): Enter 0</li>\n<li>Token Query Parameter Name (Optional): Enter id_token</li>\n<li>\n<p>Data Mapping:</p>\n<ul>\n<li>Select Field(Dropdown): Select the LoginRadius field ID field</li>\n<li>Profile Key: Enter the user identifier field name from the JWT ( please see <a href=\"https://docs.criipto.com/getting-started/token-contents/\">Token contents</a> for the JWT payload returned by an eID)</li>\n</ul>\n</li>\n<li>Enable Include In Social Schema</li>\n</ul>\n</li>\n<li>Click the <strong>Add</strong> button </li>\n</ol>\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":"January 29, 2021","updated_date":null,"description":"An electronic identity is an electronic card or device with a unique identity number issued by either a government agency or some banks.LoginRadius supports all the major industry federated SSO methods. Hence, you can integrate eID authentication with LoginRadius using some third application like Criipto, which supports the industry-standard SSO methods.","title":"Integration with electronic identity (eID) ","tags":["Electronic Identity","Bank ID","Criipto","LoginRadius"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/b916d567b9e41b342cccd7613d625bf6/8829b/Integration_with_eID.webp","srcSet":"/static/b916d567b9e41b342cccd7613d625bf6/61e93/Integration_with_eID.webp 200w,\n/static/b916d567b9e41b342cccd7613d625bf6/1f5c5/Integration_with_eID.webp 400w,\n/static/b916d567b9e41b342cccd7613d625bf6/8829b/Integration_with_eID.webp 680w","sizes":"(max-width: 680px) 100vw, 680px"}}},"author":{"id":"Jitender Agarwal","github":null,"avatar":null}}}},{"node":{"excerpt":"In C#, We have majorly two types of data types Value and Reference type. We can not assign a null value directly to the Value data type. In…","fields":{"slug":"/engineering/nullable-csharp/"},"html":"<p>\nIn C#, We have majorly two types of data types <em>Value</em> and <em>Reference</em> type. We can not assign a null value directly to the Value data type. In this case, C# 2.0 provides us the Nullable types to assign a value data type to null. </p>\n<h2 id=\"what-is-nullable-types\" style=\"position:relative;\"><a href=\"#what-is-nullable-types\" aria-label=\"what is nullable types 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 Nullable types?</h2>\n<p>As described above, The Nullable types used to assign the null value to the value data type. That means we can assign a null value directly to a variable of the value data type. We can declare null value using <code>Nullable&#x3C;T></code> where <code>T</code> is a type like an int, float, bool, etc.</p>\n<p>Nullable types represent the Null value as well the actual range of that data type. Like the <strong>int</strong> data type can hold the value from <code>-2147483648</code> to <code>2147483647</code> but a <strong>Nullable int</strong> can hold the value <code>null</code> and range from <code>-2147483648</code> to <code>2147483647</code></p>\n<h2 id=\"how-to-declare-nullable-types\" style=\"position:relative;\"><a href=\"#how-to-declare-nullable-types\" aria-label=\"how to declare nullable types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to declare Nullable types</h2>\n<p>There are two ways to declare Nullable types.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">example</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>OR</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\">? </span><span class=\"mtk12\">Example</span><span class=\"mtk1\">;</span></span></code></pre>\n<h2 id=\"properties-of-nullable-types\" style=\"position:relative;\"><a href=\"#properties-of-nullable-types\" aria-label=\"properties of nullable types 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>Properties of Nullable types</h2>\n<p>Nullable types have two properties.</p>\n<ol>\n<li>HasValue</li>\n<li>Value</li>\n</ol>\n<p><strong>HasValue</strong>: This property returns a bool value based on that if the Nullable variable has some value or not. If the variable has some value, then it will return true; otherwise, it will return false if it doesn’t have value or it’s null.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">null</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">a</span><span class=\"mtk1\">.</span><span class=\"mtk12\">HasValue</span><span class=\"mtk1\">); </span><span class=\"mtk3\">// Print False</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">b</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">9</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">b</span><span class=\"mtk1\">.</span><span class=\"mtk12\">HasValue</span><span class=\"mtk1\">); </span><span class=\"mtk3\">// Print True</span></span></code></pre>\n<p><strong>Value</strong>: This property gives the value of the Nullable type variable. If the variable has some value, it will return the value; else, it will give the runtime <code>InvalidOperationException</code> <a href=\"https://www.loginradius.com/blog/engineering/exception-handling-in-csharp/\">exception when the variable</a> value is null.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">null</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">a</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Value</span><span class=\"mtk1\">); </span><span class=\"mtk3\">// Gives run time exception of type &#39;InvalidOperationException&#39;</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">b</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">9</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">b</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Value</span><span class=\"mtk1\">); </span><span class=\"mtk3\">// Print 9</span></span></code></pre>\n<h2 id=\"method-of-nullable-types\" style=\"position:relative;\"><a href=\"#method-of-nullable-types\" aria-label=\"method of nullable types 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>Method of Nullable types</h2>\n<p><strong>GetValueOrDefault()</strong>: This method returns the actually assigned value of the Nullable type variable if the value is not null, and if the variable value is null, then it will give the default value of that data type. Here is the example code</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">9</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">a</span><span class=\"mtk1\">.</span><span class=\"mtk11\">GetValueOrDefault</span><span class=\"mtk1\">()); </span><span class=\"mtk3\">// Returns 9</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">Nullable</span><span class=\"mtk1\">&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">null</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">a</span><span class=\"mtk1\">.</span><span class=\"mtk11\">GetValueOrDefault</span><span class=\"mtk1\">()); </span><span class=\"mtk3\">// Returns 0</span></span></code></pre>\n<h2 id=\"rules-of-using-nullable-types\" style=\"position:relative;\"><a href=\"#rules-of-using-nullable-types\" aria-label=\"rules of using nullable types 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>Rules of using Nullable types:</h2>\n<p>To use the Nullable type as a local variable, it should be declared first; it will give a compile-time error. This rule is similar to the value data type.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\">? </span><span class=\"mtk12\">b</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">b</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Value</span><span class=\"mtk1\">); </span><span class=\"mtk3\">//Compile time error &#39;use of unassigned local variable b&#39;</span></span></code></pre>\n<p>If the Nullable variable is a property in a class and after that, if we are accessing that Nullable variable, then it will not give any error because, in the class variable, it is declared as <code>null</code> automatically.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Test</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\">? </span><span class=\"mtk12\">B</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Program</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">static</span><span class=\"mtk1\"> </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Main</span><span class=\"mtk1\">(</span><span class=\"mtk4\">string</span><span class=\"mtk1\">[] </span><span class=\"mtk12\">args</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Test</span><span class=\"mtk1\">().</span><span class=\"mtk12\">B</span><span class=\"mtk1\">); </span><span class=\"mtk3\">// No compile time error</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<h2 id=\"null-coalescing-operator-\" style=\"position:relative;\"><a href=\"#null-coalescing-operator-\" aria-label=\"null coalescing operator  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>null coalescing operator (??)</h2>\n<p>We can not assign the Nullable type variable value to the non-nullable type variable directly. As in the example below, if we try to assign the value, it will give the compile-time error.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\">? </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">10</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\"> </span><span class=\"mtk12\">b</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">a</span><span class=\"mtk1\">;</span><span class=\"mtk3\">//Compile time error `Cannot implicitly convert type &#39;int?&#39; to &#39;int&#39;. An explicit conversion exists (are you missing a cast?)`</span></span></code></pre>\n<p><strong>Note</strong>: We can use compare operators <code>==</code> and <code>!=</code> operator with Nullable type variables and non Nullable type variables.</p>\n<p>For the Nullable variable, we can use the null coalescing operator (??) to check if the variable value is <code>null</code> or not. Then we can assign the non-nullable type variable value according to that. This operator can be used when we are unsure that at run time if that Nullable variable's value is changed according to our logic or not. Here is an example of that</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"c#\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\">? </span><span class=\"mtk12\">a</span><span class=\"mtk1\">=</span><span class=\"mtk4\">null</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\"> </span><span class=\"mtk12\">b</span><span class=\"mtk1\">=</span><span class=\"mtk12\">a</span><span class=\"mtk1\">?? </span><span class=\"mtk7\">10</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">Console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">WriteLine</span><span class=\"mtk1\">(</span><span class=\"mtk12\">b</span><span class=\"mtk1\">);  </span><span class=\"mtk3\">// Prints 10</span></span></code></pre>\n<p>In the above example, if the variable a value is null,, it will assign the value 10 to b variable. In that case, b is assigned with value 10, and the printed value will be 10.</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>In this article, We have discussed the Nullable types, and it's properties and methods. The main advantage of using the Nullable types is that we can store the Null value in a column of a database using this type. If you want to learn more about C# here is an article written by me on <a href=\"https://www.loginradius.com/blog/engineering/enum-csharp/\">How to Use Enum in C#</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"January 29, 2021","updated_date":null,"description":"Nullable is a term in C# that allows an extra value null to be owned by a form. We will learn in this article how to work with Nullable types in C#.","title":"How to Work with Nullable Types in C#","tags":["C#","Nullable"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/41c1ba90d916c8835ab6561b428a152d/58556/coverimage.webp","srcSet":"/static/41c1ba90d916c8835ab6561b428a152d/61e93/coverimage.webp 200w,\n/static/41c1ba90d916c8835ab6561b428a152d/1f5c5/coverimage.webp 400w,\n/static/41c1ba90d916c8835ab6561b428a152d/58556/coverimage.webp 800w,\n/static/41c1ba90d916c8835ab6561b428a152d/210c1/coverimage.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Hemant Manwani","github":"hemant404","avatar":null}}}},{"node":{"excerpt":"Many of us have to choose between Merge and Rebase as a Developer. Here I'll explain what merge and rebase are, why you should use them, and…","fields":{"slug":"/engineering/git-rebase-vs-git-merge/"},"html":"<p>Many of us have to choose between Merge and Rebase as a Developer. Here I'll explain what merge and rebase are, why you should use them, and how to do so.</p>\n<p>The same function is fulfilled by Git Merge and Git Rebase. They are built to incorporate adjustments into one from different divisions. Although the end objective is the same, it is done in various ways by those two approaches, and it is useful to know the difference as you become a better developer of software.</p>\n<h2 id=\"what-are-git-merge-and-git-rebase\" style=\"position:relative;\"><a href=\"#what-are-git-merge-and-git-rebase\" aria-label=\"what are git merge and git rebase 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 are Git Merge and Git Rebase?</h2>\n<p><em>Git Merge and Git Rebase are both used to combine the changes of branches but in a distinct way.</em></p>\n<p><strong>Git Merge</strong> - For developers using version control systems, merging is a prevalent method. Merging takes the contents of a source branch and combines them with a target branch, to be more precise. Only the <a href=\"https://medium.com/@loginradius/how-to-fetch-a-remote-branch-using-git-5c0f6d28264d\">target branch is updated</a> in this process. The history of the source branch remains similar.</p>\n<p><strong>Git Rebase</strong> - Another way to integrate modifications from one branch to another is by Rebase. Rebase compresses all the modifications into a single patch. The patch is then inserted into the target branch.</p>\n<h3 id=\"git-merge\" style=\"position:relative;\"><a href=\"#git-merge\" aria-label=\"git merge 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>Git Merge</h3>\n<p>Combine multiple branch histories together.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">  A---B---C feature</span>\n<span class=\"grvsc-line\"> /</span>\n<span class=\"grvsc-line\">D---E---F---G master </span></code></pre>\n<p>if we are merging feature and master branch, then it would be</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">  A---B---C feature</span>\n<span class=\"grvsc-line\"> /               \\</span>\n<span class=\"grvsc-line\">D---E---F---G---H master</span></code></pre>\n<p><strong>Commands</strong> for merging feature and master branch</p>\n<p><code>git checkout feature</code>\n<code>git merge master</code></p>\n<p><strong>Note:</strong></p>\n<ul>\n<li>merge executes only one new commit</li>\n<li>if the feature branch has a completely different development </li>\n<li>If you get conflict while merging\n<code>resolve conflicts</code>\n<code>git add (changes)</code>\n<code>git merge --continue</code></li>\n</ul>\n<h3 id=\"git-rebase\" style=\"position:relative;\"><a href=\"#git-rebase\" aria-label=\"git rebase 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>Git Rebase</h3>\n<p>Reapply commits on top of the base branch</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">   A---B---C feature</span>\n<span class=\"grvsc-line\"> /</span>\n<span class=\"grvsc-line\">D---E---F---G master</span></code></pre>\n<p>if we are rebasing the feature branch onto the master branch, then it would be</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">\t   A&#39;--B&#39;--C&#39; feature</span>\n<span class=\"grvsc-line\">\t /</span>\n<span class=\"grvsc-line\">\tD---E---F---G master</span></code></pre>\n<p><strong>Commands</strong> for merging feature and master branch</p>\n<p><code>git checkout feature</code>\n<code>git rebase master</code></p>\n<p><strong>Note:</strong> </p>\n<ul>\n<li>rebase typically executes multiple (number of commits in current branch).</li>\n<li>If you get conflict while rebasing\n<code>resolve conflicts</code>\n<code>git add (changes)</code>\n<code>git rebase --continue</code></li>\n</ul>\n<h2 id=\"when-to-use-git-rebase-or-git-merge\" style=\"position:relative;\"><a href=\"#when-to-use-git-rebase-or-git-merge\" aria-label=\"when to use git rebase or git merge 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>When to use Git Rebase or Git Merge</h2>\n<h3 id=\"choose-merge\" style=\"position:relative;\"><a href=\"#choose-merge\" aria-label=\"choose merge 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>Choose Merge</h3>\n<ul>\n<li>whenever we want to add changes of a feature branch back into the base branch.</li>\n<li>if you want to keep the same history rather than rewrite it.</li>\n<li>if you want to revert the changes quickly</li>\n</ul>\n<h3 id=\"choose-rebase\" style=\"position:relative;\"><a href=\"#choose-rebase\" aria-label=\"choose rebase 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>Choose Rebase</h3>\n<ul>\n<li>whenever we want to add changes of a base branch back to a feature branch.</li>\n<li>squash multiple commits</li>\n<li>reiterate each commit and update the changes</li>\n<li>reverting rebase would be very difficult</li>\n</ul>\n<h3 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</h3>\n<p>I hope some perspectives on Git merge and Git rebase have been provided by this description. The strategy of merge vs rebase is still debatable. But maybe this article will help to dispel your doubts and encourage you to take an approach that works for your team. Here are few articles posted by me that will help you in learning few more things in Git:</p>\n<ol>\n<li><a href=\"https://www.loginradius.com/blog/engineering/git-cherry-pick/\">How to use Git Cherry Pick</a></li>\n<li><a href=\"https://www.loginradius.com/blog/engineering/git-pull-force/\">How to Perform a Git Force Pull</a></li>\n</ol>\n<p>Do comment on the subjects that you would like me to write about in the coming weeks :)</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":"January 27, 2021","updated_date":null,"description":"In this post, I will give you a walkthrough on merge and rebase, comparing Git rebase vs. Git merge to find out the similarities and differences.","title":"Git merge vs. Git Rebase: What's the difference?","tags":["GIT"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/23c891d4a8760d428bfc6f05aa86f387/58556/merge.webp","srcSet":"/static/23c891d4a8760d428bfc6f05aa86f387/61e93/merge.webp 200w,\n/static/23c891d4a8760d428bfc6f05aa86f387/1f5c5/merge.webp 400w,\n/static/23c891d4a8760d428bfc6f05aa86f387/58556/merge.webp 800w,\n/static/23c891d4a8760d428bfc6f05aa86f387/99238/merge.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Abhimanyu Singh Rathore","github":"abhir9","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":90,"currentPage":16,"type":"//engineering//","numPages":53,"pinned":"5c425581-f474-5ae9-abe7-cf5342db2aaa"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}