<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Augustine Correa</title>
    <description>The latest articles on DEV Community by Augustine Correa (@indcoder).</description>
    <link>https://dev.to/indcoder</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F18992%2F889a3500-a10e-4bb1-875d-df4bc30ec1c7.jpeg</url>
      <title>DEV Community: Augustine Correa</title>
      <link>https://dev.to/indcoder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/indcoder"/>
    <language>en</language>
    <item>
      <title>Securing an Azure Static Web App with Auth0 Actions </title>
      <dc:creator>Augustine Correa</dc:creator>
      <pubDate>Mon, 20 Dec 2021 11:20:39 +0000</pubDate>
      <link>https://dev.to/indcoder/securing-an-azure-static-web-app-with-auth0-actions-1om2</link>
      <guid>https://dev.to/indcoder/securing-an-azure-static-web-app-with-auth0-actions-1om2</guid>
      <description>&lt;p&gt;For our 1st code commit, we will initialize a default Blazor WASM application on our local workstation, deploy it on to &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/front-end-frameworks/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;Azure Static Web Apps&lt;/a&gt;, and then secure it with RBAC to verify the IAM is working as intended on the frontend. As the reading time foretells, this is an in-depth and step-by-step code walkthrough of deploying a production-ready app. Buckle up!!!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Most of the work was done over the release candidate versions, &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-6-release-candidate-1/" rel="noopener noreferrer"&gt;RC1&lt;/a&gt; &amp;amp; &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-6-release-candidate-2/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;RC2&lt;/a&gt;, but I have revalidated the codebase against the &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-6/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;LTS version of .net 6&lt;/a&gt; released yesterday [11th Nov'21].&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canonical reference is on the organization blog: &lt;a href="https://www.hackmum.in/blog/azureswa_blazor_auth0_iam" rel="noopener noreferrer"&gt;https://www.hackmum.in/blog/azureswa_blazor_auth0_iam&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also available in a shortened form as a Twitter thread: &lt;iframe class="tweet-embed" id="tweet-1471151877840465920-681" src="https://platform.twitter.com/embed/Tweet.html?id=1471151877840465920"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1471151877840465920-681');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1471151877840465920&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Development
&lt;/h2&gt;

&lt;p&gt;In the past, for services similar to Azure SWA, developers had to follow a circuitous path of building the code on their local machine, followed by deploying it onto the cloud, and only then would they have been able to verify if their code performed as intended — especially true when the feature was infrastructure-dependent, like Identity and Access Management (IAM).&lt;/p&gt;

&lt;h3&gt;
  
  
  Azure SWA CLI
&lt;/h3&gt;

&lt;p&gt;Azure SWA addresses the above pain point by providing a command-line tool that approximates the cloud environment: &lt;a href="https://techcommunity.microsoft.com/t5/apps-on-azure/introducing-the-azure-static-web-apps-cli/ba-p/2257581/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;SWA CLI&lt;/a&gt;, and we will be relying on its core features to emulate authentication, custom routing, and route authorization.&lt;/p&gt;

&lt;p&gt;Install the SWA CLI globally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;azure&lt;/span&gt;&lt;span class="sr"&gt;/static-web-apps-cl&lt;/span&gt;&lt;span class="err"&gt;i
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since our Blazor WASM application will primarily address the organizer use cases, we will name it accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new blazorwasm -o OrganizerWeb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure you are in the main git branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq0frfl13vjtxckko2tp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq0frfl13vjtxckko2tp.png" alt="dotnet new command creating a Blazor WASM project with the terminal logs showing the output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Immediately, you are confronted by the bane of modern software development: the spawning of way too many files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh16z9bh2v5ns2mo8l1f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh16z9bh2v5ns2mo8l1f5.png" alt="dotnet new creating too many files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a .gitignore to ensure the unnecessary files are not inadvertently checked-in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please don't forget to check-in the .gitignore file, though🤷‍♂️.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqeszq6voqmamwc8nk5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqeszq6voqmamwc8nk5y.png" alt="Cheeky Git commit message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While creating the Blazor WASM project, .net will generate settings of application URLs with random ports. It's a matter of preference, but I like to standardize the port numbers [which will help us later when using the SWA CLI].&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37g5iggd6alj90sddxry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37g5iggd6alj90sddxry.png" alt="launch settings ports"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's kick the tires to ensure things are in working order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also get to see in action one of the most touted features of .net 6: &lt;a href="https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;hot reload&lt;/a&gt;, which also generated a lot of &lt;a href="https://devblogs.microsoft.com/dotnet/net-hot-reload-support-via-cli/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;heat&lt;/a&gt;🔥 recently&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgaggmrmluj1chyny1o1q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgaggmrmluj1chyny1o1q.png" alt="Running .net watch command for hot reload"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9esxtglgz7gkc6kerge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9esxtglgz7gkc6kerge.png" alt="Running .net watch  the weather forecast page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up, we want the Azure SWA CLI to serve the Blazor WASM application. I prefer to execute the SWA commands at the solution level because it provides a vantage position for when we want to repeat this later when including the Azure Functions project(s).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;swa&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:5000 --run "cd OrganizerWeb &amp;amp;&amp;amp; dotnet watch run"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voilà, the Blazor WASM served from the SWA CLI!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnwlcjsk25gsdjfu78y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnwlcjsk25gsdjfu78y9.png" alt="Azure SWA CLI terminal logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A page automatically opens in your browser, but that is powered by the .net watch command[please close this tab/browser; lest it will confuse you during development]. Note the URL with the port number 4280 and traverse to that location; this is the Azure SWA CLI rendered page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flal35zxwzlc99zom5sl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flal35zxwzlc99zom5sl8.png" alt="Default weather app served with Azure SWA CLI port number highlighted in the location bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL
&lt;/h3&gt;

&lt;p&gt;Production web apps are served over HTTPS. Moreover, the default security posture adopted by browsers is to only open SSL-secured sites. Case in point, when I ran the watch run command above, .net opened the browser in https[port 7001] without a hitch. But traversing to the SWA CLI rendered page, which is being served over the ol' plain HTTP, the browser promptly disallowed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav90a6dw7bfxy7bcu80v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fav90a6dw7bfxy7bcu80v.png" alt="Browser page displayed with the message of insecure connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using SSL right from the get-go ensures we catch any potential bugs related to it early. Unfortunately, &lt;a href="https://github.com/azure/static-web-apps-cli" rel="noopener noreferrer"&gt;SWA CLI repository's README&lt;/a&gt; skimps on the details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One CLI SSL option errored out.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lv14h1thbsfhsp0ztz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lv14h1thbsfhsp0ztz3.png" alt="SWA CLI SSL option fail"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Providing only the SSL option to the CLI ain't cutting it.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzj7sfe2u0wsrdptc4lm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzj7sfe2u0wsrdptc4lm.png" alt="SWA CLI option SSL fails with a message to provide key and cert"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What worked? A certificate and key generated by a Root Certificate Authority, trusted by the browser. I recommend &lt;a href="https://web.dev/how-to-use-local-https/#running-your-site-locally-with-https:-other-options" rel="noopener noreferrer"&gt;mkcert&lt;/a&gt; for its ease of accomplishing this. Please ensure that the generated certificate, and key, are kept in a secure location. These should NOT be &lt;strong&gt;checked-in&lt;/strong&gt; if generated within the repository folder; if you do so, amend the .gitignore file to exclude the key and certificate files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;swa&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ssl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../localhost.pem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../localhost-key.pem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:7001 --run "cd OrganizerWeb &amp;amp;&amp;amp; dotnet watch run"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm in the terminal logs, note the HTTPS protocol of the SWA CLI rendered URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06f8593g60nj38pvzai5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06f8593g60nj38pvzai5.jpg" alt="SWA CLI terminal logs with hot reload, and SSL-enabled URL highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traversing to the URL 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0u0bswqbpouxryf4gvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0u0bswqbpouxryf4gvs.png" alt="SWA rendered page with SSL lock icon clicked in the browser's location bar, revealing secure connection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure SWA VS Code Extension
&lt;/h2&gt;

