<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Sveltekit - Tag - Rick Roché</title><link>https://www.rickroche.com/tags/sveltekit/</link><description>Sveltekit - Tag - Rick Roché</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright><lastBuildDate>Tue, 01 Mar 2022 12:00:00 +0200</lastBuildDate><atom:link href="https://www.rickroche.com/tags/sveltekit/" rel="self" type="application/rss+xml"/><item><title>Single Sign-On, Azure Static Web Apps and Azure Active Directory</title><link>https://www.rickroche.com/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/</link><pubDate>Tue, 01 Mar 2022 12:00:00 +0200</pubDate><author>
Richard Roché</author><guid>https://www.rickroche.com/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/</guid><description><![CDATA[<div class="featured-image">
                <img src="https://www.rickroche.com/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/azure-static-web-apps-sso-cover.png" referrerpolicy="no-referrer">
            </div><p>We often build and deploy web applications specifically for users internal to our organisation. <a href="https://azure.microsoft.com/en-us/services/app-service/static/" target="_blank" rel="noopener noreffer">Azure Static Web Apps</a>
 is proving to be an excellent replacement for <a href="https://azure.microsoft.com/en-us/services/app-service/" target="_blank" rel="noopener noreffer">Azure App Service</a>
 in these scenarios.</p>
<p>At a high-level the service provides you with a great set of features (outlined in the <a href="https://azure.microsoft.com/en-us/updates/azure-static-web-apps-is-now-generally-available/" target="_blank" rel="noopener noreffer">Azure release notes</a>
)</p>
<blockquote>
<ul>
<li>Globally distributed content for production apps</li>
<li>Tailored CI/CD workflows from code to cloud</li>
<li>Auto-provisioned preview environments</li>
<li>Custom domain configuration and free SSL certificates</li>
<li>Built-in access to a variety of authentication providers</li>
<li>Route-based authorization</li>
<li>Custom routing</li>
<li>Integration with serverless APIs powered by Azure Functions</li>
<li>A custom Visual Studio Code developer extension</li>
<li>A feature-rich CLI for local development</li>
</ul>
</blockquote>
<h2 id="the-desired-experience">The desired experience?</h2>
<p>The experience I wanted to achieve was that if one of our internal users browsed to any of our internal apps, they would be able to use SSO across them provided they were a member of the AAD group needed to access the app (or just a member of our tenant for organisation-wide apps) - no login button, just a seamless logged-in user experience.</p>
<p>It turns out this was super easy to get right! Follow below!</p>
<h2 id="authentication-options">Authentication options</h2>
<p>Azure Static Web Apps makes authentication easy to enable across the three <a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization?tabs=invitations" target="_blank" rel="noopener noreffer">pre-configured identity providers</a>
</p>
<ul>
<li>Azure Active Directory (AAD)</li>
<li>Github or</li>
<li>Twitter</li>
</ul>
<p>These options allow users to login using a login button linking to the desired provider.</p>
<p>Initially I tried to use the pre-configured AAD provider, and when trying to log in using my company account I was presented with this approval dialogue</p>
<a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-swa-admin-approval.png" title="Azure Static Web Apps Admin Approval" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-swa-admin-approval.png">
        
    </a>
<p>Meaning if I was able to get an admin to grant the permission, all users from our tenant would be able to log in to all Azure Static Web Apps, regardless of who had deployed them making this a non-starter for me.</p>
<p>Fortunately we already deploy our static web apps using the Standard plan for <a href="https://azure.microsoft.com/en-us/pricing/details/app-service/static/" target="_blank" rel="noopener noreffer">$9/per app/month</a>
, giving us the ability to use <a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-custom?tabs=aad" target="_blank" rel="noopener noreffer">custom authentication</a>
 and use SSO with our organisations AAD tenant, internal app registrations and restrict access to groups / users in our tenants directory.</p>
<h2 id="getting-it-done">Getting it done!</h2>
<a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/c4-container.png" title="C4 Container Diagram" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/c4-container.png">
        
    </a>
