{
    "componentChunkName": "component---src-pages-blog-markdown-remark-fields-slug-js",
    "path": "/blog/how-to-implement-oidc-with-microsoft-entra-id",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents 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>Table of Contents</h2>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"23779253359736697000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`tight: true\ntoHeading: 3`, `23779253359736697000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"table-of-contents\">\n<ul>\n<li><a href=\"#how-to-implement-oidc-with-microsoft-entra-id\">How to implement OIDC with Microsoft Entra ID</a></li>\n<li><a href=\"#how-the-oauthoidc-flow-works\">How the Oauth/OIDC Flow works</a></li>\n<li><a href=\"#create-an-application-in-microsoft-entra-id\">Create an application in Microsoft Entra ID</a></li>\n<li><a href=\"#configure-your-application-for-microsoft-entra-id-oauth\">Configure your application for Microsoft Entra ID Oauth</a></li>\n<li><a href=\"#configure-supertokens-for-microsoft-entra-id-oauth\">Configure SuperTokens for Microsoft Entra ID Oauth</a></li>\n<li><a href=\"#conclusion\">Conclusion</a></li>\n</ul>\n</div>\n<h2 id=\"how-to-implement-oidc-with-microsoft-entra-id\" style=\"position:relative;\"><a href=\"#how-to-implement-oidc-with-microsoft-entra-id\" aria-label=\"how to implement oidc with microsoft entra id permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to implement OIDC with Microsoft Entra ID</h2>\n<p>Microsoft Entra ID - previously known as Azure AD - is a popular cloud-based version of <a href=\"https://supertokens.com/blog/what-is-ldap\" target=\"_blank\" rel=\"nofollow\">Active Directory</a>. Many companies love using Active Directory to organise their company and manage user permissions and roles. This makes Active Directory a great candidate for being an Identity Provider for applications that support SSO.</p>\n<p>This guide will both show you how to make your own Oauth/OIDC implementation in express as well as how to integrate Entra ID SSO with SuperTokens. <a href=\"https://supertokens.com/\" target=\"_blank\" rel=\"nofollow\">SuperTokens is our authentication platform</a> that you can integrate in your web applications to handle user sessions.</p>\n<h2 id=\"how-the-oauthoidc-flow-works\" style=\"position:relative;\"><a href=\"#how-the-oauthoidc-flow-works\" aria-label=\"how the oauthoidc flow works permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How the Oauth/OIDC Flow works</h2>\n<p>The user is redirected to the identity provider’s website in order to give their credentials and verify themselves. After the user has been verified, the provider sends us back an authorization code that we can trade for an id token that contains the user’s basic information, like name and email. The information we can read is set in the scope, which is shown to the user when they log in to their identity provider.</p>\n<h2 id=\"create-an-application-in-microsoft-entra-id\" style=\"position:relative;\"><a href=\"#create-an-application-in-microsoft-entra-id\" aria-label=\"create an application in microsoft entra id 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 an application in Microsoft Entra ID</h2>\n<p>In order to set up Oauth, we have to register our application with Microsoft so it knows what application is asking for user information. When we register, we are given a Client ID that we give back to Microsoft during the Oauth process so it knows it’s us.</p>\n<p>Head to the <a href=\"https://entra.microsoft.com/#home\" target=\"_blank\" rel=\"nofollow\">Microsoft Entra homepage</a>. On the left sidebar, click <code class=\"language-text\">Applications -> App Registration -> Create a New Registration</code>. This page will ask you for a Redirect URI and a platform. The platform will be web. The Redirect URI is where Microsoft will send the access code to during the Oauth flow. This endpoint will need to be created later in your app, but we can tell Microsoft what it will be now.</p>\n<p><strong>Express redirect URI</strong>: <code class=\"language-text\">http://localhost:3000/auth/callback</code></p>\n<p><strong>SuperTokens redirect URI</strong>: <code class=\"language-text\">http://localhost:3000/auth/callback/entra</code></p>\n<p>Under supported account types, you’ll be asked if you want to handle single tenant, multi-tenant, or personal accounts. This will depend on your use case:</p>\n<p><strong>Single tenant</strong> - making an internal tool and only want people in your organisation to be able to use this application.</p>\n<p><strong>Multi-tenant</strong> - making a tool for corporate users that allows others to login with their Entra ID account.</p>\n<p><strong>Common</strong> - allows anyone with any microsoft account to log in (xbox, skype, etc)</p>\n<p>Select whichever use case is right for you.</p>\n<p>After saving, you should  be redirected to the overview page containing your Client ID (also referred to as an Application ID). If you aren’t redirected to this page, then you can click <code class=\"language-text\">security -> permissions -> app registration -> overview</code> in the new left hand tab. Save the Client ID to add to your application later.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6bf035032bd2435f19ae67c98b090d67/1df5b/entra-id-application-id.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 55.06329113924051%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAACW0lEQVQozz1Sy07bQBT1BxUUECqif8ACBFIpFBb0G8qii6pdQIhoxauQVCIhD7/GnvF4xmM7dkLS8luz8qk8oSyOzh3p3NeZa71dX8e7jQ2sra1hdXUVKysr2N7awtHRIQ4O9g0fHn7E3t57g/39D/h0fIzNzU28WVp6zWssL6PRaMDqD4dwbBvE9+FRDkICKKUwmUxQlCWKokRZFphOp3h6qvFk4klZYjweoygKw3meI8+yRcHBYADHceB6HgJCEPMIhMYYuiG8IAKNJKI4AeMSJOQImQAXCrFMDbhYQCQprN5jH7Ztw/M8kICAUgopJbIsw2w2M6KHXh/9fh+e7yPPx+CxgJQJmFAIuIJSKVS6gPU6nevCD0IwxszKaZri+fkZt7/usL2zi53dXZycfDZNak3MOQhP4LHEaOt1syyF9fjYMxPWBYMwBCHECIRU6I98OF4IN4iNBSSM4PohPELh+hReDbKASyKTYz10u+j1emblekLOuTFYSQFKPNDAh4go4v/gCxY1c4YoYmCMQsQRVCJh1cWMh2blAFEUIVULX2IpkSQJKGPGW0rDF6av7zAMjUV5/rJyt9utBoNB5ThO5ZOgIoRUQogqTdMqz/JKqaRyHLuy7VE1HA4r27YNRqORQR1LKY1eKVVZ9suH1J2yPDf3V04m5uYGTMAPJWKegaox/s7nEOMpqCrwZzbDfD6HysYYEWbus861zppN3Wye6VarpW9vb3S7fa/v7+90p32vvza/62/Nc/3z8lp/Ob/Unfadvri60acXi7jWXV1f69PWD/270zHvf/XgcZJEIrwiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Entra ID application ID\"\n        title=\"Entra ID application ID\"\n        src=\"/static/6bf035032bd2435f19ae67c98b090d67/f058b/entra-id-application-id.png\"\n        srcset=\"/static/6bf035032bd2435f19ae67c98b090d67/c26ae/entra-id-application-id.png 158w,\n/static/6bf035032bd2435f19ae67c98b090d67/6bdcf/entra-id-application-id.png 315w,\n/static/6bf035032bd2435f19ae67c98b090d67/f058b/entra-id-application-id.png 630w,\n/static/6bf035032bd2435f19ae67c98b090d67/40601/entra-id-application-id.png 945w,\n/static/6bf035032bd2435f19ae67c98b090d67/78612/entra-id-application-id.png 1260w,\n/static/6bf035032bd2435f19ae67c98b090d67/1df5b/entra-id-application-id.png 1999w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>Click on Authentication on the left hand side. Under the section “Implicit grant and hybrid flows”, select the option:</p>\n<p><code class=\"language-text\">ID tokens (used for implicit and hybrid flows)</code></p>\n<p>And then save at the bottom.</p>\n<p>Click “Certificates and Secrets” on the left side of the screen and create a new Client Secret. The Client Secret is used to verify that the Oauth flow was started by the owner of the registered app, as this key is meant to be kept private. Copy the Client Secret Value - and not the Client Secret ID - for use later in the 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: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/14be5e17618ec00b03b92c1f73678dea/1df5b/entra-id-secret-key.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 55.06329113924051%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB40lEQVQoz5WSzXLaMBSF/RSsaicsYN00ZZekpHkrFuw7zbRQJos6BmwMlmVZ/pEx9pBpXu107g3OdNh1cUZXsvTdn2NrMBhgOByi3+/DubiE7TgYjUa4vx/j7u4W4/EX3N7c4Pr6E2s0+oyHh6+4uvqIXq8H27Zx4Ti4tD/AcWxY374/Yjb7ifl8jqenX3j8McNqtcJ2u0UYhkiSBFmWIc/zkzLeiyjCcrnEer2G53n47bpwXRdWEIbYBAGEENBaoyhylGXJsVIKZVnAmJLPSBSbssR+v0fTHHA4HNA0Ddq2ZVnuswff97maXRQhlvIEzBEJCRFLCCE5jkT8fpYo/S662yW0qOwgCBgYCcEtlkUBlebYiQTbSCKKE+wiCSEVRKyQZiV0Vp5WA50bGGNQVQbW0vOw2WwYGG5DBIEPrVPkWQYpJaRKoTPNZ23T4PX1Dz+katq2wcvLEYe6ZqCpKliu+8xDJROonUQpVFXFBqRpirrec0xzorlSR8fjEYvFApPJBNPpFL4fYH+CWuQMOUXAnRAM4fLNWxudKAmNgzopaCRK8RsSuU7fGUjVdTMkYBzHXFF3oYPRWtc1u0p7cpliEsXdXQbSf0fAVGuGdZBznSc47+ANuFoxkIz5t/T/VQf8C8zUdmnu/rb0AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Entra ID secret key\"\n        title=\"Entra ID secret key\"\n        src=\"/static/14be5e17618ec00b03b92c1f73678dea/f058b/entra-id-secret-key.png\"\n        srcset=\"/static/14be5e17618ec00b03b92c1f73678dea/c26ae/entra-id-secret-key.png 158w,\n/static/14be5e17618ec00b03b92c1f73678dea/6bdcf/entra-id-secret-key.png 315w,\n/static/14be5e17618ec00b03b92c1f73678dea/f058b/entra-id-secret-key.png 630w,\n/static/14be5e17618ec00b03b92c1f73678dea/40601/entra-id-secret-key.png 945w,\n/static/14be5e17618ec00b03b92c1f73678dea/78612/entra-id-secret-key.png 1260w,\n/static/14be5e17618ec00b03b92c1f73678dea/1df5b/entra-id-secret-key.png 1999w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>Finally, click <code class=\"language-text\">Overview -> endpoints</code> at the top of the page. Copy the OpenID Connect metadata document url for later.</p>\n<h2 id=\"configure-your-application-for-microsoft-entra-id-oauth\" style=\"position:relative;\"><a href=\"#configure-your-application-for-microsoft-entra-id-oauth\" aria-label=\"configure your application for microsoft entra id oauth permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Configure your application for Microsoft Entra ID Oauth</h2>\n<p>If following the supertoken steps, you can scroll to the next section. If you’re doing a custom integration, follow these steps.</p>\n<p>Let’s create our express server and handle the Oauth flow.\nGenerate a new project:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"76124778865892500000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npm init`, `76124778865892500000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> init</code></pre></div>\n<p>Then add the needed dependencies:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"64530829854682080000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npm install --save express express-session axios dotenv cookie-parser`, `64530829854682080000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save express express-session axios dotenv cookie-parser</code></pre></div>\n<p>Create a file named .env in the root of your project and add the following values:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"56057654708647100000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`CLIENT_ID=<YOUR_CLIENT_ID>\nCLIENT_SECRET_VALUE=<YOUR_CLIENT_SECRET_VALUE>\nCOOKIE_SECRET=<SECRET_FOR_COOKIES>\nSECRET=<SECRET_FOR_EXPRESS_SESSION>`, `56057654708647100000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">CLIENT_ID</span><span class=\"token operator\">=</span><span class=\"token operator\">&lt;</span>YOUR_CLIENT_ID<span class=\"token operator\">></span>\n<span class=\"token assign-left variable\">CLIENT_SECRET_VALUE</span><span class=\"token operator\">=</span><span class=\"token operator\">&lt;</span>YOUR_CLIENT_SECRET_VALUE<span class=\"token operator\">></span>\n<span class=\"token assign-left variable\">COOKIE_SECRET</span><span class=\"token operator\">=</span><span class=\"token operator\">&lt;</span>SECRET_FOR_COOKIES<span class=\"token operator\">></span>\n<span class=\"token assign-left variable\">SECRET</span><span class=\"token operator\">=</span><span class=\"token operator\">&lt;</span>SECRET_FOR_EXPRESS_SESSION<span class=\"token operator\">></span></code></pre></div>\n<p>Now we can start making our express app.</p>\n<p>We’ll create an index.js file to write our express server in. After that, we’ll make an auth endpoint that sends the user to Microsoft with our Client ID so Microsoft knows it’s our application starting the process. We’ll also add some code to initialise an express session for after the user has authenticated themselves, generate state to mitigate CSRF attacks, and a configuration object that has the Oauth information needed for Microsoft.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"39331368264399560000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`require('dotenv').config()\n\nconst express = require('express');\nconst session = require('express-session');\nconst axios = require('axios');\nconst qs = require('querystring');\nconst crypto = require('crypto');\nconst cookieParser = require('cookie-parser');\n\n\nconst app = express();\n\n// Configuration settings for Microsoft Entra ID\nconst config = {\n  clientId: process.env.CLIENT_ID,\n  clientSecret: process.env.CLIENT_SECRET_VALUE,\n  redirectUri: &quot;http://localhost:3000/auth/callback&quot;,\n  scope: [&quot;openid&quot;, &quot;email&quot;, &quot;profile&quot;]\n};\n\n// Add session middleware\napp.use(session({\n  secret: process.env.SECRET,\n  resave: false,\n  saveUninitialized: true\n}));\n\napp.use(cookieParser(process.env.COOKIE_SECRET));\n\n// The root path links us to the /auth endpoint, which generates\n// the url to start oauth flow\napp.get('/', (req, res) => {\n  res.send('<a href=&quot;/auth&quot;>Login with Microsoft Entra ID</a>');\n});\n\n// The auth endpoint generates our oauth url for Microsoft Entra ID\napp.get('/auth', (req, res) => {\n\n  require('crypto').randomBytes(24, function(err, buffer) {\n    let stateParam = buffer.toString('hex');\n    res.cookie(&quot;stateParam&quot;, stateParam, { maxAge: 1000 * 60 * 5, signed: true });\n\n    const authUrl = &quot;https://login.microsoftonline.com/common/oauth2/v2.0/authorize?&quot; + qs.stringify({\n      client_id: config.clientId,\n      response_type: 'code',\n      redirect_uri: config.redirectUri,\n      response_mode: 'query',\n      scope: config.scope.join(&quot; &quot;),\n      state: stateParam\n    });\n\n    res.redirect(authUrl);\n  });\n\n  \n});\n\napp.listen(3000, () => {\n  console.log(\\`Server is running on port 3000\\`);\n});`, `39331368264399560000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'dotenv'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">config</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">const</span> express <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'express'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> session <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'express-session'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> axios <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'axios'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> qs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'querystring'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> crypto <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'crypto'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> cookieParser <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'cookie-parser'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\n<span class=\"token keyword\">const</span> app <span class=\"token operator\">=</span> <span class=\"token function\">express</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Configuration settings for Microsoft Entra ID</span>\n<span class=\"token keyword\">const</span> config <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">clientId</span><span class=\"token operator\">:</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">CLIENT_ID</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">clientSecret</span><span class=\"token operator\">:</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">CLIENT_SECRET_VALUE</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">redirectUri</span><span class=\"token operator\">:</span> <span class=\"token string\">\"http://localhost:3000/auth/callback\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">scope</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"openid\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"email\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"profile\"</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Add session middleware</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">session</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">secret</span><span class=\"token operator\">:</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">SECRET</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">resave</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">saveUninitialized</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">cookieParser</span><span class=\"token punctuation\">(</span>process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">COOKIE_SECRET</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// The root path links us to the /auth endpoint, which generates</span>\n<span class=\"token comment\">// the url to start oauth flow</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'&lt;a href=\"/auth\">Login with Microsoft Entra ID&lt;/a>'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// The auth endpoint generates our oauth url for Microsoft Entra ID</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/auth'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'crypto'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">randomBytes</span><span class=\"token punctuation\">(</span><span class=\"token number\">24</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">err<span class=\"token punctuation\">,</span> buffer</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> stateParam <span class=\"token operator\">=</span> buffer<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token string\">'hex'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">cookie</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"stateParam\"</span><span class=\"token punctuation\">,</span> stateParam<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">maxAge</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">signed</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> authUrl <span class=\"token operator\">=</span> <span class=\"token string\">\"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?\"</span> <span class=\"token operator\">+</span> qs<span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">client_id</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>clientId<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">response_type</span><span class=\"token operator\">:</span> <span class=\"token string\">'code'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">redirect_uri</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>redirectUri<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">response_mode</span><span class=\"token operator\">:</span> <span class=\"token string\">'query'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">scope</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>scope<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">state</span><span class=\"token operator\">:</span> stateParam\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">redirect</span><span class=\"token punctuation\">(</span>authUrl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">listen</span><span class=\"token punctuation\">(</span><span class=\"token number\">3000</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Server is running on port 3000</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now let’s build the callback endpoint that Microsoft will send the Authorization Code to after the user has verified themselves. On this endpoint, we’ll trade the Authorization Code for an Access Token and Refresh Token and save it in our express session. This endpoint needs to listen on the same path that we gave Microsoft for our Callback URI. We’ll also tell this endpoint to redirect to a profile endpoint that we’ll define in the next step.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"21794448652239450000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// This is our Redirect URI\n// After the flow has started, Microsoft sends us back\n// an authorization code, authorizing us to get access and refresh tokens\n// on behalf of the user\napp.get('/auth/callback', async (req, res) => {\n  const { code, state } = req.query;\n  const { stateParam } = req.signedCookies;\n\n  if (stateParam !== state) {\n    res.status(422).send(&quot;Invalid State&quot;);\n    return;\n  }\n\n  const tokenUrl = &quot;https://login.microsoftonline.com/common/oauth2/v2.0/token?&quot;;\n\n  const tokenParams = {\n    client_id: config.clientId,\n    scope: config.scope.join(&quot; &quot;),\n    code,\n    redirect_uri: config.redirectUri,\n    grant_type: 'authorization_code',\n    client_secret: config.clientSecret\n  };\n\n  try {\n    const response = await axios.post(tokenUrl, qs.stringify(tokenParams), {\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded'\n      }\n    });\n\n    // save the token data in the user session in express\n    req.session.tokenSet = response.data;\n    res.redirect('/profile');\n  } catch (error) {\n    console.error('Token exchange error:', error);\n    res.redirect('/');\n  }\n});\n`, `21794448652239450000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// This is our Redirect URI</span>\n<span class=\"token comment\">// After the flow has started, Microsoft sends us back</span>\n<span class=\"token comment\">// an authorization code, authorizing us to get access and refresh tokens</span>\n<span class=\"token comment\">// on behalf of the user</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/auth/callback'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> code<span class=\"token punctuation\">,</span> state <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>query<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> stateParam <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>signedCookies<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stateParam <span class=\"token operator\">!==</span> state<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">422</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Invalid State\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> tokenUrl <span class=\"token operator\">=</span> <span class=\"token string\">\"https://login.microsoftonline.com/common/oauth2/v2.0/token?\"</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> tokenParams <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">client_id</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>clientId<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">scope</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>scope<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    code<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">redirect_uri</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>redirectUri<span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">grant_type</span><span class=\"token operator\">:</span> <span class=\"token string\">'authorization_code'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">client_secret</span><span class=\"token operator\">:</span> config<span class=\"token punctuation\">.</span>clientSecret\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> axios<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span>tokenUrl<span class=\"token punctuation\">,</span> qs<span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>tokenParams<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-property property\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/x-www-form-urlencoded'</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// save the token data in the user session in express</span>\n    req<span class=\"token punctuation\">.</span>session<span class=\"token punctuation\">.</span>tokenSet <span class=\"token operator\">=</span> response<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">redirect</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/profile'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Token exchange error:'</span><span class=\"token punctuation\">,</span> error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">redirect</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p>Now we’ll define our profile endpoint and logout endpoint. The Profile endpoint will use the token we received, call to Microsoft for the user’s information, and display it on the screen. And the logout endpoint will destroy the express session.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"4173008810535439000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// grab token data from express session\n// and get user info from microsoft\napp.get('/profile', async (req, res) => {\n  if (!req.session.tokenSet) {\n    return res.redirect('/');\n  }\n\n  const { id_token } = req.session.tokenSet;\n\n  // the main profile information is in the body\n  // of the JWT\n  const body = id_token.split(&quot;.&quot;)[1];\n\n  // convert it from base64 to utf8\n  let bufferObj = Buffer.from(body, &quot;base64&quot;);\n  let string = bufferObj.toString(&quot;utf8&quot;);\n\n  res.send(\\`<h1>Profile</h1><span>\\${string}</span><br><br><a href=&quot;/logout&quot;>logout</a>\\`);\n});\n\napp.get('/logout', (req, res) => {\n  req.session.destroy((err) => {\n    if (err) {\n      console.error(err);\n    }\n    res.redirect('/');\n  });\n});`, `4173008810535439000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// grab token data from express session</span>\n<span class=\"token comment\">// and get user info from microsoft</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/profile'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>req<span class=\"token punctuation\">.</span>session<span class=\"token punctuation\">.</span>tokenSet<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">redirect</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> id_token <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>session<span class=\"token punctuation\">.</span>tokenSet<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// the main profile information is in the body</span>\n  <span class=\"token comment\">// of the JWT</span>\n  <span class=\"token keyword\">const</span> body <span class=\"token operator\">=</span> id_token<span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// convert it from base64 to utf8</span>\n  <span class=\"token keyword\">let</span> bufferObj <span class=\"token operator\">=</span> Buffer<span class=\"token punctuation\">.</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> <span class=\"token string\">\"base64\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> string <span class=\"token operator\">=</span> bufferObj<span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"utf8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">&lt;h1>Profile&lt;/h1>&lt;span></span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>string<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">&lt;/span>&lt;br>&lt;br>&lt;a href=\"/logout\">logout&lt;/a></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/logout'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  req<span class=\"token punctuation\">.</span>session<span class=\"token punctuation\">.</span><span class=\"token function\">destroy</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">err</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">redirect</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now when we run our app, we can log into our Microsoft account and see our account information. Nice! Full Oauth flow finished for Microsoft Entra ID.</p>\n<h2 id=\"configure-supertokens-for-microsoft-entra-id-oauth\" style=\"position:relative;\"><a href=\"#configure-supertokens-for-microsoft-entra-id-oauth\" aria-label=\"configure supertokens for microsoft entra id oauth permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Configure SuperTokens for Microsoft Entra ID Oauth</h2>\n<p>Run to make a new SuperTokens project:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"13732828118744678000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`npx create-supertokens-app@latest --recipe=thirdparty`, `13732828118744678000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">npx create-supertokens-app@latest --recipe<span class=\"token operator\">=</span>thirdparty</code></pre></div>\n<p>We need to configure the front-end to generate a “Login with Entra” button, so add the following to your front-end <code class=\"language-text\">config.tsx</code>.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"57863494644765880000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`ThirdParty.init({\n            signInAndUpFeature: {\n                providers: [\n                    {\n                        // The ID sets your callback url\n                        // ie http://localhost:3000/auth/callback/entra\n                        id: &quot;entra&quot;,\n                        name: &quot;Entra ID&quot;, // Will display &quot;Continue with X&quot;\n\n                        // optional\n                        // you do not need to add a click handler to this as\n                        // we add it for you automatically.\n                        buttonComponent: (props: {name: string}) => <div style={{\n                            cursor: &quot;pointer&quot;,\n                            border: &quot;1&quot;,\n                            paddingTop: &quot;5px&quot;,\n                            paddingBottom: &quot;5px&quot;,\n                            borderRadius: &quot;5px&quot;,\n                            borderStyle: &quot;solid&quot;\n                        }}>{&quot;Login with &quot; + props.name}</div>\n                    }\n                ],\n            },\n        }),\n`, `57863494644765880000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">ThirdParty<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">signInAndUpFeature</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token literal-property property\">providers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n                    <span class=\"token punctuation\">{</span>\n                        <span class=\"token comment\">// The ID sets your callback url</span>\n                        <span class=\"token comment\">// ie http://localhost:3000/auth/callback/entra</span>\n                        <span class=\"token literal-property property\">id</span><span class=\"token operator\">:</span> <span class=\"token string\">\"entra\"</span><span class=\"token punctuation\">,</span>\n                        <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Entra ID\"</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// Will display \"Continue with X\"</span>\n\n                        <span class=\"token comment\">// optional</span>\n                        <span class=\"token comment\">// you do not need to add a click handler to this as</span>\n                        <span class=\"token comment\">// we add it for you automatically.</span>\n                        <span class=\"token function-variable function\">buttonComponent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token literal-property property\">props</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> string<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token operator\">&lt;</span>div style<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span>\n                            <span class=\"token literal-property property\">cursor</span><span class=\"token operator\">:</span> <span class=\"token string\">\"pointer\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">border</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">paddingTop</span><span class=\"token operator\">:</span> <span class=\"token string\">\"5px\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">paddingBottom</span><span class=\"token operator\">:</span> <span class=\"token string\">\"5px\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">borderRadius</span><span class=\"token operator\">:</span> <span class=\"token string\">\"5px\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">borderStyle</span><span class=\"token operator\">:</span> <span class=\"token string\">\"solid\"</span>\n                        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token string\">\"Login with \"</span> <span class=\"token operator\">+</span> props<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n                    <span class=\"token punctuation\">}</span>\n                <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n</code></pre></div>\n<p>Now we need to configure the back-end to handle the OIDC calls. We’ll set our scopes to [“openid”, “email”, “profile”], and our oidcDiscoveryEndpoint to the OpenID Connect metadata document we got in our application overview.</p>\n<p>Add the following to your <code class=\"language-text\">config.ts</code></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"9591313430247594000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`ThirdParty.init({\n            signInAndUpFeature: {\n                providers: [\n                    {\n                        config: {\n\t\t                        // The thirdPartyId connects to the front-end id\n                            thirdPartyId: &quot;entra&quot;,\n                            name: &quot;Entra ID&quot;,\n                            clients: [{\n                                clientId: &quot;<CLIENT_ID>&quot;,\n                                clientSecret: &quot;<CLIENT_SECRET_VALUE>&quot;,\n                                scope: [&quot;openid&quot;, &quot;email&quot;, &quot;profile&quot;]\n                            }],\n                            oidcDiscoveryEndpoint: &quot;https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration&quot;,\n                            userInfoMap: {\n                                fromUserInfoAPI: {\n                                    userId: &quot;sub&quot;,\n                                    email: &quot;email&quot;,\n                                }\n                            }\n                        }\n                    },\n                ],\n            },\n        })\n`, `9591313430247594000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">ThirdParty<span class=\"token punctuation\">.</span><span class=\"token function\">init</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token literal-property property\">signInAndUpFeature</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token literal-property property\">providers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n                    <span class=\"token punctuation\">{</span>\n                        <span class=\"token literal-property property\">config</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n\t\t                        <span class=\"token comment\">// The thirdPartyId connects to the front-end id</span>\n                            <span class=\"token literal-property property\">thirdPartyId</span><span class=\"token operator\">:</span> <span class=\"token string\">\"entra\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Entra ID\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">clients</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span>\n                                <span class=\"token literal-property property\">clientId</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;CLIENT_ID>\"</span><span class=\"token punctuation\">,</span>\n                                <span class=\"token literal-property property\">clientSecret</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;CLIENT_SECRET_VALUE>\"</span><span class=\"token punctuation\">,</span>\n                                <span class=\"token literal-property property\">scope</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"openid\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"email\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"profile\"</span><span class=\"token punctuation\">]</span>\n                            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">oidcDiscoveryEndpoint</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration\"</span><span class=\"token punctuation\">,</span>\n                            <span class=\"token literal-property property\">userInfoMap</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n                                <span class=\"token literal-property property\">fromUserInfoAPI</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n                                    <span class=\"token literal-property property\">userId</span><span class=\"token operator\">:</span> <span class=\"token string\">\"sub\"</span><span class=\"token punctuation\">,</span>\n                                    <span class=\"token literal-property property\">email</span><span class=\"token operator\">:</span> <span class=\"token string\">\"email\"</span><span class=\"token punctuation\">,</span>\n                                <span class=\"token punctuation\">}</span>\n                            <span class=\"token punctuation\">}</span>\n                        <span class=\"token punctuation\">}</span>\n                    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n                <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n</code></pre></div>\n<p>Run <code class=\"language-text\">npm run start</code> and head to <code class=\"language-text\">localhost:3000</code> in the browser. You’ll see the option <code class=\"language-text\">Sign in with Entra</code>. Click it and you’ll get a session signed in from Entra ID. How easy was that?</p>\n<p><img src=\"/static/blog/f77ae84c03a5864cc39ce74e68f0b9f1/entra-id-sso-login-with-supertokens.gif\" alt=\"Entra ID SSO login with SuperTokens\"></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>Active Directory is a time tested way to store users and permissions. Its ability to integrate as an Identity Provider makes it valuable, especially to large organisations that have lots of users and permissions to manage. If you found the usual way of integrating Entra ID to be cumbersome, then try <a href=\"https://supertokens.com/features/social-login\" target=\"_blank\" rel=\"nofollow\">simplifying your SSO logins with SuperTokens</a>.</p>\n<p><a href=\"https://github.com/ConzorKingKong/entra-id-oidc-express\" target=\"_blank\" rel=\"nofollow\">Github repo for express instance</a></p>\n<p><a href=\"https://github.com/ConzorKingKong/supertokens-entra-id\" target=\"_blank\" rel=\"nofollow\">Github repo for SuperTokens project</a></p>","frontmatter":{"date":"January 07, 2025","title":"How to implement OIDC with Microsoft Entra ID","cover":"entra-id.png","author":"Connor Peshek","description":"Implementing OIDC with Microsoft Entra ID can be confusing. We're gonna help you implement it two different ways — in your own ExpressJS server or in SuperTokens."},"fields":{"slug":"/how-to-implement-oidc-with-microsoft-entra-id/"}},"site":{"siteMetadata":{"title":"SuperTokens Blog"}}},"pageContext":{"id":"c2a7768c-4077-5816-9c4b-5fe393bec295","fields__slug":"/how-to-implement-oidc-with-microsoft-entra-id/","__params":{"fields__slug":"how-to-implement-oidc-with-microsoft-entra-id"}}},
    "staticQueryHashes": []}