&lt;p&gt;Now it is time to lob our app into the cloud. And we can do it right from the comforts of VS code itself, courtesy of the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;Azure SWA extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ensure you have checked in all your code and have pushed them up to GitHub.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assuming you have validated both your Azure &amp;amp; GitHub profile by the Azure SWA extension:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When clicking on the "plus" icon [circled in red below] of the extension, you will be prompted to select the Azure subscription, followed by a dialog box for entering the name of the Azure Static Web App project.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztwbgpd8f263bn5nu7kt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztwbgpd8f263bn5nu7kt.png" alt="Azure SWA extension with the plus icon circled in red"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will be asked for the Azure Region you wish to deploy the app. Right now, East Asia will be the nearest for the alpha users of the app.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv72hvwnm60s2d2ecy2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv72hvwnm60s2d2ecy2m.png" alt="Azure SWA extension dialogue box with a dropdown displaying Azure regions"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your frontend framework: choosing Blazor for this project.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvub1177cp835itqi7s4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvub1177cp835itqi7s4y.png" alt="Azure SWA extension dialogue box with a dropdown displaying different frontend frameworks"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, you will be asked for the source folder for your frontend project.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqy186fchecnf1u6amdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqy186fchecnf1u6amdx.png" alt="Azure SWA extension dialogue box with a textbox filled with the source folder location"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the build location for your frontend project.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgotv2p3z5u3n8680eao1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgotv2p3z5u3n8680eao1.png" alt="Azure SWA extension dialogue box with a textbox filled with the build location"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If everything goes to plan, a VS Code toast notification about the successful completion of the GitHub actions will pop up. And within the Azure SWA extension, and tucked under the subscription it was created in, the Azure SWA project should be listed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxgjn24qds4rce7z1y6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxgjn24qds4rce7z1y6n.png" alt="Azure SWA extension with Azure SWA listed under the subscription it was created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By right-clicking on the Azure SWA project, you will be presented with a context menu with one of the menu item called "Browse site". Clicking on it, you can traverse to your Azure SWA hosted page.&lt;/p&gt;

&lt;p&gt;🎉🎉🎉 Congratulations! You have successfully deployed your Blazor WASM app to Azure Static Web Apps. 🎉🎉🎉&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrie52asd9nm6mqxdtvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrie52asd9nm6mqxdtvz.png" alt="Azure SWA context menu"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Things that tripped me
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;For folks from a TDD/BDD background who would usually begin by creating an Azure SWA project first and then proceed to code, unfortunately, the extension does not work on an empty folder.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5r52j1auto0z58pke148.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5r52j1auto0z58pke148.png" alt="VS Code toast notification of error message of empty workspace"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Having said that, try to deploy your code asap. This project is not just our first project in Azure but also a re-entry into .net [coming from a 10-year Node.js background]. Tinkering with the generated gitignore, I un-commented the below line [brain freeze on my part that I want to attribute to working with ASP pre-2012😉].&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft319bk095s5c6tf4pk7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft319bk095s5c6tf4pk7a.png" alt="wwwroot entry in gitignore"&gt;&lt;/a&gt;&lt;br&gt;
This led to an insidious error: the app worked fine on the local machine via SWA CLI, but on pushing the commits onto the cloud, GitHub actions failed because it could not find those files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you are creating a new Azure Static Web Apps project, the Azure SWA-generated GitHub action expects the artifacts to be on the default branch[main/master]. I had issues getting to work if I started with other git branches.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs17wxjcqmhsso87tzk3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs17wxjcqmhsso87tzk3l.png" alt="Azure SWA GitHub action fail by running on default Git branch"&gt;&lt;/a&gt;&lt;br&gt;
However, once the Azure SWA is created, the GitHub action works very well with other branches in powerful ways, which we will see in "&lt;strong&gt;&lt;em&gt;action&lt;/em&gt;&lt;/strong&gt;" during our next section.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Authentication with pre-configured providers
&lt;/h2&gt;

&lt;p&gt;Moving forward, like any good self-respecting production web app out there, our app will have certain pages that needs to be accessed only by authenticated users with authorized roles.&lt;/p&gt;

&lt;p&gt;But before plunging headlong into the custom authentication, we will first ensure the IAM plumbing works with one of the Azure SWA pre-configured providers, GitHub.&lt;/p&gt;