<p>To achieve the desired experience there are a number of components required</p>
<ul>
<li>the static web app (the website)</li>
<li>an Azure App Registration for your app in your tenant</li>
<li>an Azure resource group for your project (I&rsquo;m working on the assumption you already have a subscription, if not <a href="https://docs.microsoft.com/en-us/azure/cost-management-billing/manage/create-subscription" target="_blank" rel="noopener noreffer">read here</a>
)
<ul>
<li>an Azure Static Web App for the web app</li>
<li>an Azure Key Vault to safely store the secrets for your app</li>
</ul>
</li>
</ul>
<p>I will be showing you how to create, configure and deploy these using <a href="https://docs.github.com/en/actions" target="_blank" rel="noopener noreffer">GitHub Actions</a>
, <a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep" target="_blank" rel="noopener noreffer">Bicep</a>
 (for creating the Azure resources) and some once off scripts.</p>
<div class="details admonition info open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-info-circle fa-fw" aria-hidden="true"></i>Info<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">All code is available on GitHub <a href="https://github.com/rick-roche/azure-static-web-apps-sso" target="_blank" rel="noopener noreffer">over here</a></div>
        </div>
    </div>
<div class="details admonition note open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-pencil-alt fa-fw" aria-hidden="true"></i>Note<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">It is a good idea to wire up your Key Vault to a Log Analytics workspace or similar to track audit events when in production.</div>
        </div>
    </div>
<h2 id="initial-setup-and-deployment">Initial setup and deployment</h2>
<p>First we are going to scaffold our web app, define our infrastructure and deploy to Azure without any auth in place. Once done, we will move onto the configuration of the app with auth.</p>
<h3 id="scaffold-the-web-app">Scaffold the web app</h3>
<p>For the purposes of this post, I needed a simple static web app and used the <a href="https://kit.svelte.dev/" target="_blank" rel="noopener noreffer">SvelteKit</a>
 skeleton project with the <a href="https://github.com/sveltejs/kit/tree/master/packages/adapter-static" target="_blank" rel="noopener noreffer">static adapter</a>
.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">npm init svelte@next webapp
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> webapp
</span></span><span class="line"><span class="cl">npm install --save-dev @sveltejs/adapter-static@next
</span></span></code></pre></td></tr></table>
</div>
</div><p>You need to update the default <code>svelte.config.js</code> to <a href="https://github.com/sveltejs/kit/tree/master/packages/adapter-static#usage" target="_blank" rel="noopener noreffer">use the static adapter</a>
, see an example <a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/webapp/svelte.config.js" target="_blank" rel="noopener noreffer">here</a>
.</p>
<h3 id="define-the-azure-infrastructure">Define the Azure Infrastructure</h3>
<h4 id="resource-group">Resource Group</h4>
<p>First, create an Azure resource group. For this tutorial I&rsquo;m creating it manually from my terminal and <a href="https://docs.microsoft.com/en-us/cli/azure/" target="_blank" rel="noopener noreffer">Azure CLI</a>
</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">az group create -g rg-swa-sso -l northeurope
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="resources">Resources</h4>
<p>We will be deploying a Static Web App as well as a Key Vault using Bicep. I&rsquo;ve split out the Bicep files to make them easier to work with as follows (filenames link to the code on GitHub)</p>
<ul>
<li><a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/infra/main.bicep" target="_blank" rel="noopener noreffer"><code>main.bicep</code></a>
 - the main template that is deployed which makes use of the other templates</li>
<li><a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/infra/get-kv-secrets-refs.bicep" target="_blank" rel="noopener noreffer"><code>get-kv-secrets-refs.bicep</code></a>
 - a helper to build up the Key Vault secret references</li>
<li><a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/infra/key-vault.bicep" target="_blank" rel="noopener noreffer"><code>key-vault.bicep</code></a>
 - defines the Key Vault resources and the role assignments needed</li>
<li><a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/infra/static-sites.bicep" target="_blank" rel="noopener noreffer"><code>static-sites.bicep</code></a>
 - defines the Static Web App resources needed</li>
</ul>
<p>In the <a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/infra/main.bicep" target="_blank" rel="noopener noreffer"><code>main.bicep</code></a>
 there are the following highlights to make note of</p>
