{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected 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 is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers 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>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso 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>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso 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>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies 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>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips 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>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access 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>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets 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>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm 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>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out 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 is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in 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>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary 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>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references 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>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\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":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},{"node":{"excerpt":"First, let's understand: What is SSO, and why should you use it? What is OIDC, and why is it used for authentication? How can you leverage…","fields":{"slug":"/engineering/implementing-oidc-sso-loginradius-as-identity-provider/"},"html":"<p>First, let's understand:</p>\n<ul>\n<li>What is SSO, and why should you use it?</li>\n<li>What is OIDC, and why is it used for authentication?</li>\n<li>How can you leverage LoginRadius as an identity provider?</li>\n</ul>\n<p><strong>SSO stands for Single Sign-On</strong>. It's an authentication process that allows a user to access multiple applications or systems with one set of login credentials (username and password). Instead of requiring users to log in separately to each application, SSO enables them to log in once and gain access to all the connected systems without needing to re-enter their credentials.</p>\n<p><strong>OpenID Connect (OIDC)</strong> is a protocol that builds on OAuth 2.0 to ensure secure user authentication and authorization. It adds an identity layer to OAuth 2.0, allowing applications to confirm a user's identity and gather basic profile information. OIDC utilizes JSON Web Tokens (JWTs) for these functions, aligning with OAuth 2.0's token acquisition methods. This integration enables seamless user authentication across different platforms, supporting features like single sign-on, where users can access multiple applications with one set of credentials managed by an identity provider.</p>\n<h2 id=\"what-is-loginradius-ciam\" style=\"position:relative;\"><a href=\"#what-is-loginradius-ciam\" aria-label=\"what is loginradius ciam 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 LoginRadius CIAM?</h2>\n<p>LoginRadius is a high-performance, scalable identity and access management platform focused on customer-facing use cases. It offers comprehensive features and capabilities to help you implement user authentication and authorization and manage user data with built-in workflows and security controls. </p>\n<p>On these lines, LoginRadius offers built-in support for OIDC and the use of OIDC to implement SSO.</p>\n<p>First, you need to create an OIDC application in LoginRadius to tailor user claim fields effortlessly. You can fine-tune these customizable user claims through LoginRadius' user-friendly interface. Subsequently, you can seamlessly integrate these claims into the token, enabling streamlined extraction and utilization within the application ecosystem.</p>\n<p>In essence, LoginRadius facilitates the setup of OIDC applications and offers customization capabilities through its intuitive interface. This ensures efficient management of user claims, ultimately contributing to a more personalized and secure authentication experience.</p>\n<p>After setting up the OIDC app from the LoginRadius dashboard, you'll use the <a href=\"https://github.com/coreos/go-oidc\"><code>go-oidc</code> library</a> to configure our provider further and configure the oidc connect.</p>\n<h2 id=\"setting-up-oidc-application-in-loginradius\" style=\"position:relative;\"><a href=\"#setting-up-oidc-application-in-loginradius\" aria-label=\"setting up oidc application in 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>Setting Up OIDC Application in LoginRadius</h2>\n<p>Go to <a href=\"https://adminconsole.loginradius.com/platform-configuration/access-configuration/federated-sso/openid-connect\">OIDC Application Configuration</a> and click on <strong>Add App button</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 42.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHZsJIX/8QAFhABAQEAAAAAAAAAAAAAAAAAACIh/9oACAEBAAEFAqU1/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGhAAAgIDAAAAAAAAAAAAAAAAAAEhMTKBof/aAAgBAQAGPwKUtMx6Uf/EABgQAAMBAQAAAAAAAAAAAAAAAAABEfGh/9oACAEBAAE/IbwsCgT3P//aAAwDAQACAAMAAAAQf8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAgEFAAAAAAAAAAAAAAABABFhIXGBkdH/2gAIAQEAAT8QByAsN7xidPIo1Jxn/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"OIDC App Configuration\"\n        title=\"OIDC App Configuration\"\n        src=\"/static/00116a4848c99cc03a6b816280de4dcd/212bf/OIDC-App.jpg\"\n        srcset=\"/static/00116a4848c99cc03a6b816280de4dcd/6aca1/OIDC-App.jpg 650w,\n/static/00116a4848c99cc03a6b816280de4dcd/212bf/OIDC-App.jpg 768w,\n/static/00116a4848c99cc03a6b816280de4dcd/e2c35/OIDC-App.jpg 2399w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Enter the <strong>App name</strong> and click one of the following:</p>\n<p><strong>Native App</strong>, <strong>Single page App</strong> or <strong>Web App</strong> according to your application.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.769230769230774%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAW2RPIjA/8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIDAAQR/9oACAEBAAEFAoIKMeeYGmxUmj+b/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAgEFAAAAAAAAAAAAAAAAAAExAhAhkaH/2gAIAQEABj8CaqXRzsgwTb//xAAaEAEAAgMBAAAAAAAAAAAAAAABABEQIVFB/9oACAEBAAE/IdAINVDEFw7lsMV1qOQ+eY//2gAMAwEAAgADAAAAEJDP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHRABAQABBAMAAAAAAAAAAAAAAREAITFBUWGB0f/aAAgBAQABPxBRRdUK2cZYtCXcC94Iao9mWkGHQefOVUChI+YbZ//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"OIDC App Setup\"\n        title=\"OIDC App Setup\"\n        src=\"/static/8a90565da5b70292e876657c74b5cf22/212bf/App-Setup.jpg\"\n        srcset=\"/static/8a90565da5b70292e876657c74b5cf22/6aca1/App-Setup.jpg 650w,\n/static/8a90565da5b70292e876657c74b5cf22/212bf/App-Setup.jpg 768w,\n/static/8a90565da5b70292e876657c74b5cf22/6f74a/App-Setup.jpg 2403w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>After clicking the <strong>Create</strong> button, you'll get the OIDC application configuration page. This page contains details like your application's <strong>Client ID</strong> and <strong>Client Secret</strong>, which are necessary for setting up the OIDC provider and configuration when you code in Golang.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHtawyhB//EABYQAAMAAAAAAAAAAAAAAAAAAAESIP/aAAgBAQABBQINX//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAAMBAAAAAAAAAAAAAAAAABEgIoH/2gAIAQEABj8CoY3/xAAYEAADAQEAAAAAAAAAAAAAAAAAARFREP/aAAgBAQABPyFdOdURT//aAAwDAQACAAMAAAAQg8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAgEFAAAAAAAAAAAAAAABABEhEDFBccH/2gAIAQEAAT8QsNgvYSu7YU490ViPK8y0/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"OIDC APP Credentials\"\n        title=\"OIDC APP Credentials\"\n        src=\"/static/1461fbca24c61616613333e417d8ef5a/212bf/App-Credentials.jpg\"\n        srcset=\"/static/1461fbca24c61616613333e417d8ef5a/6aca1/App-Credentials.jpg 650w,\n/static/1461fbca24c61616613333e417d8ef5a/212bf/App-Credentials.jpg 768w,\n/static/1461fbca24c61616613333e417d8ef5a/e752a/App-Credentials.jpg 2389w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"upon-reaching-the-configuration-page-for-your-oidc-application-youll-encounter-a-variety-of-fields-ripe-for-customization\" style=\"position:relative;\"><a href=\"#upon-reaching-the-configuration-page-for-your-oidc-application-youll-encounter-a-variety-of-fields-ripe-for-customization\" aria-label=\"upon reaching the configuration page for your oidc application youll encounter a variety of fields ripe for customization 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>Upon reaching the configuration page for your OIDC Application, you'll encounter a variety of fields ripe for customization:</h4>\n<ol>\n<li><strong>Algorithm</strong>: Presently, we offer support for <strong>rs256</strong>.</li>\n<li><strong>Grant Type</strong>: Options include authorization code, implicit, password creds, etc.</li>\n<li>You can tailor settings for <strong>Token Expiry</strong>, <strong>Refresh Token</strong>, and <strong>TTL</strong> to suit your needs.</li>\n<li><strong>Data Mapping</strong>: Define fields or properties to be included in the data response.</li>\n<li><strong>Metadata</strong>: Incorporate static, non-profile values into the data response.</li>\n<li>Define the Scope for Management API.</li>\n</ol>\n<p>This array of configurable options empowers you to fine-tune your OIDC Application according to your specific requirements.</p>\n<h2 id=\"whitelisting-the-domain-of-your-application\" style=\"position:relative;\"><a href=\"#whitelisting-the-domain-of-your-application\" aria-label=\"whitelisting the domain of your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Whitelisting the Domain of Your Application</h2>\n<p>To ensure seamless redirection of requests and successful callbacks to your endpoint, add your application's domain to the whitelist. This will authorize the redirection process and prevent failures when calling the callback endpoint.</p>\n<h4 id=\"to-access-web-apps-in-deployment-follow-these-steps\" style=\"position:relative;\"><a href=\"#to-access-web-apps-in-deployment-follow-these-steps\" aria-label=\"to access web apps in deployment follow these 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>To access Web Apps in Deployment, follow these steps:</h4>\n<ol>\n<li>Navigate to the Deployment section from the Dashboard.</li>\n<li>Once in Deployment, select the Apps tab.</li>\n<li>From there, choose Web Apps.</li>\n</ol>\n<h4 id=\"now-to-add-a-new-site\" style=\"position:relative;\"><a href=\"#now-to-add-a-new-site\" aria-label=\"now to add a new site 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>Now, to add a new site:</h4>\n<ol>\n<li>Click on the <strong>Add New Site</strong> button.</li>\n<li>Enter the domain name of the website (example: \"<code>https://localhost:8080</code>\").</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 42.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHasEgV/8QAFxAAAwEAAAAAAAAAAAAAAAAAABAREv/aAAgBAQABBQKZVP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAAIDAAAAAAAAAAAAAAAAAAAxARCR/9oACAEBAAY/AnO0j//EABoQAAICAwAAAAAAAAAAAAAAAAABEVEhMYH/2gAIAQEAAT8hSZbLkcY2uf/aAAwDAQACAAMAAAAQCA//xAAWEQEBAQAAAAAAAAAAAAAAAAAAIRH/2gAIAQMBAT8Q2q//xAAVEQEBAAAAAAAAAAAAAAAAAAAQQf/aAAgBAgEBPxCH/8QAGhAAAgIDAAAAAAAAAAAAAAAAAREAITFhgf/aAAgBAQABPxBuBWVwceJcACgTc//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Whitelisting Domain Name\"\n        title=\"Whitelisting Domain Name\"\n        src=\"/static/831a186ed00cc5a79276211572734129/212bf/Whitelisting-Domain.jpg\"\n        srcset=\"/static/831a186ed00cc5a79276211572734129/6aca1/Whitelisting-Domain.jpg 650w,\n/static/831a186ed00cc5a79276211572734129/212bf/Whitelisting-Domain.jpg 768w,\n/static/831a186ed00cc5a79276211572734129/e2c35/Whitelisting-Domain.jpg 2399w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"whitelisting-domain-from-oidc-application-configuration\" style=\"position:relative;\"><a href=\"#whitelisting-domain-from-oidc-application-configuration\" aria-label=\"whitelisting domain from oidc application configuration 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>Whitelisting Domain from OIDC Application Configuration</h3>\n<p>LoginRadius lets you uniquely identify the redirect URLs for individual OIDC applications:</p>\n<ul>\n<li>When setting the configuration of the OIDC Application, you can specify the redirect URL of your backend,\nand it will be whitelisted.</li>\n<li>The field name is <strong>Login Redirect URL</strong>.</li>\n</ul>\n<h2 id=\"setting-up-the-provider-object-and-the-oauthconfig-with-the-loginradius-oidc-app-credentials\" style=\"position:relative;\"><a href=\"#setting-up-the-provider-object-and-the-oauthconfig-with-the-loginradius-oidc-app-credentials\" aria-label=\"setting up the provider object and the oauthconfig with the loginradius oidc app credentials permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting Up the Provider Object and the OAuthconfig with the Loginradius OIDC App Credentials</h2>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">provider</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk11\">NewProvider</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;`https://api.loginradius.com/{oidcappname}&quot;</span><span class=\"mtk1\">)</span><span class=\"mtk8\">`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">if err != nil {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    // handle error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">// Configure an OpenID Connect aware OAuth2 client.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">oauth2Config := oauth2.Config{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    ClientID:     your-oidc-clientID,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    ClientSecret: your-oidc-clientSecret</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    RedirectURL:  redirectURL,</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    // Discovery returns the OAuth2 endpoints.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    Endpoint: provider.Endpoint(),</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    // &quot;openid&quot; is a required scope for OpenID Connect flows.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">    Scopes: []string{oidc.ScopeOpenID, &quot;profile&quot;, &quot;email&quot;},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">}</span></span></code></pre>\n<p>When setting up a new provider, you'll need to input the LoginRadius OIDC App URL, typically in this format: <code>https://{siteUrl}/service/oidc/{OidcAppName}</code></p>\n<p>To seamlessly integrate this with your Go backend, create two essential APIs for setting up and configuring <code>go-oidc</code>:</p>\n<ol>\n<li><strong>Login Endpoint</strong>: This endpoint initiates the authentication process and redirects to the callback endpoint with the authorization code.</li>\n<li><strong>Callback Endpoint</strong>: Here, the authorization code received from the login endpoint is exchanged for an access token. Additionally, this endpoint extracts user claims from the access token.</li>\n</ol>\n<p>By establishing these APIs, your Go backend efficiently handles the authentication flow, ensuring a smooth user experience while securely managing user identity and access.</p>\n<h2 id=\"handle-the-callback-hit\" style=\"position:relative;\"><a href=\"#handle-the-callback-hit\" aria-label=\"handle the callback hit 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>Handle the Callback Hit</h2>\n<p>Handle the callback hit that exchanged the authorization token for the access token:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">verifier</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">provider</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Verifier</span><span class=\"mtk1\">(&</span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Config</span><span class=\"mtk1\">{</span><span class=\"mtk12\">ClientID:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">clientID</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleOAuth2Callback</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\"> *</span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">context</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Verify state and errors.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    authCode := </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk11\">query</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;code&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">oauth2Token</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">oauth2Config</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Exchange</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authCode</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> != </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// handle error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Extract the ID Token from the OAuth2 token.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">rawIDToken</span><span class=\"mtk1\">, ok := </span><span class=\"mtk12\">oauth2Token</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Extra</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;id_token&quot;</span><span class=\"mtk1\">).(</span><span class=\"mtk12\">string</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> !</span><span class=\"mtk12\">ok</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// handle missing token</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Parse and verify ID Token payload.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">idToken</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">verifier</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Verify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">rawIDToken</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> != </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// handle error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Extract custom claims</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">claims</span><span class=\"mtk1\"> struct {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">Email</span><span class=\"mtk1\">    </span><span class=\"mtk12\">string</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`json:&quot;email&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">Verified</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bool</span><span class=\"mtk1\">   </span><span class=\"mtk8\">`json:&quot;email_verified&quot;`</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err := </span><span class=\"mtk12\">idToken</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Claims</span><span class=\"mtk1\">(&</span><span class=\"mtk12\">claims</span><span class=\"mtk1\">); </span><span class=\"mtk12\">err</span><span class=\"mtk1\"> != </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// handle 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<p>For both endpoints, let's review a sample backend server with implementation in <a href=\"https://github.com/gin-gonic/gin\">Gin Golang</a>.</p>\n<h2 id=\"gin-golang-code\" style=\"position:relative;\"><a href=\"#gin-golang-code\" aria-label=\"gin golang code 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>Gin Golang Code</h2>\n<p>For OIDC integration with the Go backend, you'll implement it using the <a href=\"https://github.com/coreos/go-oidc\">coreos/go-oidc</a> library (feel free to check it out). This library provides comprehensive support for OIDC, allowing to easily verify tokens, extract user claims, and validate ID tokens. Its features ensure secure authentication and seamless integration with various OIDC providers.</p>\n<p>With the <code>go-oidc</code> library, you can efficiently implement OIDC authentication in the Go backend, guaranteeing users a smooth and secure authentication process.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">go get github.com/coreos/go-oidc/v3/oidc</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">package</span><span class=\"mtk1\"> </span><span class=\"mtk12\">main</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">import</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;encoding/json&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;fmt&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;io&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;log&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;net/http&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;os&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/coreos/go-oidc/v3/oidc&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;github.com/gin-gonic/gin&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk8\">&quot;golang.org/x/oauth2&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Define global OAuth2 configuration and OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">oauthConfig</span><span class=\"mtk1\"> = &</span><span class=\"mtk12\">oauth2</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Config</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tClientID:     </span><span class=\"mtk8\">&quot;your-client-id&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">// Replace with your LoginRadius Client ID</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tRedirectURL:  </span><span class=\"mtk8\">&quot;http://localhost:8080/api/callback&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tClientSecret: </span><span class=\"mtk8\">&quot;your-client-secret&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">// Replace with your LoginRadius Client Secret</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tScopes:       []</span><span class=\"mtk12\">string</span><span class=\"mtk1\">{</span><span class=\"mtk8\">&quot;user&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">globalProvider</span><span class=\"mtk1\">   *</span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Provider</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">globalOuthConfig</span><span class=\"mtk1\"> *</span><span class=\"mtk12\">oauth2</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Config</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Server struct holds interfaces like HTTP server, DBHelper, ServerProvider, MongoDB client, etc.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Server</span><span class=\"mtk1\"> struct {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// InitializeOAuthConfig sets up the global OAuth2 configuration and OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">InitializeOAuthConfig</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Create a new OIDC provider using the OAuth2 endpoint and OIDC provider URL.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">provider</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk11\">NewProvider</span><span class=\"mtk1\">(</span><span class=\"mtk12\">context</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Background</span><span class=\"mtk1\">(), </span><span class=\"mtk8\">&quot;https://&lt;siteUrl&gt;/service/oidc/&lt;OidcAppName&gt;&quot;</span><span class=\"mtk1\">) </span><span class=\"mtk3\">// Replace with your OIDC Provider URL</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\">!= </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Fatalf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Failed to create new provider: %v&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">globalProvider</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">provider</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Set up the OAuth2 configuration with the client ID, secret, redirect URL, and scopes.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\toauth2Config := &</span><span class=\"mtk12\">oauth2</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Config</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tClientID:     </span><span class=\"mtk12\">oauthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ClientID</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tClientSecret: </span><span class=\"mtk12\">oauthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ClientSecret</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tRedirectURL:  </span><span class=\"mtk12\">oauthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk12\">RedirectURL</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tEndpoint:     </span><span class=\"mtk12\">provider</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Endpoint</span><span class=\"mtk1\">(),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\tScopes:       []</span><span class=\"mtk12\">string</span><span class=\"mtk1\">{</span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ScopeOpenID</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;profile&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">globalOuthConfig</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">oauth2Config</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// StartLoginProcess initiates the login process by redirecting the user to the OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">StartLoginProcess</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\"> *</span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Context</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Generate the authorization URL for the OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tauthURL := </span><span class=\"mtk12\">globalOuthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk11\">AuthCodeURL</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;state&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Nonce</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Redirect the user to the OIDC provider for authentication.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">http</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Redirect</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Writer</span><span class=\"mtk1\">, </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authURL</span><span class=\"mtk1\">, </span><span class=\"mtk12\">http</span><span class=\"mtk1\">.</span><span class=\"mtk12\">StatusFound</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// HandleCallback processes the callback from the OIDC provider after the user has authenticated.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">HandleCallback</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\"> *</span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Context</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Retrieve the authorization code from the query parameters.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tcode := </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Query</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;code&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Exchange the authorization code for an access token.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">oauth2Token</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">globalOuthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Exchange</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">code</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\">!= </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Error exchanging code for token: %v&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Extract the ID token from the OAuth2 token.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">rawIDToken</span><span class=\"mtk1\">, ok := </span><span class=\"mtk12\">oauth2Token</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Extra</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;id_token&quot;</span><span class=\"mtk1\">).(</span><span class=\"mtk12\">string</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\">!</span><span class=\"mtk12\">ok</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Println</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Missing ID token&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Verify the ID token using the OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">verifier</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">globalProvider</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Verifier</span><span class=\"mtk1\">(&</span><span class=\"mtk12\">oidc</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Config</span><span class=\"mtk1\">{</span><span class=\"mtk12\">ClientID:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">globalOuthConfig</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ClientID</span><span class=\"mtk1\">, </span><span class=\"mtk12\">SkipClientIDCheck:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">idToken</span><span class=\"mtk1\">, err := </span><span class=\"mtk12\">verifier</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Verify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">rawIDToken</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">err</span><span class=\"mtk1\">!= </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Error verifying ID token: %v&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Extract claims from the verified ID token.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">claims</span><span class=\"mtk1\"> interface{}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> err := </span><span class=\"mtk12\">idToken</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Claims</span><span class=\"mtk1\">(&</span><span class=\"mtk12\">claims</span><span class=\"mtk1\">); </span><span class=\"mtk12\">err</span><span class=\"mtk1\">!= </span><span class=\"mtk12\">nil</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Printf</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Error extracting claims: %v&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">err</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Respond with a success message.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk11\">JSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">http</span><span class=\"mtk1\">.</span><span class=\"mtk12\">StatusOK</span><span class=\"mtk1\">, </span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">H</span><span class=\"mtk1\">{</span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;success&quot;</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// InjectRoutes sets up the routes for the application, including login and callback endpoints.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">func</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">srv</span><span class=\"mtk1\"> *</span><span class=\"mtk10\">Server</span><span class=\"mtk1\">) </span><span class=\"mtk11\">InjectRoutes</span><span class=\"mtk1\">() *</span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Engine</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\trouter := </span><span class=\"mtk12\">gin</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Default</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tapi := </span><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Group</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk3\">// Define the login route that redirects users to the OIDC provider for authentication.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">GET</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/login&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">StartLoginProcess</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk3\">// Define the callback route that handles the callback from the OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk12\">api</span><span class=\"mtk1\">.</span><span class=\"mtk11\">GET</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/callback&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">HandleCallback</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Initialize the OAuth2 configuration and OIDC provider.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk11\">InitializeOAuthConfig</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Create a new server instance.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\tserver := &</span><span class=\"mtk10\">Server</span><span class=\"mtk1\">{}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Inject routes into the Gin engine.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\trouter := </span><span class=\"mtk12\">server</span><span class=\"mtk1\">.</span><span class=\"mtk11\">InjectRoutes</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk3\">// Start the HTTP server.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">log</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Fatal</span><span class=\"mtk1\">(</span><span class=\"mtk12\">http</span><span class=\"mtk1\">.</span><span class=\"mtk11\">ListenAndServe</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;:8080&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">router</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The process described involves several key steps in setting up an OAuth2 flow with OpenID Connect (OIDC) for user authentication.</p>\n<p>Here's a brief overview of what was done in the code:</p>\n<h3 id=\"initialization-of-oidc-provider-and-oauth2-configuration\" style=\"position:relative;\"><a href=\"#initialization-of-oidc-provider-and-oauth2-configuration\" aria-label=\"initialization of oidc provider and oauth2 configuration 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>Initialization of OIDC Provider and OAuth2 Configuration</h3>\n<ul>\n<li>The OIDC provider is initialized using the <code>oidc.NewProvider</code> function, which requires the OAuth2 endpoint and the OIDC provider's URL. This step is crucial for establishing a connection with the OIDC provider, enabling the application to authenticate users through the provider.</li>\n<li>The OAuth2 configuration (<code>oauthConfig</code>) is set up with essential details such as the client ID, client secret, redirect URL, and scopes. These credentials are specific to the OIDC application registered with the provider (e.g., LoginRadius). The redirect URL is where the provider will send the user after authentication, and the scopes define the permissions requested from the user.</li>\n</ul>\n<h3 id=\"setting-up-the-callback-endpoint\" style=\"position:relative;\"><a href=\"#setting-up-the-callback-endpoint\" aria-label=\"setting up the callback endpoint permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting Up the Callback Endpoint</h3>\n<ul>\n<li>A callback endpoint is defined in the application, typically as <code>/api/callback</code>. This endpoint handles the callback from the OIDC provider after the user has been authenticated.</li>\n<li>When the user authenticates successfully, the OIDC provider redirects the user back to the application with an authorization code included in the query parameters.</li>\n<li>The application then exchanges this authorization code for an access token by calling the exchange method on the OAuth2 configuration object. This exchange process is handled securely by the OAuth2 library, ensuring that the application receives a valid access token.</li>\n</ul>\n<h3 id=\"verifying-the-access-token-and-extracting-user-claims\" style=\"position:relative;\"><a href=\"#verifying-the-access-token-and-extracting-user-claims\" aria-label=\"verifying the access token and extracting user claims 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>Verifying the Access Token and Extracting User Claims</h3>\n<ul>\n<li>Once the access token is obtained, the application extracts the ID token from it. The ID token contains claims about the authenticated user, such as their name, email, and roles.</li>\n<li>The ID token is then verified using the OIDC provider's verifier. This step ensures that the token is valid and has not been tampered with. Verification involves checking the token's signature and possibly other claims to ensure it matches the expected values.</li>\n<li>After verification, the application extracts the claims from the ID token. These claims can be used to identify the user within the application, personalize the user experience, or enforce access control based on the user's roles or permissions.</li>\n</ul>\n<p>This process leverages the security and standardization provided by OIDC and OAuth2 to implement a secure authentication flow. By following these steps, the application can authenticate users through LoginRadius OIDC provider, ensuring that user credentials are managed securely and that the application can trust authenticated users' identities.</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 tutorial, you have learned how to implement OIDC SSO with LoginRadius as the Identity Provider. You have also built a simple Golang backend with Gin to understand the implementation.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"May 30, 2024","updated_date":null,"description":"In this tutorial, you will learn how to implement Single Sign-On (SSO) using OpenID Connect (OIDC) with LoginRadius as your Identity Provider.","title":"How to Implement OpenID Connect (OIDC) SSO with LoginRadius?","tags":["SSO","OIDC","LoginRadius"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4509bd963b39d84ce554829099fba02f/ee604/implementing-oidc-sso.png","srcSet":"/static/4509bd963b39d84ce554829099fba02f/69585/implementing-oidc-sso.png 200w,\n/static/4509bd963b39d84ce554829099fba02f/497c6/implementing-oidc-sso.png 400w,\n/static/4509bd963b39d84ce554829099fba02f/ee604/implementing-oidc-sso.png 800w,\n/static/4509bd963b39d84ce554829099fba02f/f3583/implementing-oidc-sso.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Sanjay Velu","github":"SanjayV0","avatar":null}}}},{"node":{"excerpt":"First, let's understand some basic terminology. Basic Terminology Brute-force attack: A method where every possible combination of…","fields":{"slug":"/engineering/bruteforce-lock-and-unlock/"},"html":"<p>First, let's understand some basic terminology.</p>\n<h2 id=\"basic-terminology\" style=\"position:relative;\"><a href=\"#basic-terminology\" aria-label=\"basic terminology 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>Basic Terminology</h2>\n<ol>\n<li><strong>Brute-force attack:</strong> A method where every possible combination of characters or values is systematically tried to gain unauthorized access to a system, application, or data.</li>\n<li><strong>Brute-force lock:</strong> Brute-force lock is a type of account lock made to prevent a bruteforce attack.</li>\n<li><strong>Brute-force lockout:</strong> Brute-force lockout is a security mechanism that blocks access after a certain number of failed authentication attempts to prevent unauthorized access through repeated trial and error.</li>\n<li><strong>CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart):</strong> CAPTCHA is a method used to determine whether a user is human by presenting a challenge that is easy for humans to solve but difficult for bots.</li>\n<li><strong>Multi-Factor Authentication (MFA):</strong> MFA is a security method that requires multiple forms of identification to grant access, typically combining something the user knows, has, and is.</li>\n</ol>\n<p>In LoginRadius, you can implement brute-force lockout using APIs.</p>\n<blockquote>\n<p>To implement brute-force lockout, please register in the <a href=\"https://admin-console.loginradius.com/dashboard\"><em>LoginRadius Admin Console</em></a>.</p>\n</blockquote>\n<p>Let's go through the API implementation of brute-force lockout and user unlock.</p>\n<h2 id=\"api-implementation-for-brute-force-lockout\" style=\"position:relative;\"><a href=\"#api-implementation-for-brute-force-lockout\" aria-label=\"api implementation for brute force lockout 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>API Implementation for Brute-force Lockout</h2>\n<h3 id=\"creating-a-basic-application\" style=\"position:relative;\"><a href=\"#creating-a-basic-application\" aria-label=\"creating a basic application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a Basic Application</h3>\n<ol>\n<li>To implement brute-force lockout using API, create a simple app with login and registration features.</li>\n<li>This can be done by using <em><a href=\"https://admin-console.loginradius.com/deployment/idx\">Admin Console</a></em>.</li>\n<li>Navigate through <em><a href=\"https://devadmin-console.lrinternal.com/deployment/idx\">Deployment > Identity Experience Framework</a></em>.</li>\n<li>You can design the required application using theme, customization, preview, and implement options.</li>\n<li>You can also customize the predefined templates if needed.</li>\n</ol>\n<blockquote>\n<p>You can view the created app using the link <em><a href=\"https://%60%3Capp-name%3E%60.hub.loginradius.com/auth.aspx\">https://<code>&#x3C;app-name></code>.hub.loginradius.com/auth.aspx</a></em> in the <em>implement</em> section of the <em>Identity Experience Framework</em> or from the preview section.</p>\n</blockquote>\n<h3 id=\"brute-force-lockout\" style=\"position:relative;\"><a href=\"#brute-force-lockout\" aria-label=\"brute force lockout 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>Brute-force Lockout</h3>\n<h4 id=\"enabling\" style=\"position:relative;\"><a href=\"#enabling\" aria-label=\"enabling 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>Enabling</h4>\n<p>In LoginRadius, the brute-force lockout feature can be enabled from the <em><a href=\"https://admin-console.loginradius.com/platform-security/account-protection/auth-security/brute-force-lockout\">Admin Console</a></em>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.61538461538462%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABrElEQVQoz32STWsUQRCG51+JhGzWzdfiZkEU4tVLQC8iBBEhkPyg+Au8eVH0IJhDwLPOV0/P7Ex3T/fOx75W9bLLmqwOPHRT0/XWW9UdPJo8xc7+BIODCXb3xxidnmH88hJ74ycUe4zB4cQzPJ5i7+jE7x8Oj/BgcICd0Ri7dIb/HU+f4eT5CwTOzVHXFrW1sNbRvoaqKmhjoLRG13X437dYLPza0jlLGkGSCpRlhaKYQSkN5xyyLEMYhojCCFJK5HkBmecUlx4paU9xQ8VZkDFk4HckECht8OXrN7x6fY43b9/j3cUVwjhFMtNIiwoVuS3L0hf1a6VgqSh30zTN2iG7C5MMgciWDsIoJiLEcYzK1JDaodAW87Zbu1glb2uZxyaosyAvCj+rtm18RcZSK0Yv23fzxs+nbVtP3/d/FdgUTAUJ3tz+9Ik8A74QxpBDRbBQtxKjlYux4MrZVsGPnz5j0XdehIN943AbKVz/yEhke/K2j2fIlxlESYrZeugEXUJRKgi6FG2Wbjfh53QXjs8o91ciEWT0BPjpbJIKASHEvfi/SIkwEfjwPcIfL/rWGQiSpx0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"admin_bfl_page.png\"\n        title=\"admin_bfl_page.png\"\n        src=\"/static/a9abab8067a9a5380efae628b960b3cc/e5715/admin_bfl_page.png\"\n        srcset=\"/static/a9abab8067a9a5380efae628b960b3cc/a6d36/admin_bfl_page.png 650w,\n/static/a9abab8067a9a5380efae628b960b3cc/e5715/admin_bfl_page.png 768w,\n/static/a9abab8067a9a5380efae628b960b3cc/c65fa/admin_bfl_page.png 1434w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"testing\" style=\"position:relative;\"><a href=\"#testing\" aria-label=\"testing 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>Testing</h4>\n<ol>\n<li>Register with a new user and log in with the correct email and password. It is observed that the user is redirected to the profile page after authentication.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 49.38461538461538%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGElEQVQoz32SzU8TQRiH+Yck3vRGbdQD0hAPxggkWPkS9GA1FMEUYtAGKqaKRkk0losHL5KIRBM0Jh706skPohzUkJbt0t3t7rb71ceZoVUOxEmenXdmNr/5ve87bb7vY9suxZLOz99FtrUKmm5iWi5WtaYwTBHbdaqOt4u9i9yTlHcsHNfFq9dp8zyPKAqpVqtMTk6SvnKZwuNHZGevc0MwPDTIxbFRDMOARgNpIAwDwiAQy4YgIhCx3PcESlBu2LZNdv4W8a4EM/MLXBifYCR5ms6jHcSPHaesabjChWma4nJLEYahEpUaSsf3Wg4jSuUy10aGuX+ykzeZNB9vZ1kb7OVO7DAT5/rZ0nRKuo1uiTTrYNUaGG6EH0TKXSAwnT2CmhA8n0zyZCbDh2dPuTueYnk6zdqDe6y/WBU1swnrNZF2hPg0kctIuZOibk0KikJGwrZWLDJ8NsnE7E2m53JMZTJMDSTIXL1Edm6ez790Vr8YvPpm8nrDVPPLrwZl2ycK/L+iymEobtFFjdI9Z5jq6yM1OsbzlRVm0ilGek8xOjTApx9bvN20effd4P2mJWaT9Q2DHeefoKStLhxK28XSNp2JbrpjMTra2zmR6KK/r4dDBw8QPxKjUqmw32g1RXXZa9ZQdssUz2K5UCC/uMhCPk8ul1PMiXQfLi3hOI7KxPPFEwl2CZr4/h7BViAP/jda/+3HXsE/8YWxtTuNeGcAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"loginpage_with_data.png\"\n        title=\"loginpage_with_data.png\"\n        src=\"/static/d3def753c308c27e016d94aff3d5635a/e5715/loginpage_with_data.png\"\n        srcset=\"/static/d3def753c308c27e016d94aff3d5635a/a6d36/loginpage_with_data.png 650w,\n/static/d3def753c308c27e016d94aff3d5635a/e5715/loginpage_with_data.png 768w,\n/static/d3def753c308c27e016d94aff3d5635a/4c5bd/loginpage_with_data.png 1435w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span>\n<br>\n<span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB4ElEQVQoz32SS2sTURiG+3u6snhZxFkIihLtSqihpK1GbKnSNo3GdlKhtchoRSNSaa2LaqISUBcJRRMwruuPUFzVNBlvmNtkLsnjOZNOmgj6wTsfB877nPecb/osy8JoNPj5q8ynz1/YKZQo6T/aKn2jINY7X4tUqobYZ1Ormx3VDcvtv8s1GoJhmSZ9pvhIqG3bqKrKjYUYq6sPWYjNsXRzkdELISbGxykVi1SrFdfoled1hFd2U8gFStm2g6ZpKIpCPP6AcCTKZPAsI8cOM3jyBIXdXWF03INbLYRarprNJh7D8oDeta9FrzMUGObV6zdsvcvxWFvk0unjhM6PiSfQaTptoCwJk+UBHdvie3nvynJTvV5najrM3HyM9/kPpFIptLv3Wd98ztbbLIZh7IH203UD26G6gLVajeXbKzx78ZJEMkk4PMu92SCPliNsPk2K96v2JPsbaJrW/pUlUBpuzUyjDgeYuDJFIpFk/vIYk+f8YkAqeknvAP6VUEI7wIoA3rkaIR4YYmZklLWNDZ6srxEY9LOkRtH1/wN7huIlDIYu4juqcLC/nwMDA5zxn8J35BCKz9cD7K7uhD1Tlv/Xx+1tstks2VzO7el0mkwmQz6fdw90xJQ9Y7e8hFJ/APhEsTpxWRLtAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"successful_login.png\"\n        title=\"successful_login.png\"\n        src=\"/static/ba2b6d61774f4c9d32738ca535404e8a/e5715/successful_login.png\"\n        srcset=\"/static/ba2b6d61774f4c9d32738ca535404e8a/a6d36/successful_login.png 650w,\n/static/ba2b6d61774f4c9d32738ca535404e8a/e5715/successful_login.png 768w,\n/static/ba2b6d61774f4c9d32738ca535404e8a/c65fa/successful_login.png 1434w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<ol start=\"2\">\n<li>Now, log out and try to log in with incorrect credentials.</li>\n<li>If the password is incorrect successively till the lockout threshold, the account gets locked. </li>\n<li>Therefore, brute-force lockout is achieved.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACIklEQVQoz32S3UuTURjA9yclXYRYa4lWMIoIZ4NyNStWF6XGUildY6EkdFFUGIro/Fhz5ubmJngTUhdd2MdFF9ZdRDbJnG57P/a+77Zf550uJkgHfjyH8zznd55zOBYpPE12Osj6yEiFzYkJNsfHyYZCSPPzyLEY+WiUzOws25EI2yJmpqYqbE1OVtgYGyM3EyQ/9wqLlIghL8YopOKErrkJWOsJuS/x/JydYWcLPttRHjZayZk1yynkpQSKmJtoYm7uU5ILyImoyC1i0QETQ/B0PEiToxXfk2d4Bx9x0+PirP0kR5qayRZLKKImVyojiZgXlPeoOooCi6aqGIUCkiwT6OzgxZlm3nTfYnXIz7IQjp6y4mt3sbG1Q3ozx58dlaxcrLAjGeiazq5DZUvkLJqmoes6Ba3Ana4uHvf3824xztC9XoZ9XqKjL1lKJNFVWbRh9liq6U1QLlF1yKq2JzQMVEWhy+PhtvcuPf4AgYEBuq/Y6e24zv2+Pt5/zzCzJjH3Nc/rb3lm13KEBT+zGmXDbMiUajUdims/uOGhx+Gg093OVGiGQb+PqxfO0+66yJcfv/mQVvn0S+JzWuajiKvrEhlFpyiEpsdkn9DZdpnTJxqx1h3iuM2Gs7WF+sN1HGtoQBFvfNAo11x5n1ATwrcrKyzE48QEUfH3wuEwkcgcyVSqcqBRLKKZtQJdNzDEU1VF/4S1C/8b1bqD0CsH7Ob/At3aoIZGA4SQAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"incorrect_pwd.png\"\n        title=\"incorrect_pwd.png\"\n        src=\"/static/aa289f7862ab5cf1bb2ece6007b6ebd4/e5715/incorrect_pwd.png\"\n        srcset=\"/static/aa289f7862ab5cf1bb2ece6007b6ebd4/a6d36/incorrect_pwd.png 650w,\n/static/aa289f7862ab5cf1bb2ece6007b6ebd4/e5715/incorrect_pwd.png 768w,\n/static/aa289f7862ab5cf1bb2ece6007b6ebd4/bd9eb/incorrect_pwd.png 1442w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<blockquote>\n<p>In the <em><a href=\"https://admin-console.loginradius.com/platform-security/account-protection/auth-security/brute-force-lockout\">Admin Console</a></em>, you can set the <em>brute-force lockout threshold, lockout type, and suspend effective period</em>. </p>\n</blockquote>\n<h3 id=\"lockout-types-in-loginradius\" style=\"position:relative;\"><a href=\"#lockout-types-in-loginradius\" aria-label=\"lockout types in 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>Lockout Types in LoginRadius</h3>\n<p>LoginRadius supports the following lockout types: </p>\n<ol>\n<li><strong>Suspend</strong>: Suspends further login attempts after multiple failed tries for a certain amount of time, deterring automated attacks and enhancing system security by limiting access from suspicious sources.</li>\n<li>\n<p><strong>CAPTCHA</strong>: </p>\n<ul>\n<li>A security measure used to unlock a locked account on entering valid credentials by presenting a challenge to solve. </li>\n<li>This challenge is often easy for humans to solve but difficult for the bots.</li>\n</ul>\n<blockquote>\n<p><em>Refer <a href=\"#captcha\">CAPTCHA</a> in miscellaneous section to learn more</em>.</p>\n</blockquote>\n</li>\n<li><strong>Security Questions</strong>: A personalized query set up by the user to verify identity to unlock a locked account with valid credentials.</li>\n<li><strong>Block</strong>: Restricts login attempts from a specific source (email ID or username) after multiple failed tries, enhancing security against unauthorized access.</li>\n</ol>\n<h3 id=\"unlocking-an-account-locked-through-brute-force-lockout\" style=\"position:relative;\"><a href=\"#unlocking-an-account-locked-through-brute-force-lockout\" aria-label=\"unlocking an account locked through brute force lockout 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>Unlocking an Account Locked through Brute-force Lockout</h3>\n<p>You can unlock the locked user account in two ways, using:</p>\n<ol>\n<li>Account Update API from the LoginRadius Account API collection.</li>\n<li>Auth Unlock Account by Access Token from the LoginRadius Authentication API collection.</li>\n</ol>\n<blockquote>\n<p>For more understanding on <em>Auth Unlock Account</em>, refer <a href=\"https://www.loginradius.com/docs/api/v2/admin-console/platform-security/auth-security-configuration/\">Auth Security Configuration</a></p>\n</blockquote>\n<h4 id=\"account-update-api-from-the-loginradius-account-api-collection\" style=\"position:relative;\"><a href=\"#account-update-api-from-the-loginradius-account-api-collection\" aria-label=\"account update api from the loginradius account api collection 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>Account Update API from the LoginRadius Account API Collection</h4>\n<p>Calling the Account Update API with the provided endpoint, using the given method, providing the <em>apisecret</em> and <em>apikey</em>, and formatting the given body will unlock the account.</p>\n<ol>\n<li>Endpoint: <code>https://api.loginradius.com/identity/v2/manage/account/{uid}</code></li>\n<li>Method: PUT</li>\n<li>Parameters: apisecret, apikey</li>\n<li>Body:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">   ...</span>\n<span class=\"grvsc-line\">  &quot;FirstName&quot;: &quot;Test&quot;,</span>\n<span class=\"grvsc-line\">  &quot;MiddleName&quot;: null,</span>\n<span class=\"grvsc-line\">   ...</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<ol start=\"5\">\n<li>Response:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">    ...</span>\n<span class=\"grvsc-line\">    &quot;LoginLockedType&quot;: &quot;None&quot;,</span>\n<span class=\"grvsc-line\">    &quot;Email&quot;: [</span>\n<span class=\"grvsc-line\">        {</span>\n<span class=\"grvsc-line\">            &quot;Type&quot;: &quot;Primary&quot;,</span>\n<span class=\"grvsc-line\">            &quot;Value&quot;: &quot;user1@yopmail.com&quot;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">    ],</span>\n<span class=\"grvsc-line\">    ...</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<br>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 49.07692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3KmgD//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEAAQUCX//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABoQAAEFAQAAAAAAAAAAAAAAABAAARExUWH/2gAIAQEAAT8haxHVp//aAAwDAQACAAMAAAAQ4A//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAaEAACAwEBAAAAAAAAAAAAAAAAAREhQVEx/9oACAEBAAE/EGhliIqrFdw15wXglwrwl9P/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"unlocked_account_update.jpeg\"\n        title=\"unlocked_account_update.jpeg\"\n        src=\"/static/2c6b8e1386c3ac8d4ed9a214833246d0/212bf/unlocked_account_update.jpg\"\n        srcset=\"/static/2c6b8e1386c3ac8d4ed9a214833246d0/6aca1/unlocked_account_update.jpg 650w,\n/static/2c6b8e1386c3ac8d4ed9a214833246d0/212bf/unlocked_account_update.jpg 768w,\n/static/2c6b8e1386c3ac8d4ed9a214833246d0/a90fb/unlocked_account_update.jpg 1433w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></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<ul>\n<li>Unlocking user accounts previously locked due to brute force lockout using LoginRadius APIs demonstrates the platform's account management and security enhancement efficiency.</li>\n<li>Moving forward, leveraging LoginRadius's robust security features ensures uninterrupted user access while fortifying your system against unauthorized access attempts.</li>\n</ul>\n<h2 id=\"miscellaneous\" style=\"position:relative;\"><a href=\"#miscellaneous\" aria-label=\"miscellaneous 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>Miscellaneous</h2>\n<h3 id=\"captcha\" style=\"position:relative;\"><a href=\"#captcha\" aria-label=\"captcha 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>CAPTCHA</h3>\n<p>LoginRadius supports the following types of CAPTCHAs: </p>\n<ul>\n<li>reCAPTCHA V2: Users solve challenges like clicking on images or entering text to prove they're human.</li>\n<li>reCAPTCHA V3: Operates in the background, assessing user behavior to assign a risk score without user interaction.</li>\n<li>hCAPTCHA: Like reCAPTCHA, it offers bot protection with a privacy focus.</li>\n<li>QQ Tencent CAPTCHA: A CAPTCHA service by Tencent commonly used in China to verify human users.</li>\n</ul>\n<h3 id=\"multi-factor-authentication-mfa\" style=\"position:relative;\"><a href=\"#multi-factor-authentication-mfa\" aria-label=\"multi factor authentication mfa 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>Multi-Factor Authentication (MFA):</h3>\n<ul>\n<li><em>LoginRadius</em> offers multiple security features, including Multi-Factor Authentication. </li>\n<li>This feature can be enabled from the <em><a href=\"https://admin-console.loginradius.com/dashboard\">Admin Console</a></em> to add an additional layer of security.</li>\n<li>LoginRadius provides predefined MFA types, which can be enabled further.</li>\n</ul>\n<p><em>To understand more about LoginRadius APIs, refer to the <a href=\"https://www.loginradius.com/docs/api/v2/getting-started/introduction/\">API docs</a></em>.</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":"May 29, 2024","updated_date":null,"description":"In this blog, you'll learn about brute-force lockout, the creation of a basic app using Identity Experience Framework, and how to unlock a user account using APIs.","title":"Testing Brute-force Lockout with LoginRadius","tags":["Brute-force","LoginRadius","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/1ff36040268e755844bfd2e543baf5b5/ee604/implementing-brute-force-lockout.png","srcSet":"/static/1ff36040268e755844bfd2e543baf5b5/69585/implementing-brute-force-lockout.png 200w,\n/static/1ff36040268e755844bfd2e543baf5b5/497c6/implementing-brute-force-lockout.png 400w,\n/static/1ff36040268e755844bfd2e543baf5b5/ee604/implementing-brute-force-lockout.png 800w,\n/static/1ff36040268e755844bfd2e543baf5b5/f3583/implementing-brute-force-lockout.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Gayathri Suresh","github":"gayathrisuresh150501","avatar":null}}}},{"node":{"excerpt":"LoginRadius is one of the leading and technologically advanced Customer Identity and Access Management (CIAM) solutions. Enterprise…","fields":{"slug":"/engineering/smart-cache-redis-cloud-aws-elasticache-for-redis/"},"html":"<p>LoginRadius is one of the leading and technologically advanced Customer Identity and Access Management (CIAM) solutions. Enterprise customers rely on our CIAM to manage end-user authentication and authorization. They typically serve hundreds of thousands to millions of end-users, making our CIAM a critical part of their IT infrastructure and value delivery.</p>\n<p>Our backend consists of multiple microservices handling various identity and access management functions and workflows through APIs. And we use MongoDB as persistent storage for configuration data. For faster access and availability of this data, we deployed Redis in-memory cache through Redis Enterprise Cloud.</p>\n<h2 id=\"challenges-with-cache-updates\" style=\"position:relative;\"><a href=\"#challenges-with-cache-updates\" aria-label=\"challenges with cache updates 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>Challenges with Cache Updates</h2>\n<p>We had our configuration cache set up in Redis Cloud. And to reduce the Redis Cloud latency, we kept the configuration cache at the application level in memory — but we ran into problems.</p>\n<p>Generally, customers don’t update their configurations so frequently. But when a customer updates their configuration, it doesn’t propagate in the backend until the server memory cache is purged — sometimes even taking several hours.</p>\n<p><em>This is bad for business:</em> A customer updates configurations in response to a new requirement or rapidly changing business environment. If these changes take so much time for a digital identity process, it can affect end-users and, in turn, business outcomes. Simply imagine that a customer updated app configuration to accommodate a one-time flash sale, and end-users can’t place orders properly due to configuration update issues!</p>\n<p>So, we started evaluating various options to address these issues. We considered running multiple instances in the Redis Cloud and synchronizing them to minimize latency for all regions while ensuring customer configuration updates go live immediately. But this proved to be technically cumbersome and costly.</p>\n<p>We continued our research with various solutions and concluded that AWS ElastiCache for Redis best serves our needs.</p>\n<h2 id=\"migrating-to-aws-elasticache-for-redis\" style=\"position:relative;\"><a href=\"#migrating-to-aws-elasticache-for-redis\" aria-label=\"migrating to aws elasticache for redis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Migrating to AWS ElastiCache for Redis</h2>\n<p>AWS provides ElastiCache for Redis as a Redis Cloud alternative with all necessary capabilities. Also, we were already using AWS Cloud for some of our IT infrastructure needs.\nSo, we can deploy ElastiCache alongside the same infrastructure to solve the latency issues.</p>\n<p>Accordingly, we have created ElastiCache instances in multiple AWS regions and set up the primary ElastiCache DB to quickly sync configuration updates in the secondary ElastiCache instances. Also, we deployed ElastiCache instances in multiple locations as needed.</p>\n<p>For migration, we updated the old Redis and ElastiCache primary instances simultaneously. Once we reached a sufficient confidence level with the new setup, we completely switched over to ElastiCache.</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>Our applications and cache are deployed in AWS, so our API response latency is no longer problematic. Ultimately, we can reduce application in memory cache updates to a few minutes or seconds as required.</p>\n<p>Now customers get updated configurations deployed rapidly, solving our primary challenge!</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":"August 09, 2023","updated_date":null,"description":"ElastiCache’s capabilities are better suited than Redis Cloud for our technical requirements and use cases, especially better scalability and pricing.","title":"Breaking Down the Decision: Why We Chose AWS ElastiCache Over Redis Cloud","tags":["Cache","AWS","Redis","LoginRadius"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/f73d944745cd7f94227e1f20e4214968/14b42/migrating-to-aws-elasticache-for-redis.jpg","srcSet":"/static/f73d944745cd7f94227e1f20e4214968/f836f/migrating-to-aws-elasticache-for-redis.jpg 200w,\n/static/f73d944745cd7f94227e1f20e4214968/2244e/migrating-to-aws-elasticache-for-redis.jpg 400w,\n/static/f73d944745cd7f94227e1f20e4214968/14b42/migrating-to-aws-elasticache-for-redis.jpg 800w,\n/static/f73d944745cd7f94227e1f20e4214968/47498/migrating-to-aws-elasticache-for-redis.jpg 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},{"node":{"excerpt":"Introduction As a developer, I like to work on the terminal. Many developers are the same way. Instead of scrolling, clicking the mouse…","fields":{"slug":"/engineering/loginradius-launches-cli-enterprise-dashboard/"},"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>As a developer, I like to work on the terminal. Many developers are the same way. Instead of scrolling, clicking the mouse, they prefer working with only keywords (through commands or shortcuts). The command-line interface (CLI) is a great tool for them.</p>\n<p>So, LoginRadius has launched a CLI for its enterprise dashboard. The CLI makes it easier by using some commands to perform different operations and manage the flow of the LoginRadius Enterprise dashboard.</p>\n<h2 id=\"the-idea-behind-loginradius-cli\" style=\"position:relative;\"><a href=\"#the-idea-behind-loginradius-cli\" aria-label=\"the idea behind loginradius cli 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 Idea Behind LoginRadius CLI</h2>\n<p>We always look for ways to eliminate resistance from the process of working with LoginRadius. Therefore, we have taken this step to introduce LoginRadius CLI for a better developer experience.</p>\n<p>In the 1970s and 1980s, most users preferred to use command-line interfaces. As time passed, we shifted to graphical user interfaces. GUIs are user-friendly; however, CLIs are faster than GUIs. Here is an example of adding domain via Admin Console v/s CLI :</p>\n<p>To add a domain through LoginRadius Admin Console, you need to:  \\</p>\n<ol>\n<li>Navigate it to Web Apps in LoginRadius Admin Console</li>\n<li>Click on Add </li>\n<li>Enter the domain </li>\n<li>Click on Save</li>\n</ol>\n<p>On the flip side, you can do this by running a single command:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 489px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 37.01431492842536%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABJ0AAASdAHeZh94AAABKklEQVQoz42R63KCMBCFeYDWUUAgXK0KyCWGKnfQtr5E3/9JTpNYRqbtj/74ZnNOdrI7J8opZ7iVDPWQY1dThFGC/YET/5cUYZLhZR+hu35AYcTBZxGgv1l4rmysFiqWmoalqmGl6Viu1DtCS0/cqd88+p4WC4SHFIpuEaiWA8Py4No+HJ/j+SCOC9204PoBvCCQ2iS2RNxP2K4nMQlBnFEoojmMIvTDgLbvZR0vF6Q5xWa75XrE9e1d6nNVoe16xEmKrh+kn3E/p0fQI7tvuNnuMIwXJGmGnJvDOIKygg+J0bQdwviAPR9YNQ33GcqqBiteee8Rp3OJsq7l1iKWiGepaGsDumFC1DmTJ+r8/LNPsObRiBzlhlMuAkNgzepfkN+Y/GPFwykt8AVZC8JRA+nkagAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cl-1\"\n        title=\"cl-1\"\n        src=\"/static/7f11c250ddbc8de781684571ea14f348/03e1f/cl-1.png\"\n        srcset=\"/static/7f11c250ddbc8de781684571ea14f348/03e1f/cl-1.png 489w\"\n        sizes=\"(max-width: 489px) 100vw, 489px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><strong>Here are some more of LoginRadius CLI Enterprise's commands:</strong></p>\n<p><strong>1. Login/Logout to your LoginRadius Dashboard</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 729px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 36.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABJ0AAASdAHeZh94AAABKUlEQVQoz5WRTW7CMBBGc4AKCokJAYoJJCQxSew4f4SqUqUueoGKRdtblJ7/69gr2kUlFk/jkT1vRmOn38V47TmWHQebB5j5xPw2/GCB8WSK7vQERzxwNGIJlgZwZz4Y4d2IkY7vJ6jaI5wF3yBYb3HICqzWHFOP/XrsspnlOv8rZP7cCmXdwcnEAXXToB8GyEojyQQKqVDpGiIvoLRGqSrESWqjJEzNge72aYailDa6jKHULZxtFJNAou16KBIqEpVKIdoneP/4xNflQnzj7XxGTsWmsRHqukHbH62woVozuRXu4hglTWSkpmtC3USe4zickAqBYLmyC3dpFWYdE9ej6NmzhXIjuxuNkEsNJ04F+DayrMOdjRsipMmvc/4PYbTHiv7i8fkFPxRExSJAJiIiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cl-2\"\n        title=\"cl-2\"\n        src=\"/static/ffdfc7286c5e6e8f036abc5b8b24014d/b2982/cl-2.png\"\n        srcset=\"/static/ffdfc7286c5e6e8f036abc5b8b24014d/a6d36/cl-2.png 650w,\n/static/ffdfc7286c5e6e8f036abc5b8b24014d/b2982/cl-2.png 729w\"\n        sizes=\"(max-width: 729px) 100vw, 729px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>This command (<em>lr login</em>) will help you to login to your LoginRadius Enterprise Dashboard. Once logged in, you can perform other operations and configure your LoginRadius Application through CLI.</p>\n<p><strong>2. Manage Application Credentials</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 66.92307692307693%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABJ0AAASdAHeZh94AAABmUlEQVQ4y41T2W7CQAzMH7QcgUBucpKbJFCOQFtV7f//ketxFaRWBPow2V1HO56xvYql6xSELtm+R467IlXTaDxVBRN1RqPJVPbT2fwKxIegeFFM+2NH1aamut1SyWtWlGRYNs0XSzJth7Slfk0AqHNtEEoYr6nZ7ijNcwqZPC8rapj42J0ljiR105Lr+bTyA1mhcpAQSrwgpGidkB+GcgGKDMsSldgvDVP2gG5a9xXaXLd1klLMhAErhEpcFEUM2H4ajel5PBH09b0FKFcsx6WIbSdZJrbTvBDbSZZLgnWaSQwOsEeySJJHPwLiWFbEoF5xV54coLBf/TCSeoEUsZybBDIkn2kLvmhKGf4C/xTUKBSFOTlMDqs+1xRqsUcM/2MuC+zfGxmxbHPWy9s7j86JWu5qd3mldvciOJw6SjkRiBa6IUW/12FpCqwV1UbqhloVVSX2NjwqeVn+Guie7O7YoMMfn1+0ZUX7w5FO5wtlTDw0cw8VBtyAqm7khaDTeDE4wyaeXU/yiOhKiA8ag5b3tcL6H3u38A3guWICI/3xIQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cl-3\"\n        title=\"cl-3\"\n        src=\"/static/34e18ed3bfd4b0b652b57859a93e640c/e5715/cl-3.png\"\n        srcset=\"/static/34e18ed3bfd4b0b652b57859a93e640c/a6d36/cl-3.png 650w,\n/static/34e18ed3bfd4b0b652b57859a93e640c/e5715/cl-3.png 768w,\n/static/34e18ed3bfd4b0b652b57859a93e640c/b5dee/cl-3.png 1237w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>You can get our App Credentials, reset Secret key, update account password and generate SOTT through LoginRadius CLI.</p>\n<p><strong>Set Schema for Your LoginRadius Application</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 87.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAACo0lEQVQ4y5VTS08TYRSdlcgC6HM6fT8o9EGfzJQ+aaEUolFjfGGCj8SAsagLFkZXGjf6EzQqRjEGMQGjYsSV/rAx3/WeD4boog0uznTmpt+5555zP2Xz26/fjx4/pZW7XVpaWaWry6t0ZblL11ZuHwnXb96hpRu36N7DJ7TFXMqb7T2z3Zolt2dIuDVNOJxO4XKrYmh45EgYttnFsYEBUao2aGPnh6m8+vDFbHZOUKGoi3KlSpOGQblCkSKxUW6iker1kap5e0Lz+cnmcIrK9Aytb301lZebn83W3AJl83lhTJUpz2S5QoGKukHhaEwiFh+TDfAbG40f1qP8jprX5xO1ZpsgTlnnR63JI6seEQiFyR8MMkISTrcqAaUu1SNh1fAuJ2CVIzx2ud7aVwjW6dkOd/GLTC5PILXGgQp8e3hsNPAFghSKRGUdNZD2IJwnj+YVkB8MRyT+HtXrD9B4MkVjiQQlU2lKMOBdH8IOZbI5gcMOl1uq0UtTkswaGd5OZLJMmpQNeyvkUJrteZoqVwQHIwlAWKs3KJcvHCrRjZJUmZrIUHw80X/kxkwH3UVhUpejIhisDr5j8bgkzTJ5Kj1BSQYIQdSHcI7/nBbwBgphPlYnzWqsg1A/yp7CQ3jZlxCh6IYh4I3d6ZKE1VpdJgxP4SF2NMEjYxPS7GV/hRxKOBoVWAkkCiLLfHwDWGIr/f6h4Oq1F3gVUgK+Yez9FUlSkT0EkUvVJKDUgrWrHi+unkNUGgdXD49Ko0X+QEAgDN5HVhCmcCRCAU6bbxAN22w0Yrf/C9s++B7T8cFBoZdr9Prjrqls7OyZ3bX7dPLsRXH6/GU6dW6RcekAixKo98KZC/KM6K49IHApm7s/zbfb3+nF+0/i+btt+l88Y+AsOMD1B3VrQPZblxBqAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"4\"\n        title=\"4\"\n        src=\"/static/5d4ff2be787674cb2336d3f81c30c84f/e5715/4.png\"\n        srcset=\"/static/5d4ff2be787674cb2336d3f81c30c84f/a6d36/4.png 650w,\n/static/5d4ff2be787674cb2336d3f81c30c84f/e5715/4.png 768w,\n/static/5d4ff2be787674cb2336d3f81c30c84f/29007/4.png 1600w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>This command will help you set the schema for your application. We can get all the basic fields via <em>lr get schema</em> we can update the schema via lr set schema. </p>\n<p><strong>Theme Management (LoginRadius Page)</strong></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 70.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABJ0AAASdAHeZh94AAABl0lEQVQ4y5VT2XKCQBDkE6KC3KByqIioHAIGTapSyf//UWd7S4ymUlEfppZhd3t6umeVJojQ7R3omY3BiwZV1zHSxlDHOjTduKz3gud004biuz5mgQ974sHzpzAsC5bjik3rYbAfQAtKOF+gqlvUIqq6wb5psVpnGBvm04BjAk5mIZarFMe3d+yKEmE8vwF7puUzYIAkTdEdT8jLCrMwehrsBjCIYqTZBh+fXzh0HWIhwX+X7gI6ng/H8xAJILKlIUNVw1A4LVcR167fNYUApu3IxBXgXFnEm0zhM6YzWYSX+gJ9kd85tZcarjdbZNsdtnmBtWh/J9bNOS+qvdjbSm2nQSi7oEwsyH80kTn3WFhZpmu0rx1KcZEu1w3Hp5b/4sVSViVrduH6k0vw8nVuu548o8yTFer2gM0ul3NItmTFUUpEkAH1NSz70tp1DK++ZcuJYHgSM5iXJcp9LVvt2+v1ZZsEfMgUMiyqSurGoJacR4LzxZDdYKTezOZfjsuxIUNXvF/TtqUGdLdfycw7u/zIgPMMu/gGsTF5bnIxV58AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cl-5\"\n        title=\"cl-5\"\n        src=\"/static/ae4f8c15a6b68f1854a276973dd4fd7a/e5715/cl-5.png\"\n        srcset=\"/static/ae4f8c15a6b68f1854a276973dd4fd7a/a6d36/cl-5.png 650w,\n/static/ae4f8c15a6b68f1854a276973dd4fd7a/e5715/cl-5.png 768w,\n/static/ae4f8c15a6b68f1854a276973dd4fd7a/f680b/cl-5.png 1108w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>You can update the LoginRadius IDX Page(Hosted Page) from the available themes through LoginRadius CLI commands.  </p>\n<p><strong>Learn More LoginRadius CLI Enterprise Commands</strong></p>\n<p>Run  lr – help for available commands. For more details about commands please check out the <a href=\"https://opensource.loginradius.com/cli/manual/\">documentation</a>.</p>\n<h2 id=\"try-it-out\" style=\"position:relative;\"><a href=\"#try-it-out\" aria-label=\"try it out 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>Try It Out</h2>\n<p>The LoginRadius CLI is available for Windows, Linux, and MacOS. <a href=\"https://github.com/LoginRadius/lr-cli/tree/main#readme\">Check out the installation instructions for your Operating System on our README Page</a>.</p>\n<p>We hope you will love trying LoginRadius CLI for Enterprise Dashboard. We will add and explore more features in the future. Needless to say, for developers who like working with terminals and prefer to type commands, LoginRadius CLI will be a great experience.</p>\n<p>We are eager to know your feedback, test cases and also what we can bring up next in our CLI. If you have any suggestions, please create an issue on our <a href=\"https://github.com/LoginRadius/lr-cli/issues\">open source github repository</a>.</p>\n<p><a href=\"https://www.loginradius.com/book-a-demo/\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 30.307692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAABdElEQVQY002RO0/CUBzFG6PtbZWHCAmRmBB5P8vDII9SSC0omog4oAEGjZMO6OKEuLjoJ2Fx0cSBwUQnXZxcHPwux38LJA7nNvfec8+5v1tOCCiwpbbhye2BxbYgBMtgIRVioDRRsARGXxZUzLlEHmehBaesQ4rrEMPViYf2DR9nDGKkChbVICVqsMt1WJI1sHCFwhUsUIFohJH49TxECvRUjhDW2mAbB5iP6hB8hUkhiRPN5KIZYJdrsEYrcCSpmQqMm6/m9ylUhSulY7N5ivROB3L9GOlGF3Ktbc4zuz341UPw/uIk0ESbBjoSGlYIx8BfzjSwVmyCEYEUUmCPa3Bnd+hwC75yC95S05SxbolU/iEbOCFCpDexEfIioTNCNd6Tp6IlMnNuGeeDe3z//OLx5RWj5zFGT2O8fXxh/P4Ja6w6vSEFCnTIlW2YiDzhzX7ATFKojDlvjpBPcDF4QPdyiG5/iE7/BmfXd+hd3VKpCoG8fzxWw2+c+yTpAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"book-a-free-demo-loginradius\"\n        title=\"book-a-free-demo-loginradius\"\n        src=\"/static/fcc4c4b5dc38cc4528f99d09480f4eb2/e5715/book-a-demo-loginradius.png\"\n        srcset=\"/static/fcc4c4b5dc38cc4528f99d09480f4eb2/a6d36/book-a-demo-loginradius.png 650w,\n/static/fcc4c4b5dc38cc4528f99d09480f4eb2/e5715/book-a-demo-loginradius.png 768w,\n/static/fcc4c4b5dc38cc4528f99d09480f4eb2/63ff0/book-a-demo-loginradius.png 2887w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"January 16, 2023","updated_date":null,"description":"We are happy to announce that we have launched LoginRadius CLI for enterprise dashboard.","title":"LoginRadius Launches a CLI for Enterprise Dashboard","tags":["enterprise","admin console","developers"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.4598540145985401,"src":"/static/1887b01a9c110cfa79272e2995bcd767/ee604/cli-1.png","srcSet":"/static/1887b01a9c110cfa79272e2995bcd767/69585/cli-1.png 200w,\n/static/1887b01a9c110cfa79272e2995bcd767/497c6/cli-1.png 400w,\n/static/1887b01a9c110cfa79272e2995bcd767/ee604/cli-1.png 800w,\n/static/1887b01a9c110cfa79272e2995bcd767/a8378/cli-1.png 1024w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},{"node":{"excerpt":"Introduction It is essential to protect your APIs for a secure experience, and JSON Web Token (JWT) authentication allows you to protect…","fields":{"slug":"/engineering/guest-post/how-to-implement-jwt-authentication-in-deno/"},"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>It is essential to protect your APIs for a secure experience, and <strong>JSON Web Token</strong> (JWT) authentication allows you to protect your APIs so that an unauthorized person will not have access.</p>\n<h2 id=\"prerequisites\" style=\"position:relative;\"><a href=\"#prerequisites\" aria-label=\"prerequisites 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>Prerequisites</h2>\n<p>This is a hands-on tutorial to follow. To get the most out of it, ensure you have:</p>\n<ul>\n<li>A code editor of your choice</li>\n<li>Basic knowledge of JavaScript/<a href=\"https://www.typescriptlang.org/\">TypeScript</a>.</li>\n<li>Basic knowledge of <a href=\"https://www.mongodb.com/\">MongoDB</a></li>\n<li><a href=\"https://www.postman.com/\">Postman</a> or <a href=\"https://insomnia.rest/\">Insomia</a> installed</li>\n</ul>\n<h2 id=\"what-is-deno\" style=\"position:relative;\"><a href=\"#what-is-deno\" aria-label=\"what is deno 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 Deno?</h2>\n<p><a href=\"https://deno.land/\">Deno</a> is developed in Rust. It is a modern runtime environment for JavaScript/TypeScript and a WebAssembly that uses the Google V8 engine. It is simple and safe. It implements web platform standards and provides web platform capabilities.</p>\n<p>Deno’s features are intended to enhance Node.js’s capabilities. It’s secure by default, with no access to files, networks, or the environment except explicitly enabled. And it supports both JavaScript and TypeScript out of the box.</p>\n<h2 id=\"why-use-deno\" style=\"position:relative;\"><a href=\"#why-use-deno\" aria-label=\"why use deno 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 Deno?</h2>\n<p>Deno is a well-thought-out modular system. Apart from its simplicity and high security, there are so many other reasons to use Deno:</p>\n<ul>\n<li>Outside of an async function, you can use await</li>\n<li>No setting is required for TypeScript to work</li>\n<li>There are no dependencies, and it ships as a single executable</li>\n<li>A dependency inspector and a code formatter are built-in</li>\n<li>Packages in Deno are decentralized</li>\n</ul>\n<h2 id=\"what-is-json-web-token\" style=\"position:relative;\"><a href=\"#what-is-json-web-token\" aria-label=\"what is json web token 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 JSON Web Token?</h2>\n<p>JSON Web Token, popularly called JWT, is an open standard that offers a concise and self-contained method for securely transferring data between parties as a JSON object. It holds information in an easy-to-access format for developers and computers; the token's compact size makes it simple to send through URL, POST parameter, or HTTP header. It allows two parties — a client and a server — to share information securely. A secret or public/private key pair is used to digitally sign the information in a JWT. </p>\n<p>Authentication is the primary use of JWT. It is assigned to a user after they sign in to an application, and with the assigned JWT, a user can request other routes.</p>\n<h2 id=\"install-deno\" style=\"position:relative;\"><a href=\"#install-deno\" aria-label=\"install deno 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>Install Deno</h2>\n<p>Without too many shenanigans, let's start by installing Deno!</p>\n<p>Deno installation in Windows isn't as smooth sailing as on Mac or Linux. Unlike in Node.js, where you run a command on your terminal, Deno in Windows can be installed using PowerShell, Scoop (a command-line installer), or Chocolatey (a package manager). <a href=\"https://deno.land/manual/getting_started/installation\">Click here for the guide on how to install Deno</a>.</p>\n<p>To install Deno with PowerShell, open your PowerShell and run the following command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">iwr https://deno.land/x/install/install.ps1 -useb | iex</span></code></pre>\n<p>Relax while Deno is being installed. When completed, exit PowerShell and close and reopen a terminal. The new PATH is activated by closing and reopening the terminal. Now that you have installed Deno, let's check the version of Deno.</p>\n<p>To check the version of your installed Deno, run: <code>deno -V</code></p>\n<h2 id=\"project-setup\" style=\"position:relative;\"><a href=\"#project-setup\" aria-label=\"project setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project Setup</h2>\n<p>With installation out of the way, let us set up your project. Create a folder <code>DenoAPI_JWT_Auth</code>; you can call it any name you choose. Create an <code>app.ts</code> file and a folder <code>src</code> in your folder.</p>\n<p>Inside your <code>src</code> folder, create the following folders: <code>controllers</code>, <code>database</code>, <code>middlewares</code>, <code>routes</code>, <code>schema</code>, and <code>utils</code>.</p>\n<p>Your project directory should look as follows:</p>\n<p><code>DenoAPI_JWT_Auth</code>  </p>\n<p>│\n└─<strong>src</strong><br>\n│   └───controllers<br>\n│   │\n│   └───database<br>\n│   │\n│   └───middlewares<br>\n│   │\n│   └───routes<br>\n│   │\n│   └───schema<br>\n│   │\n│   └───utils<br>\n└─<strong>app.ts</strong>  </p>\n<h2 id=\"create-oak-server\" style=\"position:relative;\"><a href=\"#create-oak-server\" aria-label=\"create oak server permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create Oak Server</h2>\n<p>Next is to create your Oak server. <a href=\"https://oakserver.github.io/oak/\">Oak</a> is a Deno middleware system that provides a router middleware for HTTP servers.</p>\n<p>Go to <code>app.ts</code>, import Application from the Deno Oak URL, create an instance of the application, define your port, and call a middleware, as follows.</p>\n<p><code>app.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Application</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Application</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">PORT</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">8080</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   </span><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">((</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">, </span><span class=\"mtk12\">next</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;Welcome&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">next</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       });</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`Application is listening on port: </span><span class=\"mtk4\">${</span><span class=\"mtk12\">PORT</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">({</span><span class=\"mtk12\">port:PORT</span><span class=\"mtk1\">});</span></span></code></pre>\n<p>Let's quickly run your server: to run the server, use <code>deno run --allow-net app.ts</code> </p>\n<p>Deno will always request permission to use your network. <code>--allow-net</code> gives Deno permission to all network calls.</p>\n<p>You should see <code>Application is listening on port: 8080</code></p>\n<p>Now, in your <code>routes</code> folder, create a file called <code>allRoutes.ts</code>, and set up your router by importing <code>Router</code> from the oak URL, then create an instance of the router and export the default router.</p>\n<p><code>routes.allRoutes.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Moving on, you need to modify <code>app.ts</code>. So, go to <code>app.ts</code> and import the router. Let the app use <code>router.routes()</code> and <code>router.allowedMethods()</code> methods, then remove the middleware, so it doesn't overshadow the imported routes. The <code>allowedMethods()</code> tells Deno to include all routes by your router.</p>\n<p><code>app.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Application</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./src/routes/allRoutes.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Application</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">PORT</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">8080</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">routes</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">allowedMethods</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`Application is listening on port: </span><span class=\"mtk4\">${</span><span class=\"mtk12\">PORT</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">({</span><span class=\"mtk12\">port:PORT</span><span class=\"mtk1\">});</span></span></code></pre>\n<p>You can rerun your app with the same command: <code>deno run --allow-net app.ts</code></p>\n<h2 id=\"create-user-data\" style=\"position:relative;\"><a href=\"#create-user-data\" aria-label=\"create user data permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create User Data</h2>\n<p>Now, you need to create user data. But before that, let's connect your application to the MongoDB database.</p>\n<ul>\n<li>Go to your <code>database</code> folder</li>\n<li>Create a file called <code>connectBD.ts</code></li>\n<li>Import MongoClient from the Deno MongoDB URL</li>\n<li>Create an instance of MongoClient</li>\n<li>Connect your database</li>\n<li>Export default</li>\n</ul>\n<p><code>database.connectDB.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">MongoClient</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/mongo@v0.30.0/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">// Connecting to a Mongo Database</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">client</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">MongoClient</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dbString</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;DB_String&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">client</span><span class=\"mtk1\">.</span><span class=\"mtk11\">connect</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dbString</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=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Database connected!&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">db</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">client</span><span class=\"mtk1\">.</span><span class=\"mtk11\">database</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;deno_auth&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">db</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span></code></pre>\n<p>With that out of the way, let's create an interface for your database.</p>\n<p>In your <code>schema</code> folder, create a file <code>user.ts</code>, import objectId from deno MongoDB URL, then define and export your schema.</p>\n<p><code>schema.user.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">ObjectId</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/mongo@v0.30.0/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">interface</span><span class=\"mtk1\"> </span><span class=\"mtk10\">UserSchema</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">_id</span><span class=\"mtk1\">: </span><span class=\"mtk10\">ObjectId</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">username</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">password</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span></code></pre>\n<p>Let's play with some logic: go to your <code>controllers</code> folder, and create a file called <code>users.ts</code>. In the file, import your database and UserSchema.</p>\n<p>It's not a good practice to store your password in plain text for security reasons. To has your password, let's import bcrypt from the deno bcrypt URL.</p>\n<p>So, create a function called <code>signup</code> that takes username and password. Take the user details from the request body, hash the password, and save them to your database.</p>\n<p><code>controllers.users.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">db</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../database/connectBD.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk4\">*</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/bcrypt/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">UserSchema</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../schema/user.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Users</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">db</span><span class=\"mtk1\">.</span><span class=\"mtk11\">collection</span><span class=\"mtk1\">&lt;</span><span class=\"mtk10\">UserSchema</span><span class=\"mtk1\">&gt;(</span><span class=\"mtk8\">&quot;users&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">signup</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\">({</span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">}:{</span><span class=\"mtk12\">request</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">username</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">} = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">().</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">salt</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\">.</span><span class=\"mtk11\">genSalt</span><span class=\"mtk1\">(</span><span class=\"mtk7\">8</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">hashedPassword</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\">.</span><span class=\"mtk11\">hash</span><span class=\"mtk1\">(</span><span class=\"mtk12\">password</span><span class=\"mtk1\">, </span><span class=\"mtk12\">salt</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">_id</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Users</span><span class=\"mtk1\">.</span><span class=\"mtk11\">insertOne</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">username</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">password:hashedPassword</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> =</span><span class=\"mtk7\">201</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;User created&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">userId:_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user:username</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></code></pre>\n<p>Now, head over to <code>allRoutes.ts</code> in your <code>routes</code> folder, import the <code>signup</code> function from the controller, and create a POST route for <code>signup</code>, as follows.</p>\n<p><code>routes.allRoutes.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">import { Router } from &quot;https://deno.land/x/oak/mod.ts&quot;;</span>\n<span class=\"grvsc-line\">import {signup} from &quot;../controllers/users.ts&quot;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">const router = new Router();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">//User routes</span>\n<span class=\"grvsc-line\">router.post(&quot;/api/signup&quot;, signup)</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">export default router;</span></code></pre>\n<h2 id=\"create-authenticate-user-route\" style=\"position:relative;\"><a href=\"#create-authenticate-user-route\" aria-label=\"create authenticate user route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create Authenticate User route</h2>\n<p>Next, create an authentication route that authenticates your user route. The latest version of Deno does not allow a string as a secret key but accepts a cryptokey generated from a <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey\">Web Crypto API</a> with the <code>generatekey()</code> method of the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto\">SubtleCrypto</a> interface.</p>\n<p>So, head over to your <code>utils</code> folder, create a file called <code>apiKey.ts</code>,  and in the file, generate your key and export it, as follows.</p>\n<p><code>utils.apiKey.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">key</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">crypto</span><span class=\"mtk1\">.</span><span class=\"mtk12\">subtle</span><span class=\"mtk1\">.</span><span class=\"mtk11\">generateKey</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    { </span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;HMAC&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">hash:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;SHA-512&quot;</span><span class=\"mtk1\"> },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [</span><span class=\"mtk8\">&quot;sign&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;verify&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span></code></pre>\n<p>Now that you have successfully created your key, you can create a user authentication route so that every user that logs in will get authenticated.</p>\n<p>Head over to <code>user.ts</code> in your controller, import the API key, create a <code>signin</code> function, and write some validation logic to validate that the user exists in your database. If validation is successful, you create a token to authenticate the user. </p>\n<h2 id=\"using-jwt-to-authenticate-a-user\" style=\"position:relative;\"><a href=\"#using-jwt-to-authenticate-a-user\" aria-label=\"using jwt to authenticate a user permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using JWT to Authenticate a User</h2>\n<p>Now, let's import Deno JWT (djwt) <code>create</code> function from the URL to create a token. When a user logs in, take the id and username, pass the payload into the JWT <code>create</code> function, generate a token, and use the token to authenticate the user.</p>\n<p><code>controllers.users.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">db</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../database/connectDB.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk4\">*</span><span class=\"mtk1\"> </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/bcrypt/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">UserSchema</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../schema/user.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">create</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/djwt@v2.4/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">key</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../utils/apiKey.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Users</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">db</span><span class=\"mtk1\">.</span><span class=\"mtk11\">collection</span><span class=\"mtk1\">&lt;</span><span class=\"mtk10\">UserSchema</span><span class=\"mtk1\">&gt;(</span><span class=\"mtk8\">&quot;users&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//create a user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">signup</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\">({</span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">}:{</span><span class=\"mtk12\">request</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">username</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">} = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">().</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">salt</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\">.</span><span class=\"mtk11\">genSalt</span><span class=\"mtk1\">(</span><span class=\"mtk7\">8</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">hashedPassword</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\">.</span><span class=\"mtk11\">hash</span><span class=\"mtk1\">(</span><span class=\"mtk12\">password</span><span class=\"mtk1\">, </span><span class=\"mtk12\">salt</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">_id</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Users</span><span class=\"mtk1\">.</span><span class=\"mtk11\">insertOne</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">username</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">password:hashedPassword</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> =</span><span class=\"mtk7\">201</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;User created&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">userId:_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user:username</span><span class=\"mtk1\">}     </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   </span><span class=\"mtk3\">//sign in a user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">signin</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> ({</span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">}:{</span><span class=\"mtk12\">request</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">; </span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">username</span><span class=\"mtk1\">, </span><span class=\"mtk12\">password</span><span class=\"mtk1\">} = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">user</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Users</span><span class=\"mtk1\">.</span><span class=\"mtk11\">findOne</span><span class=\"mtk1\">({</span><span class=\"mtk12\">username</span><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">user</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">404</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`user &quot;</span><span class=\"mtk4\">${</span><span class=\"mtk12\">username</span><span class=\"mtk4\">}</span><span class=\"mtk8\">&quot; not found`</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">confirmPassword</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">bcrypt</span><span class=\"mtk1\">.</span><span class=\"mtk11\">compare</span><span class=\"mtk1\">(</span><span class=\"mtk12\">password</span><span class=\"mtk1\">, </span><span class=\"mtk12\">user</span><span class=\"mtk1\">.</span><span class=\"mtk12\">password</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">confirmPassword</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">404</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Incorrect password&quot;</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//authenticate a user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">payload</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">user</span><span class=\"mtk1\">.</span><span class=\"mtk12\">_id</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">username</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">jwt</span><span class=\"mtk1\"> =  </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">alg:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;HS512&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">typ:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;JWT&quot;</span><span class=\"mtk1\"> }, { </span><span class=\"mtk12\">payload</span><span class=\"mtk1\"> }, </span><span class=\"mtk12\">key</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk12\">jwt</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">userId:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">user</span><span class=\"mtk1\">.</span><span class=\"mtk12\">_id</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">username:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">user</span><span class=\"mtk1\">.</span><span class=\"mtk12\">username</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">token:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">jwt</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=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">500</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;internal server error&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>So far, you have progressed well. The next thing is to import your <code>signin</code> function in the routes and create a post request for it, as follows.</p>\n<p><code>routes.allRoutes.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">signup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/users.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//User routes</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signup&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signup</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signin&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Congratulations on making it this far! You are through with the authentication route. Now, you can register a user, sign in, and authenticate the user. </p>\n<p>You need to create your todo CRUD API and protect the routes so that a random person will not be able to access your route except when authenticated.</p>\n<p>Go to your <code>schema</code> folder, and create a file <code>task.ts</code>. In the file, create your tasks interface and export it.</p>\n<h2 id=\"create-todo-route\" style=\"position:relative;\"><a href=\"#create-todo-route\" aria-label=\"create todo route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create Todo Route</h2>\n<p><code>schema.task.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">interface</span><span class=\"mtk1\"> </span><span class=\"mtk10\">TaskSchema</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">name</span><span class=\"mtk1\">: </span><span class=\"mtk10\">string</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">isCompleted</span><span class=\"mtk1\">: </span><span class=\"mtk10\">boolean</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  } </span></span></code></pre>\n<p>After successfully creating the task interface, move to our controller, create a file <code>tasks.ts</code>, and import the database, schema, and object Id. Then write the logic for our todo CRUD API.</p>\n<p><code>controllers.tasks.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">db</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../database/connectDB.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">TaskSchema</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../schema/task.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">ObjectId</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/mongo@v0.30.0/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">db</span><span class=\"mtk1\">.</span><span class=\"mtk11\">collection</span><span class=\"mtk1\">&lt;</span><span class=\"mtk10\">TaskSchema</span><span class=\"mtk1\">&gt;(</span><span class=\"mtk8\">&quot;tasks&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">create</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\">({</span><span class=\"mtk12\">request</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">}:{</span><span class=\"mtk12\">request</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">name</span><span class=\"mtk1\">, </span><span class=\"mtk12\">isCompleted</span><span class=\"mtk1\">} = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">().</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">_id</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\">.</span><span class=\"mtk11\">insertOne</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isCompleted</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Task created!!&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">id:_id</span><span class=\"mtk1\">, </span><span class=\"mtk12\">name:name</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Completed:isCompleted</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getTasks</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> ({</span><span class=\"mtk12\">response</span><span class=\"mtk1\">}:{</span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">allTasks</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\">.</span><span class=\"mtk11\">find</span><span class=\"mtk1\">({}).</span><span class=\"mtk11\">toArray</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">tasks:allTasks</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  };</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getById</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> ({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">params</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   }:{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">params</span><span class=\"mtk1\">:{</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">:</span><span class=\"mtk10\">string</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">taskId</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">task</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\">.</span><span class=\"mtk11\">findOne</span><span class=\"mtk1\">({</span><span class=\"mtk12\">_id:</span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ObjectId</span><span class=\"mtk1\">(</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">)});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">task</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`no task with Id: </span><span class=\"mtk4\">${</span><span class=\"mtk12\">taskId</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">task:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">task</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">updateById</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> ({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">params</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">request</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}:{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">params</span><span class=\"mtk1\">:{</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">:</span><span class=\"mtk10\">string</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">request</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">taskId</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">name</span><span class=\"mtk1\">, </span><span class=\"mtk12\">isCompleted</span><span class=\"mtk1\">} = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk11\">body</span><span class=\"mtk1\">().</span><span class=\"mtk12\">value</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">task</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\">.</span><span class=\"mtk11\">updateOne</span><span class=\"mtk1\">({</span><span class=\"mtk12\">_id:</span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ObjectId</span><span class=\"mtk1\">(</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">)},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">$set:</span><span class=\"mtk1\">{</span><span class=\"mtk12\">name:name</span><span class=\"mtk1\">, </span><span class=\"mtk12\">isCompleted:isCompleted</span><span class=\"mtk1\">}});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk8\">&quot;Updated task&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">task:task</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">deleteTask</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> ({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">params</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</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\">params</span><span class=\"mtk1\">:{</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">:</span><span class=\"mtk10\">string</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">taskId</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">params</span><span class=\"mtk1\">.</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">task</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tasks</span><span class=\"mtk1\">.</span><span class=\"mtk11\">deleteOne</span><span class=\"mtk1\">({</span><span class=\"mtk12\">_id:</span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ObjectId</span><span class=\"mtk1\">(</span><span class=\"mtk12\">taskId</span><span class=\"mtk1\">)});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">200</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> = {</span><span class=\"mtk12\">message:</span><span class=\"mtk8\">&quot;Deleted task&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">task:task</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<p>With that out of the way, you need to create your todo CRUD routes. So, head over to <code>allRoutes.ts</code> and import the CRUD functions from the task controllers, then create the routes for our todo, as follows.</p>\n<p><code>routes.allRoutes.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">signup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/users.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">create</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getTasks</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getById</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateById</span><span class=\"mtk1\">, </span><span class=\"mtk12\">deleteTask</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/tasks.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//User routes</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signup&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signup</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signin&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//Task routes</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">create</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getTasks</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getById</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">patch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateById</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">deleteTask</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\">;</span></span></code></pre>\n<h2 id=\"protect-todo-routes\" style=\"position:relative;\"><a href=\"#protect-todo-routes\" aria-label=\"protect todo routes 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>Protect Todo Routes</h2>\n<p>You need to protect your todo routes so that an unauthorized person will not be able to access them.</p>\n<p>To protect the todo routes, go to your <code>middlewares</code> folder: create a file called <code>isAuthorized.ts</code>, import the <code>verify</code> function from deno JWT URL, import <code>Context</code> from deno, import the secret key you've created, and create the <code>authorized</code> function.</p>\n<p>The authorize function checks if a user has a JWT token, grant the user access if he does, and deny him access if otherwise.</p>\n<p><code>middlewares.isAuthorized.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">verify</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/djwt@v2.4/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">key</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../utils/apiKey.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Context</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">authourized</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Context</span><span class=\"mtk1\">, </span><span class=\"mtk12\">next</span><span class=\"mtk1\">:</span><span class=\"mtk10\">any</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">try</span><span class=\"mtk1\">{   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">headers</span><span class=\"mtk1\">: </span><span class=\"mtk10\">Headers</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">request</span><span class=\"mtk1\">.</span><span class=\"mtk12\">headers</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">authorization</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">headers</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Authorization&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">authorization</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">401</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">jwt</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">authorization</span><span class=\"mtk1\">.</span><span class=\"mtk11\">split</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39; &#39;</span><span class=\"mtk1\">)[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">jwt</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">401</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">payload</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">verify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">jwt</span><span class=\"mtk1\">, </span><span class=\"mtk12\">key</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">payload</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">throw</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Error</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;!payload&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">next</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=\"mtk15\">catch</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">error</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">status</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">401</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">ctx</span><span class=\"mtk1\">.</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\"> ={</span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;You are not authorized to access this route&quot;</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<p>To protect your todo routes, import the authorized middleware function from the <code>isAuthorized.ts</code> middleware file and pass the middleware into the todo routes to protect them from unauthorized people.</p>\n<p><code>routes.allRoutes.ts</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">Router</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;https://deno.land/x/oak/mod.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">signup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/users.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">create</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getTasks</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getById</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateById</span><span class=\"mtk1\">, </span><span class=\"mtk12\">deleteTask</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../controllers/tasks.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../middlewares/isAuthorized.ts&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Router</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//User routes</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signup&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signup</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/signin&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">signin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//Task routes</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">router</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\">, </span><span class=\"mtk12\">create</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getTasks</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getById</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">patch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\">, </span><span class=\"mtk12\">updateById</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">delete</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/api/tasks/:taskId&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">authourized</span><span class=\"mtk1\">, </span><span class=\"mtk12\">deleteTask</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">router</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Awesome! Your application is ready, but wait! Don't get too excited yet, relax let's test the application :)</p>\n<p>Below is what your final project directory looks like:</p>\n<p><code>DenoAPI_JWT_Auth</code>  </p>\n<p>│<br>\n└─<strong>src</strong><br>\n│   └───controllers<br>\n│   │      └───users.ts<br>\n│   │      └───tasks.ts<br>\n│   │\n│   └───database<br>\n│   │      └───connectDB.ts<br>\n│   │<br>\n│   └───middlewares<br>\n│   │      └───isAuthorized.ts<br>\n│   │<br>\n│   └───routes<br>\n│   │      └───allRoutes.ts<br>\n│   │\n│   └───schema<br>\n│   │      └───user.ts<br>\n│   │      └───task.ts<br>\n│   │\n│   └───utils<br>\n│   │      └───apiKey.ts<br>\n│   │<br>\n└─<strong>app.ts</strong>  </p>\n<h2 id=\"test-application\" style=\"position:relative;\"><a href=\"#test-application\" aria-label=\"test application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Test Application</h2>\n<p>Now that your application is ready, you need to test the various routes to ensure they are working. To test the routes, rerun your server with <code>deno run --allow-net app.ts</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 715px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 12.461538461538462%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAdElEQVQI102MwQ6CMBQEHwcvkoYYSo1ewCrYtBdBjaFy8/+/aUxqBA6b3UyyI/oWMc8J85gohxHtI7v6RW496hxQl0DRhrS3tSdvFr45OqTqyMx1jtjhw8G/MS6ydyOFvaNOParpkbJNB9Hdr//RC0uSlfQLJDA1TH1m1mYAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"deno run screenshot\"\n        title=\"deno run screenshot\"\n        src=\"/static/60cd74e5ef22e5c2a2926d2314375c0c/d0c0e/apk23wt.png\"\n        srcset=\"/static/60cd74e5ef22e5c2a2926d2314375c0c/a6d36/apk23wt.png 650w,\n/static/60cd74e5ef22e5c2a2926d2314375c0c/d0c0e/apk23wt.png 715w\"\n        sizes=\"(max-width: 715px) 100vw, 715px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Great! The app is running on port:8080. You can now head to the postman to test your routes.</p>\n<h3 id=\"signup-route\" style=\"position:relative;\"><a href=\"#signup-route\" aria-label=\"signup route 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>Signup Route</h3>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 326px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 15.644171779141104%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAp0lEQVQI1z2OSw6CQBBEOQkzAwnMj48a3LlBCAhMIFHPIPe/QNl0jIvKq65OVzrSWiPLMhii/inPc1aappBSQikFKQR7QUyShCWF5CyO438etV2Pz76ju7dc4pxDVZbM8+mCZZkx9AOmccIcHuR7hHXD8/3CMo8Ic8C6Bbq/QUmFqKTj5tqgKAoYY2Ct5bKDx+fszZF59p5kaGedhfc0e4+6roiWP/wChBldbhvEbzsAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Sign up\"\n        title=\"Sign up\"\n        src=\"/static/302f2a15bb851bd8f7546c4f2b1d9fcc/ce9b1/d2orbz0.png\"\n        srcset=\"/static/302f2a15bb851bd8f7546c4f2b1d9fcc/ce9b1/d2orbz0.png 326w\"\n        sizes=\"(max-width: 326px) 100vw, 326px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.38461538461539%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABV0lEQVQoz31SW1KEMBDMNfyRvEMISUpqwarVC/jlt+fwOB62nYksLrjrR1dDKtPTMx1xOp2wLAvO5zNqrXDOwVoLozWMMQ165SM03QkhoJYCW18QX98hxnFsIoUOp2nCvMzIeYT3Hj1dvnC4A09wWkK+feLh4wsipURiGTFFJBIvNWN6Ksj8TU1YPKZKLj2k7CCVIpYbFP0zZPcIEwoEO4gpN+TYw5NbHseuY/H42lgq0lvxbWhYHyB4Dy5EuD4iWC6SOwebk+OZ2rtkZgNCSbbbNXSHMbZxpLrZZI+uNRVcwC43XHZ0ZzS9pq+N3kEZR+wgnucZaRhaKMOYEGNsyTpnf8R3TmUT9MHD9JZ2Rk/M0xNjUCAmZHo2icRGCmVIFEpAomACFThrN7dq2+PV6N1xxx0FqTkUhZAKuSTB4BDJmbfmz8Kv+RZ+Q7kcrgLHYP4TOQoyfwPRtTkmgfkB6gAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"trydtxn\"\n        title=\"trydtxn\"\n        src=\"/static/d0bd11adeaf0889aa4a2c39c6b24f1d2/e5715/trydtxn.png\"\n        srcset=\"/static/d0bd11adeaf0889aa4a2c39c6b24f1d2/a6d36/trydtxn.png 650w,\n/static/d0bd11adeaf0889aa4a2c39c6b24f1d2/e5715/trydtxn.png 768w,\n/static/d0bd11adeaf0889aa4a2c39c6b24f1d2/6be49/trydtxn.png 1160w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"sign-in-route\" style=\"position:relative;\"><a href=\"#sign-in-route\" aria-label=\"sign in route 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>Sign-in Route</h3>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 313px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 18.530351437699682%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA0ElEQVQY02WP3U6FMBCEeQ9+EwJV4NAY2lNujJwYaO3BG/UGff/n+CwYTdSLyc7MbmYzUVEU5HlOVVX/UJYlWZ4d+79I05Qs4JcfsiJrLd57pOxpmoa2bem6jrZrEfUN4ziitMJog1JD0GfUoJguEw/TBa01ozGYs2G4k0TbxzvbtnHaQ0LYHiqlpO9PCHGLXRzOLdjZYV14fnUs88z6vOL8GvQT69Xz+vKGfbwnKvKCvbYQ4gd1XR9zr5wkSaiXkaTJwb90ShzHgccH//b2u0/dmXqnyZcy6wAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Signin Route URL\"\n        title=\"Signin Route URL\"\n        src=\"/static/4b20b100c466f0c71be5ab91702d6165/80977/fee5d0s.png\"\n        srcset=\"/static/4b20b100c466f0c71be5ab91702d6165/80977/fee5d0s.png 313w\"\n        sizes=\"(max-width: 313px) 100vw, 313px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 55.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABWklEQVQoz5WSR1LEQAxF+xbsxnbn6DShKFYcgAU7DsQpOO1HcsCD8SxYvJLcln4rtOj7HsMw4Ha7oR96eO+htYGUckIp9WP38DnHp5Rhz6/wL28QpW3hnQfbcRxxuV7Qd+0UGEK4sw7OHWAtjLE4vX/i6eMLIsaIUgpSjogpoSWxcWhRMvl0Cf8LqYNUFnVdoWkasvUGfTd8Tr52BYJLdyHB5w7Z021aUWAzJf4HFrZUseA5aCpZWQejaG77Cg5YBVbWqrUxEOxUVbWwJTR3gXt7SHWi/zWEJVVuWxsNRe1qrbfZHMAdGc6xFG82pEmQ2kM801YTLYO36GmbvFGehbXz0/nV4uJPT0bfwc/IJhImQRYKuSCWDl30yMEh0hkvRz5aAgv/oaIcPc/Q+EhPpMM1e5zTTE/CHTFEN/mTjfNZpHbDCrXrzTwmxYLbrdU2pxW5swuPFsOj+AZ4PDqoXBkAHAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Signin Route\"\n        title=\"Signin Route\"\n        src=\"/static/6a023599e3ea65da4cf6216c918bfb40/e5715/wncqtya.png\"\n        srcset=\"/static/6a023599e3ea65da4cf6216c918bfb40/a6d36/wncqtya.png 650w,\n/static/6a023599e3ea65da4cf6216c918bfb40/e5715/wncqtya.png 768w,\n/static/6a023599e3ea65da4cf6216c918bfb40/afd0b/wncqtya.png 1153w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Amazing! Now that you have signed up and authenticated a user, the returned token, which shows that the user has been authenticated, can be used to access your todo CRUD APIs.</p>\n<h3 id=\"accessing-the-todo-routes\" style=\"position:relative;\"><a href=\"#accessing-the-todo-routes\" aria-label=\"accessing the todo routes 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>Accessing the Todo Routes</h3>\n<p>First, let's try accessing your todo routes without the token...</p>\n<h4 id=\"create-task-route\" style=\"position:relative;\"><a href=\"#create-task-route\" aria-label=\"create task route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Create Task Route</h4>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 14.0625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAl0lEQVQI122OQQ7CIBBFexaBgQKCPYBJdyYgEWpNvYTp/VdfaGNXLl7+BDJ/Xue9h3MOxpgDay36vocQ4oBzAaKWHFJKSKX29+Of48QYus+64lkKdC3QtUxrjWEYQIIwXkfkqSDeAuI9YZozUgx45ILlvWB+FZScN1IKW3F3qcvu/N+Q1YvNhoj2lHv+rJWSUM220mbOGb6c6F6YqBgtZQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Create Task Route URL\"\n        title=\"Create Task Route URL\"\n        src=\"/static/13c5d5fa3ba7c1dba862e9419f2e4134/72799/0bohcxv.png\"\n        srcset=\"/static/13c5d5fa3ba7c1dba862e9419f2e4134/72799/0bohcxv.png 320w\"\n        sizes=\"(max-width: 320px) 100vw, 320px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span>  </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABLElEQVQoz22SSVLEMAxFcwo2FGTwGA+xU6GruliwYMGaLYfgKlz58+UeKtC9eCUnkaX/pXS1VpRacDgcIOcQAowxUErdoLX+g7zz3iPGCLV9wLx9oUspwTmHlBPqWrG9bCglt8R5nq9Rcqy1d5Hij+/fePj8QSeKcs6IKSBEnpeMtS7IKWJZGNnIx4JRGQxDT4Z/jBgZx/4J2szotFZY1oJ1W7GViBQdFVmEC2EXG27H/pnWEwtKFyXzMLbNRLoNIzs2xpvYVPVn9kr755bTxdmfh8yhG90WcipwH6MNtOXSHGG+3JE42YRJe3Svx2PbbuRy0pkgy+AS9DS17pdizY1snM0nQ9TEIqeoLP8OF2iZMo2jSutg+MESz2TLRCeq1W3Rq+2d5Z6WLd39Atsq51LkvW44AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Create Task Route Access Denied\"\n        title=\"Create Task Route Access Denied\"\n        src=\"/static/eddf56128a683e03a2c63c00e4b6ee0e/e5715/q6eetmg.png\"\n        srcset=\"/static/eddf56128a683e03a2c63c00e4b6ee0e/a6d36/q6eetmg.png 650w,\n/static/eddf56128a683e03a2c63c00e4b6ee0e/e5715/q6eetmg.png 768w,\n/static/eddf56128a683e03a2c63c00e4b6ee0e/4dba2/q6eetmg.png 1151w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>As you can see, when you tried to create a task, you got a message <code>You are not authorized to access this route</code> because a random person did it without a token.</p>\n<p>Now, let's also try accessing the delete by Id route without the token...</p>\n<h4 id=\"delete-task-route\" style=\"position:relative;\"><a href=\"#delete-task-route\" aria-label=\"delete task route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Delete Task Route</h4>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 503px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 9.74155069582505%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAcElEQVQI1y2MURKEIAxDPQ4gfK0rI8VWKYz3P1G2un68SdJ0Mu3CyDnDOYcQApbPAmYGlYJa6fE3lchyhYg87OZZ/h1bLtuGGCOmcV0ge/beY54j1u+KrorWzhfFGB3aGrSrqfH2tx7nYfcOseGUEn4MDUPYmWyg+gAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Delete Task Route URL\"\n        title=\"Delete Task Route URL\"\n        src=\"/static/b7fd865acc41ec16e1086373a2254185/a4078/ngozekb.png\"\n        srcset=\"/static/b7fd865acc41ec16e1086373a2254185/a4078/ngozekb.png 503w\"\n        sizes=\"(max-width: 503px) 100vw, 503px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.53846153846153%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABRElEQVQoz42SS07DMBCGfQfWKPHYjh9JH26UUiSWXKISJ2PFTX/GUzdNaSksPtma+T1Pq2maMO0nHA4H4bWeMQQ450BEv6I1YRh6xH4Fn9+QXt6h+p4NMSHnjN24Q95lYc+JxnFkX0Tg4N77W4rdGZhhwvPHJ56OX1Db9RodO8kaWGdBLCBDUp21Vih3rbXQtq1UZ1hT7mJvG2hy6MIAVTJdHJdHJVDXdXKf/dWXpKs421vG+w7bzQZqKf4vrb5Ockqk0TTNKeA1VXRjf4y0ze+UPJaNaVBt6Web51ZFU7Smct624ORUq2GQefgYkFKal2GIbmZXHpe5msAaxvASredFii1DWw+15kF6/jbl38Xg0XPwJN+BxbXyefjn6pvKohviuZYYypRqHGcgLZQgcnJLhWXAh4tijffh3lLuDPyPoEvNN4L8OOdGI11OAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Delete Task Route Access Denied\"\n        title=\"Delete Task Route Access Denied\"\n        src=\"/static/4359067413cbb62e82e14c00c55ad0e2/e5715/cdkr6ad.png\"\n        srcset=\"/static/4359067413cbb62e82e14c00c55ad0e2/a6d36/cdkr6ad.png 650w,\n/static/4359067413cbb62e82e14c00c55ad0e2/e5715/cdkr6ad.png 768w,\n/static/4359067413cbb62e82e14c00c55ad0e2/4ad3a/cdkr6ad.png 1152w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Your todo CRUD APIs have been protected, and the only way a user can access them is by getting authenticated. Now let's log in again and use the returned token to access the todo routes.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 34.61538461538461%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABCElEQVQoz3WQTW7DIBCFuUal2gYbzI/t1r+xkiwaWereCyfrXCGH6jlfgZSWRu3i04wej8cwZBxHzPOMw/EIozWKokCe52CMeULv6iNOb5oGuqqh2j306wTiBaXQtS2GYcA0jdBGQ1ktRkqJsix/IaXVeQ7+ssfz9QNP7zcQIQTayqCpNKSSEKWAkD+XOOe+uonc9DEsv/+CUQpaKDCuQLQ2NkTCmAp9339P4oxZlvmaJAm6rsO2bThbLucL1nWFtisKHkYzH0xU1ULXPZTFBTNmX6N3wh7dpbqusSwLTm8n7HaTX4+bPvjol5dkVgjEId4Uaa6maepxEzvis9CTOOAx7K/+P1+onyRMy5qh9V8JAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Tasks\"\n        title=\"Tasks\"\n        src=\"/static/88a4b27df7688f5717979bed2432bdd3/e5715/ehp4zwf.png\"\n        srcset=\"/static/88a4b27df7688f5717979bed2432bdd3/a6d36/ehp4zwf.png 650w,\n/static/88a4b27df7688f5717979bed2432bdd3/e5715/ehp4zwf.png 768w,\n/static/88a4b27df7688f5717979bed2432bdd3/5a3c9/ehp4zwf.png 1169w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>So, you have logged a user in and put the returned Bearer's token in the authorization header. You can access our todo APIs now because, with the bearer's token, you are authorized to access the todo APIs.</p>\n<h4 id=\"create-task-route-1\" style=\"position:relative;\"><a href=\"#create-task-route-1\" aria-label=\"create task route 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>Create Task Route</h4>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 320px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 14.0625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAl0lEQVQI122OQQ7CIBBFexaBgQKCPYBJdyYgEWpNvYTp/VdfaGNXLl7+BDJ/Xue9h3MOxpgDay36vocQ4oBzAaKWHFJKSKX29+Of48QYus+64lkKdC3QtUxrjWEYQIIwXkfkqSDeAuI9YZozUgx45ILlvWB+FZScN1IKW3F3qcvu/N+Q1YvNhoj2lHv+rJWSUM220mbOGb6c6F6YqBgtZQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Create Task Route URL\"\n        title=\"Create Task Route URL\"\n        src=\"/static/13c5d5fa3ba7c1dba862e9419f2e4134/72799/y9ilrk9.png\"\n        srcset=\"/static/13c5d5fa3ba7c1dba862e9419f2e4134/72799/y9ilrk9.png 320w\"\n        sizes=\"(max-width: 320px) 100vw, 320px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 52.46153846153846%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSklEQVQoz51SSU7EMBD0N5Agi/c1MZFGAk4cOHPjxCf4CU8uygmBYRjmwKHUtttd7uqyqLVirjMOhwPaOsUIYwyUUj+gtf6Fdh5DQEgF5vEV+v4ZopQC7z3KVFBvK5Zlwcy1Dx6R5C0XWOScg7X2BDwzJHcR1y/vuHp6g4gxoOSCmFjMwka8zGUlSykzl2HDhGFU6Pse/TAwfmPgfuhuMDKnlIVQSqLME2VXTMmzE8OXNeMO8xX9JXgLRwgpJaxj+5TmSGR0m9f/ITYJlNJ1W9xlXMB+7zgOfYdxHCECh726Rme12dxrib/QFK2/oN0l1AoDaROkMhAP93eYaESgCTEnmpM4C8+5WEgStI52sn3dHpWUpz4xKpK6DGM9RLvg+I9yoTHeIJNI83+dkhzHs6DkVidaFzZm5KmSjA63VynrXGfHZ6cYhq3zD6nJHtrMGTr/AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Create Task Route Access Granted\"\n        title=\"Create Task Route Access Granted\"\n        src=\"/static/a88a8a15e6fe5ce4b8a1d33ffdf1491f/e5715/nbiaskx.png\"\n        srcset=\"/static/a88a8a15e6fe5ce4b8a1d33ffdf1491f/a6d36/nbiaskx.png 650w,\n/static/a88a8a15e6fe5ce4b8a1d33ffdf1491f/e5715/nbiaskx.png 768w,\n/static/a88a8a15e6fe5ce4b8a1d33ffdf1491f/d74fe/nbiaskx.png 1164w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"get-all-tasks-route\" style=\"position:relative;\"><a href=\"#get-all-tasks-route\" aria-label=\"get all tasks route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Get All Tasks Route</h4>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 313px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 15.015974440894567%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAmklEQVQI11WPyw6CMBRE+ZXSFy3dUDaGRCNuNAEsBb/BRP9/P97WR3AxObkzyWRuobWGVgpVVcEY86eUlWUJxhg455nfWwiRtfUSC9+2uD8fOB33udQ5h7qu4ZsGShv0hx4xBlzOI67TgDBPmIYRcb1hIc10LyGQH9B1OxTGWHjfwlHJdp21Ni8UXPzWJin6JlESFfGdfTwp8QK/2l13kFg0mQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Get All Tasks Route\"\n        title=\"Get All Tasks Route\"\n        src=\"/static/99aa3aea1516970dab8b17908f446500/80977/zosrr9u.png\"\n        srcset=\"/static/99aa3aea1516970dab8b17908f446500/80977/zosrr9u.png 313w\"\n        sizes=\"(max-width: 313px) 100vw, 313px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.69230769230769%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABXElEQVQoz52TS07EMBBEfQt2+Nf+O4nRLGYNey7CCTgdVyu6E0Ki0WiEWDzFTsflqm5F5ZwxxsD1el1ZxoKUEkrJkJqwr0s+3q3UhkLPcO+fePr4gh6vUL119HlCbW0Vu1wGpt4wTTN676h9gQ8ZxhjG3kFDU4FZ3mB8hJpYTITGVFmooLeMVhMq03hdakbKETmFB3h2H0HeQ5VaUNhN44MxeHhyIPKM+yUIXAvr++N5sNW9d1BbFAPNWGux7yXOtj+QvXMO9gbjiJ+01tU8szvuWW2VIzZEHkiMEV4+/Llkv0jEgtQygWIAcVwfCS52UFk2wRC4ELlnPJyZp9kzr1O8cXugtYZh9AmjedJ2u1A5Pkgpo85jFUzSE+7F7uyv7C1REk0cltrR2FkKhMiiu0N7x+WZ/TvvZTgkgnYT7PMa9+zw3MNHSGxpnfwQyrktchsXvPSKwg7J/V/wG61TOtgzzQC7AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Get All Tasks Route Access Granted\"\n        title=\"Get All Tasks Route Access Granted\"\n        src=\"/static/70d1e40746853de6d2585d1309a369ed/e5715/zxkgmsm.png\"\n        srcset=\"/static/70d1e40746853de6d2585d1309a369ed/a6d36/zxkgmsm.png 650w,\n/static/70d1e40746853de6d2585d1309a369ed/e5715/zxkgmsm.png 768w,\n/static/70d1e40746853de6d2585d1309a369ed/105d8/zxkgmsm.png 1170w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"get-task-by-id-route\" style=\"position:relative;\"><a href=\"#get-task-by-id-route\" aria-label=\"get task by id route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Get Task By Id Route</h4>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 503px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 9.74155069582505%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAcElEQVQI1y2MURKEIAxDPQ4gfK0rI8VWKYz3P1G2un68SdJ0Mu3CyDnDOYcQApbPAmYGlYJa6fE3lchyhYg87OZZ/h1bLtuGGCOmcV0ge/beY54j1u+KrorWzhfFGB3aGrSrqfH2tx7nYfcOseGUEn4MDUPYmWyg+gAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Get Task By Id Route\"\n        title=\"Get Task By Id Route\"\n        src=\"/static/b7fd865acc41ec16e1086373a2254185/a4078/hph0xmy.png\"\n        srcset=\"/static/b7fd865acc41ec16e1086373a2254185/a4078/hph0xmy.png 503w\"\n        sizes=\"(max-width: 503px) 100vw, 503px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 46.61538461538461%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABPUlEQVQoz3VSy04DMQzMXyAuzeblZF/JtlXZcuCIxIE7f8Cdb+DDBztl2W1VDiNblj3jjKNKKZj2E06nE+Z5rng+n3E4HNB1HYgIzjl4768QQoDj2LYt+n6Ae/mAf/2EKnkEBcIwDihTqcjTReR4PHJzj5QSYoyVRAQkCulfzoL67QsP799Q+5Ix8JBxFsYKDBqG5VyaJcqGxnC9aSqkJmTGNGtt94ieHJTlZhmQogxtIUP2l2ipSS5CXd9V8aXufKhPV1qvKgu2w7ciS11rvfbXqKF3O6iBjRfFQBcQ5/dIFiJ5TYh8qMjH4X5HHi54WBphfYI6z0/IOddrtUwul5U8yRB7dW9jK34zxMuai+c+giITSpOniDRkjInQsWIK7sq7rRW39qzQLGCglj8W+5G34y/i3b8e/ufp1o4fUkQBnvDjL70AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Get Task By Id Route Access Granted\"\n        title=\"Get Task By Id Route Access Granted\"\n        src=\"/static/8a8588a75ce26b99cd275e357b924e0f/e5715/get-task-by-id.png\"\n        srcset=\"/static/8a8588a75ce26b99cd275e357b924e0f/a6d36/get-task-by-id.png 650w,\n/static/8a8588a75ce26b99cd275e357b924e0f/e5715/get-task-by-id.png 768w,\n/static/8a8588a75ce26b99cd275e357b924e0f/e6c84/get-task-by-id.png 1148w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Feel free to test the other routes to see how things work.</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 tutorial, you've built a todo CRUD API and protected the routes from unauthorized access using JSON Web Token (JWT). You have learned how to create an Oak server in Deno, connect MongoDB, implement JWT authentication, as well as create and authenticate CRUD routes in a Deno application. </p>\n<p><a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Deno/denoAPI_JWT_Auth\">The code for this tutorial is available here</a> on Github. Feel free to clone and extend the features of the application.</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 .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"July 28, 2022","updated_date":null,"description":"In this hands-on tutorial, you'll learn from scratch how to implement JWT authentication for CRUD APIs in Deno.","title":"How to Implement JWT Authentication for CRUD APIs in Deno","tags":["JWT","Deno","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4d526ec8bb1f9453095b950dfc3c462d/ee604/jwt-authentication-with-deno.png","srcSet":"/static/4d526ec8bb1f9453095b950dfc3c462d/69585/jwt-authentication-with-deno.png 200w,\n/static/4d526ec8bb1f9453095b950dfc3c462d/497c6/jwt-authentication-with-deno.png 400w,\n/static/4d526ec8bb1f9453095b950dfc3c462d/ee604/jwt-authentication-with-deno.png 800w,\n/static/4d526ec8bb1f9453095b950dfc3c462d/f3583/jwt-authentication-with-deno.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Ekekenta Odionyenfe Clinton","github":"icode247","avatar":null}}}}]},"markdownRemark":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected 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 is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers 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>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso 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>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso 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>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies 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>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips 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>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access 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>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets 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>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm 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>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out 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 is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in 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>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary 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>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references 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>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\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":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},"pageContext":{"limit":6,"skip":0,"currentPage":1,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}