&lt;p&gt;Let's create a new git branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git switch -c CustomAuth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/shows/Azure-Tips-and-Tricks-Static-Web-Apps/?WT.mc_id=AZ-MVP-5003041" rel="noopener noreferrer"&gt;Microsoft Learn&lt;/a&gt; has a great video series on Azure SWA, and one of them, &lt;a href="https://docs.microsoft.com/en-us/shows/azure-tips-and-tricks-static-web-apps/how-to-add-a-c-api-to-your-blazor-web-app-12-of-16--azure-tips-and-tricks-static-web-apps/?WT.mc_id=AZ-MVP-5003041" rel="noopener noreferrer"&gt;Frank Boucher's authentication video&lt;/a&gt;, was crucial for this post.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Microsoft has released a .net library that configures an Authentication State Provider for our Azure SWA app.[ Don't go by its nomenclature. Microsoft is underselling it; it's not just for Azure Functions😉]&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.Azure.Functions.Authentication.WebAssembly --prerelease
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;While developing this app in RC1 and RC2, there was only a prerelease version for use. I expected that we would have an official one when .net 6 was released. Alas, it is still in prerelease.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxj12igwfws6tfz66193.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxj12igwfws6tfz66193.png" alt="VS Code terminal showing dotnet add package failing with a request to use prerelease version"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, this package's &lt;a href="https://www.nuget.org/packages/Microsoft.Azure.Functions.Authentication.WebAssembly/1.0.1-preview" rel="noopener noreferrer"&gt;nuget&lt;/a&gt; page is bereft of any content for a potential user, and I have serious doubts about the &lt;a href="https://github.com/Azure/azure-app-service-authentication" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; it's claiming to be its source.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you add the library, we need to register the service in the WASM app builder found in the Program CSharp file: the 2 new lines added 👇 [The structure of this page will be different if you are on .net 5.]&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yt23za25vogzpr0xbk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yt23za25vogzpr0xbk5.png" alt="Program.cs with horizontal green markers at the start of the new lines added to the file"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next up, we need to bolt on the Authorization scaffolding to the Blazor App [This step is applicable for any Blazor WASM standalone app; it's not specific to Azure SWA]&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5z0iwixqxbthavyn416d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5z0iwixqxbthavyn416d.png" alt="Blazor WASM's app razor page with code added for authentication highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Productivity tip: Use VS Code Format Document to get your code in this file to be indented automatically.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cc0qyuxf015xnpk0ozy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cc0qyuxf015xnpk0ozy.png" alt="VS Code Command Palette dropdown with Format Document as the first option"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let's update the layout of the Weather App by replacing the "About" link with a "Login/Logout" one.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjd1rbpbrm2jwg1605qp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjd1rbpbrm2jwg1605qp.png" alt="Pre and post of the main layout page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the URL highlighted within red: &lt;strong&gt;"Azure Static Web Apps uses the &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization/?WT.mc_id=AZ-MVP-5003041&amp;amp;tabs=invitations#system-folder" rel="noopener noreferrer"&gt;/.auth system folder&lt;/a&gt; to provide access to authorization-related APIs."&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the SWA CLI command to bring up the Azure SWA app locally. When you click the Login link, you will come across one of the best features of SWA CLI: its emulation of the Azure SWA authentication infrastructure.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frehfu9hjnetxlzsy76tj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frehfu9hjnetxlzsy76tj.png" alt="SWA CLI emulation of Azure SWA authentication"&gt;&lt;/a&gt;&lt;br&gt;
The provider is pre-filled with the one we have in our path in the .auth link above, with a text box for the user name and a text area for Roles[for now, we leave it untouched]. Clicking on the Login button will lead you back to the index page with the Login link replaced with a message welcoming the username entered in the emulator page and a &lt;strong&gt;logout&lt;/strong&gt; link.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq45fs4zvspnrvn7uuhx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq45fs4zvspnrvn7uuhx2.png" alt="Azure SWA app's index page with the user name highlighted"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Presently, anyone can access the Weather Forecast page [reachable at the /fetchdata route].&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2xg9f3jech049aidziw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2xg9f3jech049aidziw.png" alt="Weather Forecast page with the Login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's change that. Adding just two lines in your FetchDate.razor file and a restart should make that happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgurx84j5oj05h8po40n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgurx84j5oj05h8po40n.png" alt="FetchData.razor file with the code addition highlighted in green"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, when an unauthenticated user clicks on the Fetch Data link in the navbar, the page will display a terse message instead of the weather forecast. "Note to self: It would be cool if the famous MC Hammer  &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=otCpCn0l4Wo" rel="noopener noreferrer"&gt;U can't touch this&lt;/a&gt;&lt;/strong&gt; gif plays when an un-authenticated user clicks that link."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwke1ydjwf48k62c3bkrn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwke1ydjwf48k62c3bkrn.png" alt="Weather Forecast page displaying "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hey, wait a minute, even John Smith from earlier can access the Weather Forecast page?!! Quite right, and here's the thing with "&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?WT.mc_id=AZ-MVP-5003041&amp;amp;view=aspnetcore-6.0#authorize-attribute" rel="noopener noreferrer"&gt;attribute [Authorize]&lt;/a&gt;" as it is, it only restricts anonymous access; once you are authenticated(doesn't matter as who), you are through.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9f65hcm8idqounz61hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff9f65hcm8idqounz61hh.png" alt="The weather forecast is displayed with John Smith as logged in user"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's ensure only weather reporters can access the forecast page; we are now introducing Role-based Access Control[RBAC]. It requires a mere amendment to the Authorize Attribute.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpob0lzk2la3hm8xzle7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpob0lzk2la3hm8xzle7j.png" alt="fetch data code with Authorize attribute amended with weather-reporter role"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now, our authenticated but not having the requisite role aka unauthorized user cannot access the forecast page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq49conmr8iwbcw7m542j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq49conmr8iwbcw7m542j.png" alt="Weather Forecast page displays a message of "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  TIL: David Letterman started his career as a weather reporter in the 70's.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0323d1udjwszx88n3rdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0323d1udjwszx88n3rdw.png" alt="David Letterman in front of weather map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's log out and then click on the Login link again to bring us back to the emulator. Only this time, we masquerade as David Letterman in the role of a weather reporter.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzbphbpnzlo0j0rd0z8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzbphbpnzlo0j0rd0z8z.png" alt="Azure SWA CLI emulator with username as David Letterman and role as weather-reporter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And lo and behold, David Letterman can access the weather forecast.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfwr0xwf81w2zctyte2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfwr0xwf81w2zctyte2s.png" alt="Weather Forecast page successfully displayed with David Letterman highlighted in green"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The combination of SWA CLI and Azure SWA VS Code extensions is a great way to get started with Azure SWA on your local machine. But it does not mean you can develop the app without an internet connection. The VS Code extension has to connect to the Azure infrastructure to do its job. But also the SWA CLI authentication emulator when using it for the first time since it needs to download a few static assets for the page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyumz3csqovote2yvegwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyumz3csqovote2yvegwj.png" alt="SWA CLI emulator page along with Developer Tools console showing "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pull Request in Pre-Production
&lt;/h3&gt;

&lt;p&gt;Great, now that we have corroborated on the workstation that the web app has a functioning IAM; let's validate it after deploying it on Azure.&lt;/p&gt;

&lt;p&gt;Push the branch to GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push -u origin CustomAuth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GitHub dashboard for the project displays a helpful message about a git branch being available and persuading us to undertake a Pull Request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lii0lii9501ggze1d1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lii0lii9501ggze1d1v.png" alt="GitHub project dashboard with pull request button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And like any good OSS project, we follow this hygiene for merging a code into an upstream or main branch.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dhrtvnkmlkjgjyc2d54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dhrtvnkmlkjgjyc2d54.png" alt="GitHub pull request page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember the GitHub Actions generated for a newly created Azure SWA? It also gets triggered for any Pull Request on the main branch.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhj6ci7v0mcojmfhu07m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhj6ci7v0mcojmfhu07m.png" alt="GitHub actions running on pull request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's a crucial productivity feature of Azure SWA: at the end of the successful processing of the GitHub action, the code will be available at a dedicated Stage URL. The Stage URL is almost identical to the production[main/master] branch URL, except for the subdomain appended with the GitHub Pull Request Number and Azure region.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy34zeonuc1ek6x7xrnaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy34zeonuc1ek6x7xrnaw.png" alt="GitHub Pull Request Page showing the automated comment with the stage URL. The Pull Request on the page is highlighted, and so too is the Stage URL in the comments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can test your stage URL independently or make a side-by-side comparison with the production branch.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzy842vopj34g9d0wxfv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzy842vopj34g9d0wxfv.png" alt="Two browser tabs resized to fit screen side by side for comparison of the production branch and the Stage branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the login link[only available in codebase version hosted on the stage URL], and immediately you realize the training wheels are off when the browser redirects to the GitHub Sign-in page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftolxmqcxagc8fdnc2stb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftolxmqcxagc8fdnc2stb.png" alt="GitHub Sign-in page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you logged in for the first time, you need to consent for your personal information[email &amp;amp;/or username, depending on the provider] being shared with the app.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaaatqp1qm1hw96fttc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaaatqp1qm1hw96fttc3.png" alt="Azure consent page when visiting the site for the first time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have been authenticated, but we do not yet have access to the Weather Forecast page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh9ln4z7p0ql8rh1iphi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh9ln4z7p0ql8rh1iphi.png" alt="Weather Forecast page on stage with username highlighted in green and the page message of "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why? David was doing a standup job as a weather reporter, BUT only on my local workstation [SWA CLI]. Over on the stage URL, it's my GitHub profile that is getting authenticated, which has not been assigned any role on the Azure Portal. Anyway, David has a flourishing career as a late-night TV host, and it is time we bid him adieu and have me, or to be precise, my GitHub profile, take over his weather reporting duties on the deployed app. Head on over to the Azure portal and visit the Role management page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you grasp the significance of the last statement? We created an Azure SWA app, developed it locally, deployed it on Azure, created another branch to incorporate the IAM feature, hosted that version on its own stage URL — we did ALL that and did not have to visit the Azure Portal even once, till now. All accomplished from the comforts of the tools you are most familiar with: VS Code and GitHub. A remarkable win for developer productivity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Azure SWA provides a built-in &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization/?WT.mc_id=M365-MVP-5003041&amp;amp;tabs=invitations#role-management" rel="noopener noreferrer"&gt;invitation system&lt;/a&gt; to assign roles to users when using pre-approved providers.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6hlflc31sfzkdjc7cml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6hlflc31sfzkdjc7cml.png" alt="Azure SWA Role invitation tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops, it looks like we need to revisit our code. Roles in Azure cannot contain hyphens. Replace the old role with &lt;strong&gt;&lt;em&gt;weathercaster&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23rm5q5ugs8xq55aod61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23rm5q5ugs8xq55aod61.png" alt="Role in Authorize attribute changed to weathercaster in Fetch data razor page "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test it locally, as we had done earlier.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgu5016lh7hrwv6vhgtdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgu5016lh7hrwv6vhgtdr.png" alt="SWA CLI authentication emulator page with the username filled with Github Profile name and weathercaster added to the list of roles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks good.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvaibpnpqfdfexxyxa3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvaibpnpqfdfexxyxa3o.png" alt="Weather Forecast page with username as GitHub profile name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the &lt;em&gt;weathercaster&lt;/em&gt; role to my GitHub Profile name in the Azure Portal. And click on the invitation link generated below, which will redirect you to the main branch version of the web app[You can close this browser tab].&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2n7dgkpf98vovh7p4ue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2n7dgkpf98vovh7p4ue.png" alt="Role Management page in Azure Portal with weathercaster entered in the role text area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Push the changes to GitHub. Doing so will once again trigger the GitHub Actions, and at the end of its successful processing, it will generate a new comment with the same Stage URL.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6700wm8jfvsknjf8o3ig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6700wm8jfvsknjf8o3ig.png" alt="Visage GitHub Actions page with Azure SWA comments with stage URL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yay, my Github profile finally has access to the Weather Forecast page.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8lyd7flav8lv50c5h1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8lyd7flav8lv50c5h1n.png" alt="Weather Forecast page on the Stage URL with GitHub user profile"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;You can control aspects of the Azure SWA via a JSON configuration file named &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;staticwebapp.config.json&lt;/a&gt;. I like to create this file at the root of the Blazor WASM project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfk30p6s43brtkdshvdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfk30p6s43brtkdshvdq.png" alt="VS Code Explorer showing location of staticwebapp json within the solution hierarchy"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom Routing
&lt;/h3&gt;