<ul>
<li>Configuring the static web app
<ul>
<li>to have app settings that are Key Vault references (<code>AAD_CLIENT_ID</code>, <code>AAD_CLIENT_SECRET</code>)</li>
<li>to use the <code>Standard</code> sku</li>
</ul>
</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bicep" data-lang="bicep"><span class="line"><span class="cl"><span class="kd">module</span><span class="w"> </span><span class="nv">swa</span><span class="w"> </span><span class="s">&#39;static-sites.bicep&#39;</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nv">name</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;deploy-swa-</span><span class="si">${</span><span class="nv">appName</span><span class="si">}</span><span class="s">&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nv">params</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nv">appSettings</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nv">AAD_CLIENT_ID</span><span class="p">:</span><span class="w"> </span><span class="nv">refs</span><span class="p">.</span><span class="nv">outputs</span><span class="p">.</span><span class="nv">aadClientIdRef</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nv">AAD_CLIENT_SECRET</span><span class="p">:</span><span class="w"> </span><span class="nv">refs</span><span class="p">.</span><span class="nv">outputs</span><span class="p">.</span><span class="nv">aadClientSecretRef</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nv">sku</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nv">name</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;Standard&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nv">tier</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;Standard&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>And configuring the key vault to allow the static web app permissions to read from it</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bicep" data-lang="bicep"><span class="line"><span class="cl"><span class="c1">// https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli#azure-built-in-roles-for-key-vault-data-plane-operations</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">var</span><span class="w"> </span><span class="nv">keyVaultSecretsUserRole</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">&#39;4633458b-17de-408a-b874-0445c86b69e6&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">module</span><span class="w"> </span><span class="nv">kv</span><span class="w"> </span><span class="s">&#39;key-vault.bicep&#39;</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nv">name</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;deploy-kv-</span><span class="si">${</span><span class="nv">appName</span><span class="si">}</span><span class="s">&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nv">params</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nv">roleAssignments</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nv">roleDefinitionId</span><span class="p">:</span><span class="w"> </span><span class="nv">keyVaultSecretsUserRole</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nv">principalType</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;ServicePrincipal&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nv">principalId</span><span class="p">:</span><span class="w"> </span><span class="nv">swa</span><span class="p">.</span><span class="nv">outputs</span><span class="p">.</span><span class="nv">siteSystemAssignedIdentityId</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="deploy-using-github">Deploy using GitHub</h3>
<h4 id="deployment-credentials">Deployment credentials</h4>
<p>For a GitHub Action to be able to deploy to your resource group you need to have some form of deployment credentials. You can read about the options available <a href="https://docs.microsoft.com/en-us/azure/app-service/deploy-github-actions?tabs=userlevel" target="_blank" rel="noopener noreffer">here</a>
. I&rsquo;ll be using the <a href="https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli" target="_blank" rel="noopener noreffer">Service Principal</a>
 approach with <a href="https://docs.microsoft.com/en-us/cli/azure/" target="_blank" rel="noopener noreffer">Azure CLI</a>
.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">az ad sp create-for-rbac --name <span class="s2">&#34;sp-swa-sso&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --role Owner <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --scopes /subscriptions/<span class="o">{</span>subscription-id<span class="o">}</span>/resourceGroups/<span class="o">{</span>resource-group-name<span class="o">}</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --sdk-auth
</span></span></code></pre></td></tr></table>
</div>
</div><p>You will get a JSON output from this that you can then save as a GitHub secret with the name <code>AZURE_CREDENTIALS</code>.</p>
<div class="details admonition note open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-pencil-alt fa-fw" aria-hidden="true"></i>Note<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content"><ul>
<li>Replace <code>{subscription-id}</code> with the ID of your subscription</li>
<li>Replace <code>{resource-group-name}</code> with the name of your resource group</li>
<li>I&rsquo;ve made the service principal have Owner access to the resource group (so that I can assign roles).</li>
</ul>
</div>
        </div>
    </div>
<h4 id="workflow-token">Workflow token</h4>
<p>Azure Static Web Apps needs access to your workflow when deploying. For this we&rsquo;ll set up a <code>WORKFLOW_TOKEN</code> secret using a GitHub personal access token with the workflow scope. Follow <a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token" target="_blank" rel="noopener noreffer">the instructions here</a>
 to create the token.</p>