&lt;p&gt;It's a good practice the login link has no reference to the authentication provider involved. And since we do not intend to use the other pre-configured providers[Twitter &amp;amp; Azure Active Directory], it's prudent from a security standpoint to have them disabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rewrite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/login/github"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/login/twitter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/login/aad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/logout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"redirect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/logout?post_logout_redirect_uri=/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Startup the SWA CLI and replace the .auth links in MainLayout accordingly. You can see the hot reload in action too.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5ortwojj451mu1oor4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5ortwojj451mu1oor4g.png" alt="Main layout with custom routes highlighted in red"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify the change on your browser's dev tools.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kqlkvorhhwtromtj5ft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kqlkvorhhwtromtj5ft.png" alt="SWA CLI rendered page with Edge Dev Tools opened and the Login link element's href attribute highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on the Login link should bring you to the SWA CLI emulator. Rinse &amp;amp; repeat.&lt;/p&gt;
&lt;h3&gt;
  
  
  Secure Routes by Roles
&lt;/h3&gt;

&lt;p&gt;To be consistent with our code, we have to ensure that a direct request to the server for /fetchdata route of the Weather Forecast page is accessed only by authenticated users with the &lt;strong&gt;&lt;em&gt;weathercaster&lt;/em&gt;&lt;/strong&gt; role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/fetchdata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowedRoles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"weathercaster"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, there's a caveat. Suppose we allow only folks with the role of "LordCount" to access the /counter route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowedRoles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"LordCount"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is an anonymous direct request to this route, then the platform will not serve the request.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9jiue1bvrray7cu4yl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9jiue1bvrray7cu4yl5.png" alt="SWA CLI emulator rendered a 401 page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this does not prevent folks from accessing the route if the first request is to the index file [which is open to anonymous access]. It, in turn, ensures the whole WASM app gets loaded onto the user browser, and now anyone, including the unauthenticated, can access the counter page. [WhyY? The nature of the beast!!! Once a Single Page Application[SPA] is loaded onto the browser, the routes are traversed locally without invoking the Azure infrastructure]. And, unlike the fetchdata page, we have not secured the counter page via the Blazor Authorization implementation.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9jiue1bvrray7cu4yl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9jiue1bvrray7cu4yl5.png" alt="Counter page accessed with a Login link showing that page is open to anonymous access"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Fallback Routes
&lt;/h3&gt;

&lt;p&gt;And because it's a SPA, we also need to serve those requests asked of the server for a route that does not adhere to any of the &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration#fallback-routes/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;routing rules&lt;/a&gt;. [just like a default statement in a switch clause 😁]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"navigationFallback"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rewrite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/index.html"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will be revisiting this file as we implement more features in the coming weeks. It is worth your while to familiarize yourself thoroughly with different aspects of the config file. During my research, I found that one of the reasons that the CSP for the global header was somewhat lax was because of &lt;a href="https://github.com/dotnet/aspnetcore/issues/34428#issuecomment-934348957" rel="noopener noreferrer"&gt;the browser refresh feature&lt;/a&gt;, which, coincidentally I raised just before the meltdown caused by the Hot Reload announcement.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjifr0z076kedd1fy2hx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjifr0z076kedd1fy2hx.jpg" alt="Dev Tools console showing the CSP error flagged by the browser"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Custom Authentication
&lt;/h2&gt;

&lt;p&gt;Now we need to replace GitHub with our custom authentication provider, Auth0. A question might be swirling up in your mind: if the plan was to have Auth0 as our authentication provider, why was I messing around with GitHub? Here's the rub, custom authentication is not part of the Free plan for Azure Static Web Apps but that of the paid &lt;a href="https://azure.microsoft.com/en-us/pricing/details/app-service/static/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;Standard Plan&lt;/a&gt;. Our strategy was to ensure we got the nuts and bolts of our frontend's IAM right, without incurring any costs.&lt;/p&gt;

&lt;p&gt;Getting custom authentication to work involves a delicate dance amongst the three amigos: Azure SWA[portal + configuration file], Blazor WASM, and Auth0&lt;/p&gt;
&lt;h3&gt;
  
  
  Auth0
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://techcommunity.microsoft.com/t5/apps-on-azure-blog/using-auth0-with-static-web-apps/ba-p/2353653/?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;Aaron Powell's post&lt;/a&gt; has been a big help in configuring the Auth0 part.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create an application, and note the following properties which we will need later on:&lt;br&gt;
a. Client ID&lt;br&gt;
b. Client Secret&lt;br&gt;
c. Domain Authority URL&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjifr0z076kedd1fy2hx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjifr0z076kedd1fy2hx.jpg" alt="Auth0 Application Properties"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As OIDC authentication rides piggyback on &lt;a href="https://auth0.com/docs/authorization/protocols/protocol-oauth2" rel="noopener noreferrer"&gt;OAuth2 authorization flow&lt;/a&gt;, we have to configure the endpoints that Auth0 needs to redirect post the login process.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdlo7h8p8w1k4qjwg6n7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdlo7h8p8w1k4qjwg6n7.png" alt="Auth0 OAuth2 Endpoints"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Azure Portal
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Visit the Hosting Plan tab under the Static Web App in the Azure Portal to convert the plan from free to standard.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91x2oxzy7pilqg78nl33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91x2oxzy7pilqg78nl33.png" alt="Hosting Plan of the Azure Static Web App showing the features of both the Free and Standard Plan"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on the Configuration link within the navigation pane, choose the stage environment and add two applications secrets, namely AUTH0_CLIENT_ID, &amp;amp; AUTH0_CLIENT_SECRET, with the values from step 1 of the Auth0 subsection above.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufqufzmpfwo1jnw3uw2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufqufzmpfwo1jnw3uw2p.png" alt="Azure SWA Configuration page with the secrets added"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Azure SWA Configuration
&lt;/h3&gt;

&lt;p&gt;Back to our code, we provision &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-custom?WT.mc_id=AZ-MVP-5003041&amp;amp;tabs=openid-connect" rel="noopener noreferrer"&gt;custom authentication&lt;/a&gt; in our static web app config file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identityProviders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"customOpenIdConnectProviders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"auth0"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"registration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"clientIdSettingName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AUTH0_CLIENT_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"clientCredential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"clientSecretSettingName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AUTH0_CLIENT_SECRET"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"openIdConnectConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"wellKnownOpenIdConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://developerday-ind.us.auth0.com/.well-known/openid-configuration"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nameClaimType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"scopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"loginParameterNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things of note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Named our custom provider as auth0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The application secrets we provisioned in the settings on the portal above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The well-known OpenID configuration endpoint, available at the Domain Authority URL.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unfortunately, the Domain Authority URL was not considered sensitive enough to be secured as an application secret. And since we have to check in the code into a public GitHub repository, in the interim, I'm constrained to utilize an Auth0 developer tenant. [Tooting a bit of my own horn: This tenant was employed in the &lt;a href="https://auth0.com/blog/auth0-announces-the-winners-of-the-actions-hackathon/" rel="noopener noreferrer"&gt;Auth0 hackathon in which I was runner-up&lt;/a&gt;: Used Auth0 Actions with Yoonik Face Recognition; I'll be expanding on this in the upcoming posts]&lt;/p&gt;

&lt;p&gt;Also, we need to update the login route in the static file. And because we have implemented this route rule earlier, we don't need to modify the link within the MainLayout page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rewrite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/login/auth0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we did with the other pre-configured providers, it's now time to thank GitHub for its service and disable it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/.auth/login/github"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the CLI, and once you click on the Login link, the SWA CLI authentication emulator page comes up. We now see the provider field pre-populated with auth0 [the name we gave in the static config file], and I'm using my username as it is in the Auth0 tenant.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbby2qauckrhizvsk0c5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbby2qauckrhizvsk0c5u.png" alt="SWA CLI render emulator page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By now, you know the drill. Send up the git commits to GitHub and wait for the GitHub actions to complete. Once done, my Auth0 profile can haz some of that sweet Weather Forecast.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgcwx2bdgnp1y383qmgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgcwx2bdgnp1y383qmgv.png" alt="Weather forecast with the Auth0 username highlighted"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom Authorization
&lt;/h3&gt;