<h4 id="github-action-workflow">Github Action Workflow</h4>
<p>With the above secrets in place, we can now create a workflow (mines in <a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/6c95cffac91b8d04aefda1921683e03fda5f51bf/.github/workflows/deploy.yaml" target="_blank" rel="noopener noreffer"><code>.github/workflows/deploy.yaml</code></a>
) which</p>
<ul>
<li>specifies some environment variables for names, tags and locations</li>
<li>checks out the repo</li>
<li>logs into Azure using <code>${{ secrets.AZURE_CREDENTIALS }}</code></li>
<li>deploys to the resource group using the <a href="https://github.com/marketplace/actions/azure-cli-action" target="_blank" rel="noopener noreffer"><code>azure/CLI@v1</code> action</a>
</li>
<li>gets the API from the deployed static web app (so that we can deploy code to it)</li>
<li>deploys the webapp using the <a href="https://github.com/Azure/static-web-apps-deploy" target="_blank" rel="noopener noreffer"><code>Azure/static-web-apps-deploy@v1</code> action</a>
</li>
</ul>
<p>See the full workflow below.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Deploy Infra and App</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">push</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">branches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pull_request</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">types</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">opened, synchronize, reopened, closed]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">branches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">env</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">RESOURCE_GROUP</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;rg-swa-sso&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">RESOURCE_TAGS</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;{&#34;owner&#34;:&#34;rick.roche&#34;, &#34;app&#34;:&#34;azure-swa-sso&#34;, &#34;repo&#34;:&#34;https://github.com/rick-roche/azure-static-web-apps-sso&#34; }&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">APP_NAME</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;swa-sso&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">LOCATION</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;westeurope&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">deploy-infra</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-latest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Checkout Repository</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/setup-node@v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">node-version</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;16&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Azure Login</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">azure/login@v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">creds</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.AZURE_CREDENTIALS }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Deploy Infra</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">deploy_infra</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">github.event_name != &#39;pull_request&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">azure/CLI@v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">inlineScript</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            az deployment group create \
</span></span></span><span class="line"><span class="cl"><span class="sd">              --resource-group ${{ env.RESOURCE_GROUP }} \
</span></span></span><span class="line"><span class="cl"><span class="sd">              --template-file ./infra/main.bicep \
</span></span></span><span class="line"><span class="cl"><span class="sd">              --parameters \
</span></span></span><span class="line"><span class="cl"><span class="sd">                  appName=&#39;${{ env.APP_NAME }}&#39; \
</span></span></span><span class="line"><span class="cl"><span class="sd">                  location=&#39;${{ env.LOCATION }}&#39; \
</span></span></span><span class="line"><span class="cl"><span class="sd">                  repositoryUrl=&#39;https://github.com/rick-roche/azure-static-web-apps-sso&#39; \
</span></span></span><span class="line"><span class="cl"><span class="sd">                  repositoryToken=&#39;${{ secrets.WORKFLOW_TOKEN }}&#39; \
</span></span></span><span class="line"><span class="cl"><span class="sd">                  tags=&#39;${{ env.RESOURCE_TAGS }}&#39;</span><span class="w">            
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Get Static Web App API Key</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">static_web_app_apikey</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">github.event_name != &#39;pull_request&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">azure/CLI@v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">inlineScript</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            APIKEY=$(az staticwebapp secrets list --name &#39;stapp-${{ env.APP_NAME }}&#39; | jq -r &#39;.properties.apiKey&#39;)
</span></span></span><span class="line"><span class="cl"><span class="sd">            echo &#34;::set-output name=APIKEY::$APIKEY&#34;</span><span class="w">            
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Deploy WebApp to Static Web App</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">static_web_app_deploy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">github.event_name != &#39;pull_request&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">Azure/static-web-apps-deploy@v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">azure_static_web_apps_api_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ steps.static_web_app_apikey.outputs.APIKEY }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">repo_token</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GITHUB_TOKEN }}</span><span class="w"> </span><span class="c"># Used for GitHub integrations (i.e. PR comments)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;upload&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="c"># Build configuration for Azure Static Web Apps: https://aka.ms/swaworkflowconfig</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">app_location</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;webapp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">api_location</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">output_location</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;build&#34;</span><span class="w"> </span><span class="c"># relative to app_location</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="finalising-auth">Finalising auth</h2>
<p>At this stage you should have a GitHub workflow successfully deploying a Static Web App and a Key Vault to you resource group. You should also be able to browse to your web app using the generated URL (navigate into the Static Web App from the portal, and you will see your URL on the overview tab. e.g. <a href="https://gray-wave-03fb32a03.1.azurestaticapps.net" target="_blank" rel="noopener noreffer">https://gray-wave-03fb32a03.1.azurestaticapps.net</a>
).</p>
<figure class="image-center"><a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-azure-swa-overview.png" title="Static Web App Overview" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-azure-swa-overview.png" data-sub-html="<h2>Static Web App Overview</h2><p>Static Web App Overview</p>">
        
    </a><figcaption class="image-caption">Static Web App Overview</figcaption>
    </figure>
<div class="details admonition note open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-pencil-alt fa-fw" aria-hidden="true"></i>Note<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">Your app won&rsquo;t ask you to authenticate just yet!</div>
        </div>
    </div>
<p>To enable auth our next steps will be to</p>
<ul>
<li>create an AAD app registration</li>
<li>add it&rsquo;s client ID and secret as secrets in your key vault</li>
<li>configure the static web app to auto log you in if you aren&rsquo;t already or your token has expired</li>
</ul>
<h3 id="aad-app-registration">AAD App Registration</h3>
<p>An AAD app registration allows us to bind our application to a desired set of authentication flows and restrictions. Think of it as giving your application an identity inside AAD. <a href="https://www.re-mark-able.net/understanding-azure-active-directory-application-registrations/" target="_blank" rel="noopener noreffer">Mark Foppen wrote a lovely article</a>
 that may help demystify this a bit.</p>
<p>In this tutorial I&rsquo;ll just be using <a href="https://docs.microsoft.com/en-us/cli/azure/" target="_blank" rel="noopener noreffer">Azure CLI</a>
 to create one:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">az ad app create --display-name aadapp-swa-sso <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --available-to-other-tenants <span class="nb">false</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --identifier-uris api://stapp-swa-sso <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --reply-urls <span class="s1">&#39;https://gray-wave-03fb32a03.1.azurestaticapps.net/.auth/login/aad/callback&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    --native-app <span class="nb">false</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="details admonition note open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-pencil-alt fa-fw" aria-hidden="true"></i>Note<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">Ensure you set the <code>--reply-urls</code> to be the generated URL of your app with the <code>/.auth/login/aad/callback</code> suffix. This allows AAD to call your app once the auth flow has completed.</div>
        </div>
    </div>
<p>Once created, we need to create an application secret for the application. For this tutorial you can do this via the portal following the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret" target="_blank" rel="noopener noreffer">instructions here</a>
.</p>
<p>Copy the value of the secret as well as the <code>Application (client) ID</code> of the AAD app (found under the Overview section of the app).</p>
<h3 id="setup-key-vault-secrets">Setup Key Vault Secrets</h3>
<p>Once again, I&rsquo;ve used the portal for this tutorial. You can follow the <a href="https://docs.microsoft.com/en-us/azure/key-vault/secrets/quick-create-portal#add-a-secret-to-key-vault" target="_blank" rel="noopener noreffer">guide here</a>
 setting two secrets in your vault</p>
<ul>
<li><code>aadClientId</code> - this should be set to the Application (client) ID of your app registration</li>
<li><code>aadClientSecret</code> - this should be set to the value of the application secret created above</li>
</ul>
<h3 id="configuring-the-static-web-app">Configuring the Static Web App</h3>
<p>Configuration for Azure Static Web Apps is defined in the <a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration" target="_blank" rel="noopener noreffer"><code>staticwebapp.config.json</code></a>
 file, which controls, among other things, authentication and authorisation.</p>
<p>I&rsquo;ve put mine in the <a href="https://github.com/rick-roche/azure-static-web-apps-sso/blob/main/webapp/staticwebapp.config.json" target="_blank" rel="noopener noreffer">root of the webapp folder</a>
 and set it to do the following to enable the auto-login SSO magic</p>
<ul>
<li>
<p>enable custom <code>auth</code> with <a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-custom?tabs=aad#azure-active-directory-version-2" target="_blank" rel="noopener noreffer">Azure Active Directory Version 2</a>
 using the app settings references from earlier (<code>AAD_CLIENT_ID</code>, <code>AAD_CLIENT_SECRET</code>)</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;auth&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;identityProviders&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;azureActiveDirectory&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;registration&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;openIdIssuer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://login.microsoftonline.com/4af290c8-08df-440d-93db-cbac02bd9b19/v2.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;clientIdSettingName&#34;</span><span class="p">:</span> <span class="s2">&#34;AAD_CLIENT_ID&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;clientSecretSettingName&#34;</span><span class="p">:</span> <span class="s2">&#34;AAD_CLIENT_SECRET&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>a <a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration#fallback-routes" target="_blank" rel="noopener noreffer"><code>navigationFallback</code> route</a>
 to <code>index.html</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;navigationFallback&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;rewrite&#34;</span><span class="p">:</span> <span class="s2">&#34;index.html&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>specific rules for the apps <code>routes</code></p>
<ul>
<li>
<p>creates a <code>/login</code> route redirecting to AAD allowing anonymous access</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;route&#34;</span><span class="p">:</span> <span class="s2">&#34;/login&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;rewrite&#34;</span><span class="p">:</span> <span class="s2">&#34;/.auth/login/aad&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;allowedRoles&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;anonymous&#34;</span><span class="p">,</span> <span class="s2">&#34;authenticated&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization?tabs=invitations#block-an-authentication-provider" target="_blank" rel="noopener noreffer">blocks all providers except AAD</a>
</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;route&#34;</span><span class="p">:</span> <span class="s2">&#34;/.auth/login/github&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;statusCode&#34;</span><span class="p">:</span> <span class="mi">404</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;route&#34;</span><span class="p">:</span> <span class="s2">&#34;/.auth/login/twitter&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;statusCode&#34;</span><span class="p">:</span> <span class="mi">404</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>creates a <code>/logout</code> route redirecting to AAD allowing anonymous access</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;route&#34;</span><span class="p">:</span> <span class="s2">&#34;/logout&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;redirect&#34;</span><span class="p">:</span> <span class="s2">&#34;/.auth/logout&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;allowedRoles&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;anonymous&#34;</span><span class="p">,</span> <span class="s2">&#34;authenticated&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span><span class="err">,</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>enforces auth for all other routes (<code>/*</code>)</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;route&#34;</span><span class="p">:</span> <span class="s2">&#34;/*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;allowedRoles&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;authenticated&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
</li>
<li>
<p>sets up a response override that if an unauthenticated user hits a page, they should be redirected to the <code>/login</code> route</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">&#34;responseOverrides&#34;</span><span class="err">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;401&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;redirect&#34;</span><span class="p">:</span> <span class="s2">&#34;/login&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;statusCode&#34;</span><span class="p">:</span> <span class="mi">302</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<p>The combination of all of the above means that anyone accessing the site that isn&rsquo;t logged in will be routed to the <code>/login</code> route which will ensure that the AAD auth flow is completed!</p>
<h2 id="finishing-up">Finishing up!</h2>
<p>Commit all your outstanding changes, push to GitHub and watch your action deploy&hellip; once done, access your web app in the browser, and it should redirect you to login</p>
<a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-login.png" title="Azure AD Login" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-login.png">
        
    </a>
<p>Initially you will need to provide admin consent for your AD app registration to read the logged-in user details</p>
<a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-consent.png" title="Azure AD User Consent" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-aad-consent.png">
        
    </a>
<p>If all has gone well you should see the default page after login completes</p>
<a class="lightgallery" href="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-welcome.png" title="Welcome Page" data-thumbnail="/2022/03/single-sign-on-azure-static-web-apps-and-azure-active-directory/screenshot-welcome.png">
        
    </a>
<p>And that&rsquo;s it! Hope you enjoyed this tutorial and that it helps you setup SSO for your Static Web Apps!</p>
<div class="details admonition info open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-info-circle fa-fw" aria-hidden="true"></i>Info<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">A reminder that all code is available on GitHub <a href="https://github.com/rick-roche/azure-static-web-apps-sso" target="_blank" rel="noopener noreffer">over here</a></div>
        </div>
    </div>
<p>Featured image background by <a href="https://unsplash.com/@helloimnik?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" title="Hello I&#39;m Nik" target="_blank" rel="noopener noreffer">Hello I&rsquo;m Nik</a>
 on <a href="https://unsplash.com/s/photos/sign-in?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" target="_blank" rel="noopener noreffer">Unsplash</a>
</p>
]]></description></item></channel></rss>