&lt;p&gt;Update [13th Dec'21]: This section should have been the logical culmination of this blog post. Alas, I am encountering HTTP 500 errors on Azure SWA when incorporating this feature.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqtle36u3gckqe38lur3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqtle36u3gckqe38lur3.png" alt="Azure SWA displaying a message about internal server error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are no logs available to dig through to find the cause, which was compounded by the &lt;a href="https://twitter.com/hackmum/status/1467948077096988672" rel="noopener noreferrer"&gt;total lack of response&lt;/a&gt; from the Azure team to our queries for days.&lt;/p&gt;

&lt;p&gt;Since they are stakeholders waiting on this and the upcoming blog posts, I could not interminably wait on the Azure SWA team. To get the caravan going, I decided to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create another git branch that will retrace the app a step back on production to the pre-approved providers feature&lt;/li&gt;
&lt;li&gt;Revert to the Free Plan. After all, we bumped up to the paid Standard Plan to have Custom Authentication, and since that is not working, it makes no sense to keep the meter running on the paid plan.&lt;/li&gt;
&lt;li&gt;Update this subsection after a solution from the Azure SWA team.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Auth0 Role Management
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the Auth0 end, we create a Role named "weathercaster"&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyy8hp2dc7iidpe5zpwv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyy8hp2dc7iidpe5zpwv.png" alt="Auth0 Add Role section with the name and description fields filled out"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add my username to the role.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrvcezhj7wr5n3i0ycqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrvcezhj7wr5n3i0ycqm.png" alt="Auth0 add the user to the role"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Auth0 Actions
&lt;/h3&gt;

&lt;p&gt;We need to add the roles to the id token, and just for good measure, I'm also going to add them to the access token. In the past, for my older Auth0 tenants, this was achieved by &lt;a href="https://auth0.com/docs/rules" rel="noopener noreferrer"&gt;Auth0 Rules&lt;/a&gt; and later by &lt;a href="https://auth0.com/docs/hooks" rel="noopener noreferrer"&gt;Auth0 Hooks&lt;/a&gt;. Last year, Auth0 introduced &lt;a href="https://auth0.com/docs/actions/actions-overview" rel="noopener noreferrer"&gt;Actions&lt;/a&gt; to supersede them, and it's time we take the new hotness for a ride.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We are going to need a Custom Action&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16njo23ftkswitquddqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16njo23ftkswitquddqp.png" alt="Auth0 Action Library"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a Custom Action&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74ai79cl8ubpwqykgviy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74ai79cl8ubpwqykgviy.png" alt="Create Auth0 Action Modal Page"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href="https://microsoft.github.io/monaco-editor/" rel="noopener noreferrer"&gt;Monaco code editor&lt;/a&gt; opens up. And if you get a sense of déjà vu, that's because its also the one for VS Code. Adding a role to an OAuth2.0 token is such a common use case that you can find a code snippet for it, amongst others, after clicking the &lt;strong&gt;&lt;em&gt;&lt;a href="https://auth0.com/docs/actions/triggers/post-login" rel="noopener noreferrer"&gt;View Samples&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; sticky button at the bottom right of the editor, which like the genius developer I am, have already copy-pasted into the editor.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2s33xoglpexr31or7u80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2s33xoglpexr31or7u80.png" alt="Auth0 Action Code Editor with code snippet"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to add the roles during our Login Flow.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49qa02nksynp9boprzk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49qa02nksynp9boprzk1.png" alt="Auth0 Action Flow Page"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drag and drop our Custom Action into the Login Flow.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl865fkbc9df8w2mspprj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl865fkbc9df8w2mspprj.png" alt="Auth0 Action"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply the changes, and we are done on the Auth0 end.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04wjd7tqng4lmlyc388o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04wjd7tqng4lmlyc388o.png" alt="Auth0 Action Applied"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Trust, but verify"&lt;/strong&gt;: We used the &lt;a href="https://auth0.com/docs/quickstart/spa/vanillajs#read-the-user-profile" rel="noopener noreferrer"&gt;Auth0 vanilla JS SPA sample&lt;/a&gt; to check that the Auth0 Action is indeed adding the roles to the ID Token.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifhkfvinht8njjsmj4mp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifhkfvinht8njjsmj4mp.png" alt="Browser page showing the profile sent by Auth0, with the dev tools console also showing the same"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Azure Function in Role Management
&lt;/h3&gt;

&lt;p&gt;To glean out the custom roles from the response sent by an identity provider post-authentication, &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/authentication-authorization??WT.mc_id=M365-MVP-5003041&amp;amp;tabs=function" rel="noopener noreferrer"&gt;Azure SWA has a preview feature of using Azure Function to process the payload from the identity provider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the static config file, we need to enhance the auth section with the path of the Azure Function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rolesSource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/GetRoles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identityProviders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here is where things get awry. For our first iteration of the Azure Function, I wanted to play safe and used the &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/assign-roles-microsoft-graph?WT.mc_id=M365-MVP-5003041" rel="noopener noreferrer"&gt;sample tutorial&lt;/a&gt;. It's not even processing the payload, but rather hardcoding the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohhbceddl4ovmtam49yn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohhbceddl4ovmtam49yn.png" alt="VS Code Editor with left pane showing the API code, right pane the result of the invocation of the function, and the bottom terminal with the command to start the function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But pushing these changes to GitHub, and post a successful login [verified via Auth0 logs] on the Stage URL, Azure SWA throws up the dreaded internal server error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Security is one of the pillars of a well-architected web application. And in my experience, it is always better to tackle it upfront because you have to depend on the ecosystem to get the job done. And if things go wrong, as it panned out here, you have slack in your project timeline to hustle up a Plan B.&lt;/p&gt;

&lt;p&gt;Azure SWA is a productivity win for developers but so long as you use one of the pre-configured identity providers. For Custom Authentication, it's not yet ready for prime time.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>auth0</category>
      <category>iam</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>A Well-Architected Cloud Application</title>
      <dc:creator>Augustine Correa</dc:creator>
      <pubDate>Wed, 08 Sep 2021 00:00:25 +0000</pubDate>
      <link>https://dev.to/indcoder/a-well-architected-cloud-application-44ff</link>
      <guid>https://dev.to/indcoder/a-well-architected-cloud-application-44ff</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If &lt;strong&gt;"World Peace"&lt;/strong&gt; is a beauty pageant contestant's most cliched answer, then &lt;strong&gt;"Well-Architected"&lt;/strong&gt; is that of a cloud developer describing their app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An app to deliver business value at quality relies on code and infrastructure. Most cloud service providers, by now, have gathered a wealth of experience &amp;amp; expertise on how best to develop different types of applications on their infrastructure and have provided guidance accordingly. Azure et al. have termed apps following such guidance are termed as &lt;strong&gt;"&lt;a href="https://docs.microsoft.com/en-us/azure/architecture/framework/?WT.mc_id=AZ-MVP-5003041"&gt;well-architected&lt;/a&gt;"&lt;/strong&gt; and have been successful in providing a consistent experience for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Smaller Picture
&lt;/h2&gt;

&lt;p&gt;Right from our first &lt;a href="//./Strategic_Domain_Driven_Design#big-picture-event-storming"&gt;blog post&lt;/a&gt;, we have been progressively narrowing our focus. Back then, our proposed Architecture for the entire solution looked somewhat like 👇&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OKvZjeC7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e04k5gfrb2vt0zuxbu5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OKvZjeC7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e04k5gfrb2vt0zuxbu5p.png" alt="Visage Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Honey, Azure SWA shrunk the Architecture Diagram
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;In tech, of late, procrastination isn't that bad a thing - by me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While we were muddling through our design, the good folks at Microsoft had raced ahead to release &lt;a href="https://azure.microsoft.com/en-in/services/app-service/static/?WT.mc_id=AZ-MVP-5003041"&gt;Azure Static Web Apps&lt;/a&gt;. Incorporating Azure SWA would consolidate our frontend and API, reducing management overhead, and in the process, also save us a pretty penny. To celebrate the occasion, Azure held a virtual event, &lt;a href="https://channel9.msdn.com/Events/Learn-TV/Static-Web-Apps-Code-to-Scale?WT.mc_id=AZ-MVP-5003041"&gt;Code to Scale&lt;/a&gt;[Some of the videos were great for diving into SWA]. And it was accompanied by a learning challenge, which I felt didn't quite build upon the sessions. For example, there were three mandatory modules on JS, Blazor, &amp;amp; Gatsby; a newbie would only be interested in only one[a choice would have been better]. Also missing were modules on local development with &lt;a href="https://techcommunity.microsoft.com/t5/apps-on-azure/introducing-the-azure-static-web-apps-cli/ba-p/2257581/?WT.mc_id=AZ-MVP-5003041"&gt;Azure SWA CLI&lt;/a&gt; and E2E testing with &lt;a href="https://docs.microsoft.com/en-us/microsoft-edge/playwright/?WT.mc_id=AZ-MVP-5003041"&gt;Playwright&lt;/a&gt;. I have created a &lt;a href="https://docs.microsoft.com/en-us/users/augustinecorrea-4621/collections/6ew4a4m857q61g/?WT.mc_id=AZ-MVP-5003041"&gt;MS Docs Learning Path for Azure SWA&lt;/a&gt;, which I will be updating in the coming weeks as I find more modules that are useful for Blazor WASM based Azure SWA.&lt;/p&gt;

&lt;p&gt;For the 1st iteration &lt;a href="https://dev.azure.com/augcor/Visage/_sprints/backlog/Visage%20Team/Visage/MVP"&gt;"MVP"&lt;/a&gt;, our erstwhile Architecture diagram has slimmed down considerably.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uUP1grt8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/duweohj4x4nql572ukhp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uUP1grt8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/duweohj4x4nql572ukhp.png" alt="Visage Architecture Diagram - MVP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Our frontend and API have fused into a single Azure-managed service. [Yo, imma also gonna be drinking some of that &lt;a href="https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-4/?WT.mc_id=AZ-MVP-5003041"&gt;minimal API&lt;/a&gt; Kool-Aid.]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are taking a bet on &lt;a href="https://dotnet.microsoft.com/?WT.mc_id=AZ-MVP-5003041"&gt;.Net 6&lt;/a&gt; vision. Because our deployment targets, in the coming iterations, will be devices like Laptops/Tabs[&lt;a href="https://docs.microsoft.com/en-us/windows/apps/winui/?WT.mc_id=AZ-MVP-5003041"&gt;WinUI&lt;/a&gt;] and mobiles[&lt;a href="https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/?WT.mc_id=AZ-MVP-5003041"&gt;MAUI&lt;/a&gt;]. We are doubling down on &lt;a href="https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor/?WT.mc_id=AZ-MVP-5003041"&gt;Blazor&lt;/a&gt; so that we can reuse a substantial part of our codebase &lt;strong&gt;as-is&lt;/strong&gt; across these platforms. Cons: In the diagram, we indicate there is still NO native Application Insight integration for Blazor WASM, looks like Azure is still sitting on the fence for this one. &lt;strong&gt;A web app team is flying blind without user action and transaction telemetry.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also introducing &lt;a href="https://docs.microsoft.com/en-us/azure/event-grid/overview/?WT.mc_id=AZ-MVP-5003041"&gt;Azure Event Grid&lt;/a&gt;, which will be the fulcrum of our event-based architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://azure.microsoft.com/en-in/services/cosmos-db/?WT.mc_id=AZ-MVP-5003041"&gt;Azure Cosmos DB&lt;/a&gt;, as our data store, is a natural counterfoil for Azure SWA: faster app development, global scale, and is fully managed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The recently released SWA CLI should bolster our local coding experience, and we will attempt the entire development on &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/about/?WT.mc_id=AZ-MVP-5003041"&gt;WSL2&lt;/a&gt; 🤞.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pillars of a Well-Architected Cloud Application
&lt;/h2&gt;

&lt;p&gt;Both &lt;a href="https://aws.amazon.com/architecture/well-architected/?wa-lens-whitepapers.sort-by=item.additionalFields.sortDate&amp;amp;wa-lens-whitepapers.sort-order=desc"&gt;AWS&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/azure/architecture/framework/"&gt;Azure&lt;/a&gt; agree that there are 5 &lt;strong&gt;"pillars"&lt;/strong&gt; of a well-architected cloud application, while &lt;a href="https://cloud.google.com/architecture/framework"&gt;Google&lt;/a&gt; demurs that they are only 4 &lt;strong&gt;"principles"&lt;/strong&gt;. It brought back memories of the hilarious scene from &lt;a href="https://www.youtube.com/watch?v=I48hr8HhDv0"&gt;History of the World where God gave Moses "actually" 15 commandments.&lt;/a&gt;😁&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cost Optimization&lt;/li&gt;
&lt;li&gt;Operational Excellence&lt;/li&gt;
&lt;li&gt;Performance Efficiency&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Security, Privacy, and Compliance [Psst: Azure and AWS just went with security, but I did not want Google to feel left out, so I have used their nomenclature 😉]&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From a project management perspective, these pillars render themselves quite naturally as epics. And that's how we roll with them on our &lt;a href="https://azure.microsoft.com/en-in/services/devops/boards/?WT.mc_id=AZ-MVP-5003041"&gt;Azure Boards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.azure.com/augcor/Visage/_workitems/recentlyupdated/?WT.mc_id=AZ-MVP-5003041"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5nk04g3k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrb0dtb2r6gli35rhkm6.png" alt="Azure DevOps Boards Epics"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost Optimization
&lt;/h3&gt;

&lt;p&gt;Google has four principles because it clubs Performance with Cost Estimation. While most of us dream of driving a Ferrari, but as an Indian, &lt;a href="https://www.youtube.com/watch?v=akmpsx5F2-4"&gt;this car ad gets us&lt;/a&gt;, right to the last paise 😊 =&amp;gt;  my priority will be to keep a close watch on our cloud costs. Also, it provides &lt;strong&gt;Early Warning Signals&lt;/strong&gt; [to borrow a financial term] for most Architectural issues.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pricing Calculator
&lt;/h4&gt;

&lt;p&gt;Before we write a single line of code and deploy artifacts, we must know how much this will cost us. Azure provides a handy tool to do just that: &lt;a href="https://azure.microsoft.com/en-in/pricing/calculator/?WT.mc_id=AZ-MVP-5003041"&gt;Azure pricing calculator&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For cloud practitioners, architecture diagrams doubles up as a handy shopping list. - once again, by me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's ring up our resources on the calculator [&lt;a href="https://azure.com/e/bcea12c81ce748b190dc532a9055ff13"&gt;click here for the estimate&lt;/a&gt;]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initially, we will be developing with the free version of the Azure SWA, but I'm opting for the run-rate of the Standard version because we will be using Custom Authentication [&lt;a href="https://auth0.com/"&gt;Auth0&lt;/a&gt;].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.azure.com/augcor/Visage/_workitems/edit/114/?workitem=124&amp;amp;WT.mc_id=AZ-MVP-5003041"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---DlcFK-w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/op6y1qkyjn3qah0m3y6i.png" alt="Azure SWA Standard Pricing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Going with the &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/serverless/?WT.mc_id=AZ-MVP-5003041"&gt;serverless pricing of Cosmos DB&lt;/a&gt; and a modest 1 GB storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.azure.com/augcor/Visage/_workitems/edit/114/?workitem=124&amp;amp;WT.mc_id=AZ-MVP-5003041"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CfKU7q-e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6bfi3qowf9jq2d71g4a.png" alt="Azure CosmosDB Pricing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/event-grid/overview/?WT.mc_id=AZ-MVP-5003041"&gt;Event Grid&lt;/a&gt; is free for the first 100,000 operations. I'm always amazed at these prices; 10 years ago, we would have been shelling a few lakhs for a fraction of such a service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.azure.com/augcor/Visage/_boards/board/t/Visage%20Team/Stories/?workitem=126&amp;amp;WT.mc_id=AZ-MVP-5003041"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0A8KdITD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2hfxa0w9p6nn44tg20k.png" alt="Azure Event Grid Pricing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With &lt;a href="https://azure.microsoft.com/en-in/services/key-vault/?WT.mc_id=AZ-MVP-5003041"&gt;Key Vault&lt;/a&gt;, we come to the first service not offered in any of the Azure regions in India, as per the Pricing Calculator. But it's available in the Central India region [bug ???]&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lu40cb-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yo8iaybvc2pzmhspbhek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lu40cb-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yo8iaybvc2pzmhspbhek.png" alt="Key vault Pricing"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;a href="https://docs.microsoft.com/en-us/azure/azure-monitor/?WT.mc_id=AZ-MVP-5003041"&gt;Azure Monitor&lt;/a&gt;, I have been liberal with the number of logs and metrics that are being captured because during the early days, you are trying to get familiar with your application. And this ties in with other pillars, which we will touch upon in forthcoming posts.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6zrSNhFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qct50d1j3d7kuo90vora.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6zrSNhFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qct50d1j3d7kuo90vora.png" alt="Azure Monitor Pricing"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We have attached the excel sheet estimate with the &lt;a href="https://dev.azure.com/augcor/Visage/_boards/board/t/Visage%20Team/Stories/?workitem=123"&gt;Pricing Calculator user story&lt;/a&gt; and checked it in our git repository.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The grand total comes to a very affordable ₹1,687.66 per month with no upfront payment.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Azure Cost Management [ACM]
&lt;/h4&gt;

&lt;p&gt;With ACM, we can get a quick look at our costs with a detailed breakup. And more importantly, create a trackable budget via billing data/reports, and set up cost alerts.&lt;/p&gt;

&lt;p&gt;For the MVP iteration, we have allocated a budget of ₹2000, a buffer of ~18% over our Pricing Calculator estimate. We have set a threshold alert for 75% of the actual cost and 110% of the forecasted budget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f2q34SNI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0vmt5jq16nghybjfbi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f2q34SNI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0vmt5jq16nghybjfbi5.png" alt="Azure Budget Cost Alerts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the day's end, our items on our Azure Boards are "shifting right" -&amp;gt; unlike in DevOps, good news in Project Management.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9dhnkidk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zpuuyi31w26bvlv6hz4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9dhnkidk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zpuuyi31w26bvlv6hz4n.png" alt="Azure Boards Post Budget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our upcoming blog posts, we will start incorporating best practices from other pillars into our solution. Up next, though, I will be leaving my comfort zone to plunge into UI/UX wireframing and prototyping. Stay safe 💪.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Strategic Domain Driven Design</title>
      <dc:creator>Augustine Correa</dc:creator>
      <pubDate>Thu, 01 Oct 2020 18:36:27 +0000</pubDate>
      <link>https://dev.to/indcoder/strategic-domain-driven-design-efn</link>
      <guid>https://dev.to/indcoder/strategic-domain-driven-design-efn</guid>
      <description>&lt;p&gt;A software project is akin to crossing familiar valleys to scale up a new mountain: maps are vital. And &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt; does just that: it not only provides a 20000 feet view but also guides us along a pathway to flesh out our project.&lt;/p&gt;

&lt;p&gt;We are going to architect a real project with Domain-Driven Design; our project Visage's &lt;a href="https://github.com/HackerspaceMumbai/Visage/wiki/1-Statement-Of-Intent" rel="noopener noreferrer"&gt;Statement of Intent&lt;/a&gt; and &lt;a href="https://github.com/HackerspaceMumbai/Visage/wiki/2-Essential-Workflow" rel="noopener noreferrer"&gt;Workflow&lt;/a&gt; forms the foundation for the design decisions to follow.&lt;/p&gt;

&lt;p&gt;In this first blog post about the project, we will model the Domain through a process of intentional discovery and rely on different tools to build broad contours, tease out implicit requirements as well as unearth any blind spots. All this will become apparent below as a "clearer picture" emerges.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal of Strategic DDD is to help us chart the most elusive things in Domain-driven Design: &lt;a href="https://www.infoq.com/news/2019/06/bounded-context-eric-evans/" rel="noopener noreferrer"&gt;Bounded Contexts&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Big Picture Event Storming
&lt;/h2&gt;

&lt;p&gt;Our first tool is Event Storming[ES], which is essentially the plotting of Domain events [usually depicted in orange] on a somewhat linear time scale as they occur in real life.&lt;/p&gt;

&lt;p&gt;Our 1st iteration yielded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs39tlrnqc37qkgaffzbo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs39tlrnqc37qkgaffzbo.jpg" alt="1st iteration Event Storming"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://martinfowler.com/bliki/UbiquitousLanguage.html" rel="noopener noreferrer"&gt;Ubiquitous Language  &lt;/a&gt; is the key to separate out Bounded Contexts, I feel there should also be a core set of Unambiguous Vocabulary to unify a domain. The word &lt;em&gt;Event&lt;/em&gt; in English has different meanings depending on the context, especially in software &amp;amp; DDD. So in a nod to my Indian heritage, I standardized on the Sanskrit root word for events, meetups, conferences, functions etc -&amp;gt; &lt;strong&gt;Karyakaram&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please notice the spacing between the events. Some are bunched up together and this is a reflection of their proximity to each other in respect of time. Our bounded contexts are emerging.&lt;/p&gt;

&lt;p&gt;These events are triggered by commands[depicted as blue rectangular boxes] which are usually "intentioned" by users [in yellow] or external systems [in pink].&lt;/p&gt;

&lt;p&gt;Our 2nd iteration results in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmumbai-hackerspace%2Fimage%2Fupload%2Fq_auto%2Cf_auto%2Fv1599142822%2FVisage%2FDesign-ES-2nd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmumbai-hackerspace%2Fimage%2Fupload%2Fq_auto%2Cf_auto%2Fv1599142822%2FVisage%2FDesign-ES-2nd.jpg" alt="2nd iteration Event Storming"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note how we have now added a few more Domain events. This process of discovery is encouraged in Event Storming. Our first draft will never be perfect but it sets the bedrock for further exploration.&lt;/p&gt;

&lt;p&gt;Also we noticed that our technical biases are creeping in[Send Email, duh🤦‍♂️]. We need to ensure all terms are only domain specific. Lets do some correction and flesh out the rest of the diagram.&lt;/p&gt;

&lt;p&gt;Voila, the final version of the Big Picture Event Storming is built with &lt;a href="https://app.mural.co/invitation/mural/hm2422/1595976908405?sender=augcor3018&amp;amp;key=22e68a54-6b14-413d-a37c-b6278ccacfb7" rel="noopener noreferrer"&gt;Mural&lt;/a&gt; which has a more professional looking Event Storming template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqcod1kyfbm6flvwbxfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqcod1kyfbm6flvwbxfg.png" alt="Big Picture Event Storming"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on a few design heuristics, "I spy" the nebulous contours of at least two bounded contexts[BC] with the "RegistrationClosed" being the pivotal event. I have named them "Event Registration" and "Check-ins" respectively after agonizingly iterating over them over a day or so especially the former.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Storytelling
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://domainstorytelling.org/" rel="noopener noreferrer"&gt;Domain Storytelling&lt;/a&gt; is a DDD tool where Domain Experts pictorially depict their workflow involving actors and work objects. The kicker here is that the activities are numbered in order of their occurrence.&lt;/p&gt;

&lt;p&gt;Thanks to the good folks at &lt;a href="https://github.com/WPS" rel="noopener noreferrer"&gt;WPS&lt;/a&gt;, who have provided a Domain Storytelling &lt;a href="https://www.wps.de/modeler/" rel="noopener noreferrer"&gt;Modeller&lt;/a&gt; to make our lives much easier, we have a short [&lt;a href="https://www.youtube.com/watch?v=5vXRYps9_n8" rel="noopener noreferrer"&gt;20-second video of the Visage "story"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the heuristics that is associated with Domain StoryTelling is that uni-directional flows are usually indicative of bounded contexts. This was quite revealing for now it shows that they are definitely &lt;a href="https://docs.microsoft.com/azure/architecture/microservices/model/domain-analysis?WT.mc_id=OSS-MVP-5003041" rel="noopener noreferrer"&gt;three distinct bounded contexts&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scheduling&lt;/li&gt;
&lt;li&gt;Shortlisting
The above two have been carved out from the earlier Event Management. While ruminating over the names [deja vu, I know], I had a look at Eventbrite's blade for event creation and found that they named it &lt;em&gt;Scheduling&lt;/em&gt;. And truth be told, at a higher level, that's what it actually is. &lt;strong&gt;To let DDD help you, you got to learn to keep your ego/biases aside.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;CheckingIn&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Core Domains Charts
&lt;/h2&gt;

&lt;p&gt;Now that we have our Bounded Contexts, let's see how they work with each other. Most folks go with Context Maps as their tool for this as recommended by &lt;a href="https://dddcommunity.org/book/evans_2003/" rel="noopener noreferrer"&gt;Eric Evans&lt;/a&gt; but I prefer Core Domain Charts since the latter strategically depicts the relationships between bounded contexts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F86zeo6yezjpzla9w0b6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F86zeo6yezjpzla9w0b6x.png" alt="Core Domain Charts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bounded Context Canvas
&lt;/h2&gt;

&lt;p&gt;Next up we try to focus on each Bounded Context individually. &lt;a href="https://medium.com/@ntcoding" rel="noopener noreferrer"&gt;Nick Tune&lt;/a&gt; &amp;amp; his buddies at &lt;a href="https://github.com/ddd-crew" rel="noopener noreferrer"&gt;DDD Crew&lt;/a&gt; [go check out their GitHub organization for more DDD goodies] had come up with a modelling technique to approach a Bounded Context like a black box: see what goes in, what comes out and what gets processed. The canvases have been sketched out using &lt;a href="https://drawio-app.com/" rel="noopener noreferrer"&gt;draw.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6a85m0au1wedaqdagqo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6a85m0au1wedaqdagqo4.png" alt="Shortlisting Bounded Context Canvas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you see the Core Domain Charts effect out here? Since Shortlisting is a core domain, it will be in a driving position vis-a-vis Scheduling, which is a Generic/Supporting domain, hence the former is the customer while the latter is a supplier. On the other hand with CheckingIn, which is also a core domain, it is treated on an equal footing. Don't ignore realpolitik.&lt;/p&gt;

&lt;p&gt;These canvases are the first artifacts to be &lt;a href="https://github.com/HackerspaceMumbai/Visage/commit/6768e24bc865e2b12109198ebe0421ba93991b2b" rel="noopener noreferrer"&gt;checked into the GitHub repo hosted source folder&lt;/a&gt; of their respective microservices as part of &lt;a href="https://leanpub.com/livingdocumentation" rel="noopener noreferrer"&gt;Living Documentation&lt;/a&gt;. In a sense, it signifies these canvases are the spiritual fountainhead of the co-located code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact Mapping
&lt;/h2&gt;

&lt;p&gt;Lastly, an app or a project does not exist in a vacuum, rather its invariably part of an ecosystem. I use Impact Mapping to do a kind of out of the box thinking, getting the lay of the land so to say, see who are allies of the project and what it is up against to make a dent in the cosmos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqoggy2lhi4rb1vl6fuce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqoggy2lhi4rb1vl6fuce.png" alt="Impact Mapping"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Make your vision so clear that your fears become irrelevant."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can follow the progress of this project on &lt;a href="https://bit.ly/2YHTZgq" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the next blog post, we will be going into Tactical DDD with Example Mapping based BDD, Process Modelling EventStorming, Aggregate Canvases, etc.&lt;/p&gt;

</description>
      <category>domaindrivendesign</category>
      <category>eventstorming</category>
      <category>boundedcontext</category>
      <category>impactmapping</category>
    </item>
    <item>
      <title>Hi, I'm Augustine Correa</title>
      <dc:creator>Augustine Correa</dc:creator>
      <pubDate>Mon, 15 May 2017 14:53:07 +0000</pubDate>
      <link>https://dev.to/indcoder/hi-im-augustine-correa</link>
      <guid>https://dev.to/indcoder/hi-im-augustine-correa</guid>
      <description>&lt;p&gt;I'm the prime mover behind the largest OSS community in Bombay, &lt;a href="//fb.com/hackmum"&gt;Hackerspace Mumbai&lt;/a&gt;. And as part of that initiative, I organize the longest running [over 4 years] monthly tech meetup in Bombay #mumtechup &lt;a href="//fb.com/mumtechup"&gt;Mumbai Technology Meetup&lt;/a&gt;. I'm also the organizer for the &lt;a href="https://www.meetup.com/Docker-Mumbai/" rel="noopener noreferrer"&gt;Docker Mumbai&lt;/a&gt;, Kubernetes Mumbai, and &lt;a href="https://www.meetup.com/Mumbai-HashiCorp-User-Group/" rel="noopener noreferrer"&gt;Hashicorp Mumbai&lt;/a&gt; community along with the local &lt;a href="https://www.meetup.com/Azure-Cloud-meetup-Mumbai-chapter/" rel="noopener noreferrer"&gt;Azure IoT meetup&lt;/a&gt; groups.&lt;/p&gt;

&lt;p&gt;And to avoid the front-end technologies feeling left out, I'm is also the Meteor Mumbai captain. My latest project has both GraphQL and Angular 4 (yeah, I love to live dangerously).&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
