<?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: The 425 Show</title>
    <description>The latest articles on DEV Community by The 425 Show (@425show).</description>
    <link>https://dev.to/425show</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%2Forganization%2Fprofile_image%2F2728%2F46bcfa3e-bd32-4491-979c-f807ebd348f1.png</url>
      <title>DEV Community: The 425 Show</title>
      <link>https://dev.to/425show</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/425show"/>
    <language>en</language>
    <item>
      <title>.NET 7 WebApp with Https in Docker, secured by Azure AD</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Thu, 14 Apr 2022 02:05:26 +0000</pubDate>
      <link>https://dev.to/425show/net-7-webapp-with-https-in-docker-secured-by-azure-ad-2nna</link>
      <guid>https://dev.to/425show/net-7-webapp-with-https-in-docker-secured-by-azure-ad-2nna</guid>
      <description>&lt;p&gt;I have to admit, this was a weird and tough one. All I wanted to do was run an ASP.NET Razor Pages app inside a container using Https and Azure Active Directory authentication. Well, this was definitely a fun one to solve. In this blog post I'll show you exactly how to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;export the .NET Dev certs to use with Docker&lt;/li&gt;
&lt;li&gt;configure the Azure AD authentication&lt;/li&gt;
&lt;li&gt;configure the SameSite cookie policy in .NET&lt;/li&gt;
&lt;li&gt;configure Docker to use the dev-certs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Export the .NET Dev certs
&lt;/h3&gt;

&lt;p&gt;In order to be able to work in local dev with Docker and HTTPS we need a certificate. And the easiest way to get a cert is to use the .NET dev certs - they are free and available. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: this should only be used for local Dev to unblock certain scenarios&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open your favorite terminal and type the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet dev-certs https --clean
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p &amp;lt;your secret&amp;gt;

### If you're using PowerShell, then you have to use the following command instead
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetapp.pfx -p &amp;lt;your secret&amp;gt;

dotnet dev-certs https --trust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure the ASP.NET Core Web App
&lt;/h3&gt;

&lt;p&gt;By default, ASP.NET Core website have HSTS and HTTPS redirection enabled. This means that when running the application, it will expect and redirect all requests to the TLS-enabled port. I like to set mine to the standard &lt;code&gt;5001&lt;/code&gt; since .NET 6 and 7 are now randomizing the app ports. You can change the default ports in the &lt;code&gt;Properties\launchSettings.json&lt;/code&gt; file. This is what mine looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:43362",
      "sslPort": 44382
    }
  },
  "profiles": {
    "AzureADAuthInDocker": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000;https://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;Implement the necessary authentication, you need to add the following NuGet packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft.Identity.Web &lt;/li&gt;
&lt;li&gt;Microsoft.Identity.Web.UI &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;code&gt;appsettings.json&lt;/code&gt; file add the following &lt;strong&gt;AzureAD&lt;/strong&gt; specific settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "&amp;lt;your Azure AD tenant name&amp;gt;.onmicrosoft.com",
    "TenantId": "&amp;lt;your Azure AD tenant ID&amp;gt;",
    "ClientId": "&amp;lt;your Azure AD App Registration client ID&amp;gt;",
    "CallbackPath": "/signin-oidc"
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;program.cs&lt;/code&gt; add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddAuthorization(options =&amp;gt;
{
    // By default, all incoming requests will be authorized according to the default policy.
    options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages()
    .AddMicrosoftIdentityUI();


// code ommitted

app.UseAuthentication();
app.UseAuthorization();

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

&lt;/div&gt;



&lt;p&gt;At this point you can run the application locally using &lt;code&gt;dotnet run&lt;/code&gt; and if everything has been configured correctly, you should be prompted to authenticate with your organizational (Azure AD) account&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Cookie Policy
&lt;/h3&gt;

&lt;p&gt;If you plan on using Cookies in your solution, then you need to add a cookie policy. In &lt;code&gt;Program.cs&lt;/code&gt; above the authentication settings, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.Configure&amp;lt;CookiePolicyOptions&amp;gt;(
    options =&amp;gt;
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context =&amp;gt; true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
        options.Secure = CookieSecurePolicy.Always;
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, just above the &lt;code&gt;app.UseAuthentication()&lt;/code&gt; you need to add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseCookiePolicy();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the application and test that everything's working as expected!&lt;/p&gt;

&lt;p&gt;If you get a cookie error as per below, make sure you have the right settings. Check everything and try again:&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%2Fjbnxd3t20x4be88ls6gj.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%2Fjbnxd3t20x4be88ls6gj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Docker for our web app
&lt;/h3&gt;

&lt;p&gt;There are some prerequisites when it comes to working with Docker, namely that you need to have Docker Desktop installed and WSL2 enabled if you want to use Linux containers. Make sure to have these installed correctly.&lt;/p&gt;

&lt;p&gt;When it comes to creating the Docker files, I like to lean on VS Code to do the heavy lifting for me. You can find the information on how to set things up for your ASP.NET app &lt;a href="https://code.visualstudio.com/docs/containers/quickstart-aspnet-core" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the appropriate Docker commands from the VS Code pallette, should generate the following 3 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;docker-compose.yml&lt;/li&gt;
&lt;li&gt;docker-compose.debug.yml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I left my &lt;code&gt;Dockerfile&lt;/code&gt; mostly unchanged apart from the &lt;strong&gt;ENV ASPNETCORE_URLs&lt;/strong&gt; value which I updated to: &lt;code&gt;http://+:5000;https://+:5001&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;docker-compose.yml&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.4'

services:
  azureadauthindocker:
    image: azureadauthindocker
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 5000:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, the bulk of the changes took place in the &lt;code&gt;docker-compose.debug.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Please refer https://aka.ms/HTTPSinContainer on how to setup an https developer certificate for your ASP .NET Core service.

version: '3.4'

services:
  azureadauthindocker:
    image: azureadauthindocker
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 5000:5000
      - 5001:5001
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:5001;http://+:5000
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
      - ASPNETCORE_Kestrel__Certificates__Default__Password=&amp;lt;your secret&amp;gt;
    volumes:
      - ~/.vsdbg:/remote_debugger:rw
      - C:\Users\chmatsk\.aspnet\https:/https/:ro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these changes, I can run my web app inside Docker directly from VS Code. &lt;/p&gt;

&lt;p&gt;And this is an example with everything working end-to-end&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%2Fb1af766lnggl73m43nur.gif" 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%2Fb1af766lnggl73m43nur.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to run the container from the command line, then this is the command you need to use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it -p 5000:5000 -p 5001:5001 -e ASPNETCORE_URLS="https://+:5001;http://+:5000" -e ASPNETCORE_HTTPS_PORT=5001 -e ASPNETCORE_Kestrel__Certificates__Default__Password="&amp;lt;your secret&amp;gt;" -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx -v C:\Users\chmatsk\.aspnet\https:/https/ &amp;lt;your image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this command should produce the following output and your website should be accessible on &lt;code&gt;https://localhost:5001&lt;/code&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%2Fuploads%2Farticles%2Fsxw2nh6ej4q25b0haukq.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%2Fsxw2nh6ej4q25b0haukq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reach out if you have any questions!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>docker</category>
      <category>dotnet</category>
      <category>security</category>
    </item>
    <item>
      <title>Azure Functions, Azure AD B2C and Python</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Fri, 04 Mar 2022 01:45:30 +0000</pubDate>
      <link>https://dev.to/425show/azure-functions-azure-ad-b2c-and-python-876</link>
      <guid>https://dev.to/425show/azure-functions-azure-ad-b2c-and-python-876</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/app-service/overview-authentication-authorization" rel="noopener noreferrer"&gt;Azure App Authentication&lt;/a&gt; (aka Eazy Auth) has been around for a while and it's a great turnkey solution for implementing authentication for your Azure Web Apps, APIs and Azure Functions.&lt;/p&gt;

&lt;p&gt;There are, as with every technology, certain limitations. For example, you can't implement complex logic or do token validation and, in some cases, you need to write some code if you want to interact with the authenticated context. But if you want an ON/OFF solution that can quickly secure your Azure-based apps, then App Authentication is the solution!&lt;/p&gt;

&lt;p&gt;In this blog post I'll show you how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure App Authentication with Azure AD B2C&lt;/li&gt;
&lt;li&gt;How to retrieve and interact with the B2C Access Token&lt;/li&gt;
&lt;li&gt;All of the above in Python!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a local Azure Function
&lt;/h2&gt;

&lt;p&gt;I'll spare you the trouble of taking you through the steps in creating the boilerplate Azure Function. There is a great &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-python?tabs=azure-cli%2Cbash%2Cbrowser" rel="noopener noreferrer"&gt;Quickstart&lt;/a&gt; in our official docs&lt;/p&gt;

&lt;p&gt;Once you have the Function created, open the &lt;code&gt;requirements.txt&lt;/code&gt; and add the following package: &lt;code&gt;python-jose&lt;/code&gt;. This &lt;a href="https://pypi.org/project/python-jose/" rel="noopener noreferrer"&gt;library&lt;/a&gt; is excellent for working with JWTs. &lt;/p&gt;

&lt;p&gt;Then, open the &lt;code&gt;__init__.py&lt;/code&gt; file and update the code to look like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import logging
from jose import jwt
import azure.functions as func
import json

token=None

def main(req: func.HttpRequest) -&amp;gt; func.HttpResponse:

    logging.info('Python HTTP trigger function processed a request.')

    auth = req.headers.get("Authorization", None)
    if not auth:
        return func.HttpResponse(
             "Authentication error: Authorization header is missing",
             status_code=401
        )
    parts = auth.split()

    if parts[0].lower() != "bearer":
        return func.HttpResponse("Authentication error: Authorization header must start with ' Bearer'", 401)
    elif len(parts) == 1:
        return func.HttpResponse("Authentication error: Token not found", 401)
    elif len(parts) &amp;gt; 2:
        return func.HttpResponse("Authentication error: Authorization header must be 'Bearer &amp;lt;token&amp;gt;'", 401)

    token_claims = jwt.get_unverified_claims(parts[1])

    # Do anything else you need here

    return func.HttpResponse(json.dumps(token_claims, indent=4))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code checks for an &lt;code&gt;Authorization&lt;/code&gt; header and then, it either returns an error message if something is wrong, or parses the claims and dumps them back in the HTTP response. Since we're not using Azure AD but Azure AD B2C, the standard &lt;a href="https://docs.microsoft.com/azure/app-service/configure-authentication-oauth-tokens#retrieve-tokens-in-app-code" rel="noopener noreferrer"&gt;App Authentication&lt;/a&gt; headers don't apply. The access token will be passed in the &lt;strong&gt;Authorization&lt;/strong&gt; header with the expected value of &lt;code&gt;Bearer &amp;lt;token&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Function done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the B2C application registration
&lt;/h2&gt;

&lt;p&gt;In the Azure AD B2C, head to &lt;strong&gt;App Registrations&lt;/strong&gt; and hit the &lt;strong&gt;New Registration&lt;/strong&gt; button at the very top. Give it a meaningful name and press &lt;strong&gt;Register&lt;/strong&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%2Fuploads%2Farticles%2Fhrb4fpjyda4w1kkt8a4z.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%2Fhrb4fpjyda4w1kkt8a4z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head over to the &lt;strong&gt;Expose an API&lt;/strong&gt; tab and click on the &lt;strong&gt;Set&lt;/strong&gt; &lt;code&gt;Application ID URI&lt;/code&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%2Fuploads%2Farticles%2Fuy0386p2qkko4stlwq6t.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%2Fuy0386p2qkko4stlwq6t.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Final step, add a new scope. Give it a name such as &lt;code&gt;access_as_user&lt;/code&gt; and the message for the admin consent and click the &lt;strong&gt;Add Scope&lt;/strong&gt; button&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%2F6nmaf4v3fifwbuaac0qc.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%2F6nmaf4v3fifwbuaac0qc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this is B2C, you also need a SignUp/SignIn policy. You can follow the steps in this &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-sign-up-and-sign-in-policy?pivots=b2c-user-flow" rel="noopener noreferrer"&gt;document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is one more piece of information we need to complete the process in B2C. Head to the &lt;strong&gt;Overview&lt;/strong&gt; tab of the App Registration you just created and grab the well known endpoint from the &lt;strong&gt;Endpoints&lt;/strong&gt; tab!&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%2Fp91z4fib8kmb72wqu9c3.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%2Fp91z4fib8kmb72wqu9c3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, the information we need to configure our Azure Function Authentication is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ClientID&lt;/strong&gt;: your app registration client id&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TenantID&lt;/strong&gt;: your tenant ID&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The well known URL&lt;/strong&gt;: this is for JWT information&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up Eazy Auth in the Azure Function App
&lt;/h2&gt;

&lt;p&gt;The App Service Authentication can be set up through the CLI etc, but for the purpose of this blog, we'll use the Azure Portal. In the Azure Function App, navigate to the Authentication Tab and click on the &lt;strong&gt;Add New Authentication&lt;/strong&gt; button&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%2Fs589rhcu2r8ogq9hfwsq.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%2Fs589rhcu2r8ogq9hfwsq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next window, add the following details&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identity Provider: Microsoft&lt;/li&gt;
&lt;li&gt;App Registration Type: Provide the details of an existing app registration&lt;/li&gt;
&lt;li&gt;Application ID: the API App Registration Client ID&lt;/li&gt;
&lt;li&gt;Issuer URL: The Azure AD B2C Well Known endpoint&lt;/li&gt;
&lt;li&gt;Allowed Token Audiences: your API App Registration Client ID&lt;/li&gt;
&lt;li&gt;Restrict Access: Require Authentication&lt;/li&gt;
&lt;li&gt;Unauthenticated requests: HTTP 401&lt;/li&gt;
&lt;/ul&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%2Fodyk0j5fhu2fwuu862i3.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%2Fodyk0j5fhu2fwuu862i3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this information, the Azure Function App will require an Access Token to be passed in the HTTP request in the Authorization Header. If no token is available or the token is invalid, an HTTP 401 will be returned to the client&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;You can find the source code for this blog post on &lt;a href="https://github.com/425show/JWTClaimsInPythonAzFunctions" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>security</category>
      <category>azure</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Securing a .NET Azure Function with Azure AD</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Tue, 25 Jan 2022 23:39:07 +0000</pubDate>
      <link>https://dev.to/425show/securing-a-net-azure-function-with-azure-ad-31da</link>
      <guid>https://dev.to/425show/securing-a-net-azure-function-with-azure-ad-31da</guid>
      <description>&lt;p&gt;Last week I was asked by someone in the community for a sample that shows how to secure Azure Functions with Azure AD. And specifically, a .NET 5 or 6 Azure Function using the &lt;a href="https://github.com/AzureAD/microsoft-identity-web" rel="noopener noreferrer"&gt;Microsoft.Identity.Web&lt;/a&gt; library to validate tokens and authorize access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the video
&lt;/h2&gt;

&lt;p&gt;If you want to watch the 1hr video that shows you how to do it end-to-end, it's available on YouTube&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WRBXxyT70h4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Grab the code
&lt;/h2&gt;

&lt;p&gt;The sample project from the stream is available to clone from &lt;a href="https://github.com/425show/SecureAzureFunctionMiW" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You need an Azure Subscription &lt;a href="https://azure.microsoft.com/free" rel="noopener noreferrer"&gt;Get it free here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An Azure Active Directory &lt;a href="https://aka.ms/425Show/devenv" rel="noopener noreferrer"&gt;Free M365 Developer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;.NET 6 &lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/6.0" rel="noopener noreferrer"&gt;Download here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Identity extension tool for the .NET Core command line&lt;/li&gt;
&lt;li&gt;Azure Functions Core Tools &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v4%2Cwindows%2Ccsharp%2Cportal%2Cbash#install-the-azure-functions-core-tools" rel="noopener noreferrer"&gt;Install instructions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Known issues
&lt;/h2&gt;

&lt;p&gt;At the time of writing this, there is a known issue with .NET 6, Azure Functions **v4 and Microsoft.Identity.Web. Therefore, only the magic combination of the libries/NuGet packages mentioned in this blog/video work. The team is aware and working on a fix. What's the magic combo you ask? Your Azure Functions &lt;code&gt;csproj&lt;/code&gt; file should have these dependencies (hardcode the version!)&lt;/p&gt;

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

&amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" /&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" /&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.Identity.Web" Version="1.5.1" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create the project
&lt;/h2&gt;

&lt;p&gt;The easiest way to get started is to use the .NET command line with the M.I.W extension (check the prereqs ^^^^). Open your favorite terminal and run the following command&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mkdir &amp;lt;your directory name&amp;gt;
cd &amp;lt;your directory name&amp;gt;
dotnet new func2 --auth SingleOrg


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

&lt;/div&gt;

&lt;p&gt;This will create the files we need and implement the necessary middleware code. &lt;/p&gt;

&lt;p&gt;First thing we need to do is open the &lt;code&gt;*.csproj&lt;/code&gt; file and update it to look like this:&lt;/p&gt;

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

&amp;lt;Project Sdk="Microsoft.NET.Sdk"&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net6.0&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;AzureFunctionsVersion&amp;gt;v4&amp;lt;/AzureFunctionsVersion&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" /&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" /&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.Identity.Web" Version="1.5.1" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;None Update="host.json"&amp;gt;
      &amp;lt;CopyToOutputDirectory&amp;gt;PreserveNewest&amp;lt;/CopyToOutputDirectory&amp;gt;
    &amp;lt;/None&amp;gt;
    &amp;lt;None Update="local.settings.json"&amp;gt;
      &amp;lt;CopyToOutputDirectory&amp;gt;PreserveNewest&amp;lt;/CopyToOutputDirectory&amp;gt;
      &amp;lt;CopyToPublishDirectory&amp;gt;Never&amp;lt;/CopyToPublishDirectory&amp;gt;
    &amp;lt;/None&amp;gt;
    &amp;lt;None Update="appsettings.json"&amp;gt;
      &amp;lt;CopyToOutputDirectory&amp;gt;PreserveNewest&amp;lt;/CopyToOutputDirectory&amp;gt;
    &amp;lt;/None&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;This will update the Azure Functions runtime to v4, set the target framework to .NET 6 and then pin the NuGet packages to the versions that work!&lt;/p&gt;

&lt;p&gt;That's all the changes we have to implement in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Azure Active Directory
&lt;/h2&gt;

&lt;p&gt;The Azure function is already configured to expect authenticated calls. Out of the box, since we used the M.I.W extension, there is also an API permission that we need to configure. Now, you can go ahead and set up Azure AD manually, or you can use the nifty &lt;a href="https://github.com/425show/SecureAzureFunctionMiW/blob/main/aad-setup.ipynb" rel="noopener noreferrer"&gt;.NET Notebook&lt;/a&gt; in the project to programmatically set up everything for you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Configure the Azure AD settings in the Function project
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;appsettings.json&lt;/code&gt; and add the App Registration information that was in the output of the Notebook from the previous step. Your &lt;code&gt;appsettings.json&lt;/code&gt; should look like this:&lt;/p&gt;

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

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "&amp;lt;your ad domain name&amp;gt;.onmicrosoft.com",
    "TenantId": "&amp;lt;your tenant id&amp;gt;",
    "ClientId": "&amp;lt;your API Client Id&amp;gt;",
    "CallbackPath": "/signin-oidc"
  },
 "Logging": {
   "LogLevel": {
     "Default": "Information",
     "Microsoft": "Warning",
     "Microsoft.Hosting.Lifetime": "Information"
   }
  }
}


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

&lt;/div&gt;

&lt;p&gt;Save and close! You are now ready to run the Azure Function! In your terminal, type &lt;code&gt;func host start&lt;/code&gt;. You should be presented with the following output that indicates that your Azure Function is up and running:&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%2Fec1o38dsv3akabdkuzty.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%2Fec1o38dsv3akabdkuzty.png" alt="A running azure function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default endpoint to call the API is: &lt;code&gt;http://localhost:7071/api/SampleFunc&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How does authentication work in this code?
&lt;/h2&gt;

&lt;p&gt;Firstly, in &lt;code&gt;Startup.cs&lt;/code&gt; we configure our authentication middleware in the &lt;code&gt;ConfigureServices()&lt;/code&gt; method with the following code:&lt;/p&gt;

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

services.AddAuthentication(sharedOptions =&amp;gt;
{
    sharedOptions.DefaultScheme = Microsoft.Identity.Web.Constants.Bearer;
    sharedOptions.DefaultChallengeScheme = Microsoft.Identity.Web.Constants.Bearer;
})
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));


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

&lt;/div&gt;

&lt;p&gt;Then, inside the Function code, first we make sure that we have an authenticated request, i.e. we look for an auth header with &lt;code&gt;Bearer tokenstring&lt;/code&gt; value. If there is no Auth header, the code will generate an HTTP 401 error. Secondly, we check the token claims to ensure that the user has the right api permission, in this instance &lt;code&gt;access_as_user&lt;/code&gt;. If a valid token with the wrong permission or missing permissions is presented, the code will return a 403 error back to the client. If a valid token and the right permissions are present, the code executes as expected. The code that does this is here:&lt;/p&gt;

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

var (authenticationStatus, authenticationResponse) =
   await req.HttpContext.AuthenticateAzureFunctionAsync();
if (!authenticationStatus) return authenticationResponse;
        req.HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Auth attributes (a la ASP.NET) are supported but currently ignored. There will be a fix soon to fully support method-level attributes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Call the Azure Function from your client
&lt;/h2&gt;

&lt;p&gt;Whichever client you use, you need to make sure that you can authenticate and get an Access Token to pass to your Azure Function. I use Thunder Client, which is a VS Code extension. These are my settings:&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%2Fx9uu5izl720mhlx4jk5k.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%2Fx9uu5izl720mhlx4jk5k.png" alt="Thunder Client settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now call our Function from our client. If everything was setup correctly, we should receive an HTTP 200 with a response that contains a greeting with the name of the signed in user.&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%2Ffwnzhokgakrui0faf6u6.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%2Ffwnzhokgakrui0faf6u6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have an HTTP endpoint built with .NET 6 and Azure Functions, all secured with Azure Active Directory in 3 lines of code! &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;There may still be a few small issues with the Microsoft.Identity.Web library and Azure Functions, but if you're willing to take a hard dependency on a couple of NuGet packages, then you get a lot for free using the out of the box tools. As always, make sure to reach out to us via &lt;a href="//425.show/discord"&gt;Discord&lt;/a&gt; or email us at &lt;a href="mailto:425Show@microsoft.com"&gt;425Show@microsoft.com&lt;/a&gt; if you have any questions! &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>serverless</category>
      <category>azure</category>
    </item>
    <item>
      <title>Open Standards, Security, Azure AD and AWS</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Fri, 05 Nov 2021 01:45:29 +0000</pubDate>
      <link>https://dev.to/425show/open-standards-security-azure-ad-and-aws-4j8m</link>
      <guid>https://dev.to/425show/open-standards-security-azure-ad-and-aws-4j8m</guid>
      <description>&lt;p&gt;One of the things we always talk about as Microsoft Identity Dev Advocates, is the openness and interoperability of our platform. You'll often hear me say: "any platform, any language" and that extends to tools and libraries.&lt;/p&gt;

&lt;p&gt;For example, in the past 12 months, we worked closely with the JetBrain team to bring Azure AD integration in the Rider and IntelliJ IDEs to ensure that developers can successfully implement authentication and authorization in their applications directly from their favorite IDE. &lt;/p&gt;

&lt;p&gt;Anything that can or should work with Azure AD is a fair game for me. So you can imagine how excited I got when I saw the awesome new library ( &lt;a href="https://github.com/awslabs/aws-jwt-verify"&gt;aws-jwt-verify&lt;/a&gt;) from the AWS that could perform token validation with 1st and 3rd party Identity Providers. So I got to work and built a Node.js app to test the library...&lt;/p&gt;

&lt;p&gt;Unfortunately, my first attempt to build a working sample failed because there was a small issue with the library. The &lt;code&gt;alg&lt;/code&gt; claim was expected in the JWT header but Azure AD omits it because it's marked is an optional field as per &lt;a href="https://datatracker.ietf.org/doc/html/rfc7517#section-4.4"&gt;RFC 7517&lt;/a&gt;. Sinc the library is open source, we jumped to the repo to let the team know. I also gave them a polite nudge on Twitter to ensure that we got some eyeballs.&lt;/p&gt;

&lt;p&gt;The team was quick to respond and within a few days we got a fix! The library works flawlessly now with Azure AD so if you're building an application that needs to verify (Azure AD) tokens, now you have a new library to work with. &lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Azure AD App Registrations
&lt;/h2&gt;

&lt;p&gt;Since this example builds on a previous blog post, check out the &lt;strong&gt;Create the Azure AD App Registrations&lt;/strong&gt; section &lt;a href="https://dev.to/425show/secure-apis-using-node-js-azure-ad-cosmos-db-and-the-azure-sdks-4e4i"&gt;here&lt;/a&gt;. At some point I'll provide you with a Python/.NET Notebook to do this programmatically too :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the secure Node API
&lt;/h2&gt;

&lt;p&gt;Open your favorite terminal and type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir &amp;lt;your-project-name&amp;gt;
cd &amp;lt;your-project-name&amp;gt;
npm init -y
npm install aws-jwt-verify
npm install body-parser
npm install express
npm install --save-dev @types/node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create 2 files: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index.ts&lt;/li&gt;
&lt;li&gt;tsconfig.json&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the project in code with &lt;code&gt;code .&lt;/code&gt; and edit the &lt;code&gt;tsconfig.json&lt;/code&gt; file to add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "compilerOptions": {
        "target":"esnext",
        "sourceMap": true,
        "module": "esnext",
        "outDir": "out",
        "moduleResolution": "node",
        "allowSyntheticDefaultImports":true
    },
    "exclude": [
        "node_modules"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we're ready to add the code for our API. Open the &lt;code&gt;index.ts&lt;/code&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { JwtRsaVerifier } from "aws-jwt-verify";
import express from 'express';
import bodyParser from 'body-parser';

const SERVER_PORT = process.env.PORT || 8000;
const readOnlyScope: Array&amp;lt;string&amp;gt; = ["access_as_reader"];
const readWriteScope: Array&amp;lt;string&amp;gt; = ["access_as_writer"];
let accessToken;

const config = {
    auth: {
        clientId: "c7639087-cb59-4011-88ed-5d535bafc525",
        authority: "https://login.microsoftonline.com/e801a3ad-3690-4aa0-a142-1d77cb360b07",
        jwtKeyDiscoveryEndpoint: "https://login.microsoftonline.com/common/discovery/keys"
    }
};

const verifier = JwtRsaVerifier.create({
    tokenUse: "access",
    issuer: `${config.auth.authority}/v2.0`,
    audience: config.auth.clientId,
    jwksUri: config.auth.jwtKeyDiscoveryEndpoint
  });

const validateJwt = async (req, res, next) =&amp;gt; {
    const authHeader = req.headers.authorization;
    if (authHeader) {
        const token = authHeader.split(' ')[1];

        try {
            const payload = await verifier.verify(token);
            console.info("Token is valid.");
            accessToken = payload;
            next();
        } catch {
            console.error("Token not valid!");
            return res.sendStatus(401);
        }
    } else {
        res.sendStatus(401);
    }
};

function confirmRequestHasTheRightScope(scopes:Array&amp;lt;string&amp;gt;): boolean{
    const tokenScopes:Array&amp;lt;string&amp;gt; = accessToken.scp.split(" ");
    scopes.forEach(scope =&amp;gt; {
        if(!tokenScopes.includes(scope)){
            return false;
        }
    });
    return true;
}

// Create Express App and Routes
const app = express();
app.use(bodyParser.json());

app.get('/', (req, res)=&amp;gt;{
    var data = {
        "endpoint1": "/read",
        "endpoint2": "/write"
    };
    res.send(data); 
})

app.get('/read', validateJwt, (req, res) =&amp;gt; {
    if(!confirmRequestHasTheRightScope(readOnlyScope)){
        res.status(403).send("Missing or invalid scope");
    };
    var data ={
        "message": "Congratulations - you read some data securely"
    }
    res.status(200).send(data);
});

app.get('/write', validateJwt, (req, res) =&amp;gt; {
    if(!confirmRequestHasTheRightScope(readWriteScope)){
        res.status(403).send("Missing or invalid scope");
    };
    var payload = JSON.stringify(req.body);
    res.status(200).send(payload);
});

app.listen(SERVER_PORT, () =&amp;gt; console.log(`Secure Node API is listening on port ${SERVER_PORT}!`))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API provides 3 endpoints&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; (insecure)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/read&lt;/code&gt; (secure | requires a read-only scope)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/write&lt;/code&gt; (secure | requires a read-write scope)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;config&lt;/code&gt; object contains the necessary information for the &lt;code&gt;verifier&lt;/code&gt; to be able to validate the authenticity and validity of the incoming token. Things like the &lt;code&gt;authority&lt;/code&gt; and &lt;code&gt;audience&lt;/code&gt; of the token ensuring that the token was issued by the right Azure AD tenant and it's for the right audience (i.e. our API). Without these checks, an attacker could pass any valid Azure AD token to our API.&lt;/p&gt;

&lt;p&gt;The instantiation of the &lt;code&gt;verifier&lt;/code&gt; is extremely simple, although there are &lt;a href="https://github.com/awslabs/aws-jwt-verify#cognitojwtverifier-verify-parameters"&gt;more options&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const verifier = JwtRsaVerifier.create({
    tokenUse: "access",
    issuer: `${config.auth.authority}/v2.0`,
    audience: config.auth.clientId,
    jwksUri: config.auth.jwtKeyDiscoveryEndpoint
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;config&lt;/code&gt; object to populate the necessary options and set the verifier to only accept Access tokens with the &lt;code&gt;tokenUse&lt;/code&gt; option. Once we instantiate the verifier, we can call the &lt;code&gt;.verify(token);&lt;/code&gt; method to validate the passed token. I chose to implement a middleware function to do the token validation :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;

&lt;p&gt;You can find the full source code from this blog post on &lt;a href="https://github.com/425show/VerifyAzureADTokensWithAWSLib"&gt;GitHub&lt;/a&gt;. And if you want a more complex example where we show you how to securely call some Azure Services such as Key Vault, Cosmos DB and Azure Storage, check out this &lt;a href="https://github.com/cmatskas/SecureNodeAPIWithAAD/tree/aws_jwt_verify"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This blog post is a testament of what Open Source and open standards can achieve. The ability to use the language, tools and libraries of your choice to achieve your goals is great and I, for one, am truly excited that I get to do this every day. I also want to give a big shoutout to the AWS dev team (such as &lt;a href="https://twitter.com/ottokruse"&gt;ottokruse&lt;/a&gt; ) that worked on this library for their openness to work with us to make the library truly interoperable. Here's to more collaborations!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Encrypt/decrypt data with .NET 6 and Azure Key Vault</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Wed, 27 Oct 2021 18:48:31 +0000</pubDate>
      <link>https://dev.to/425show/encryptdecrypt-data-with-net-6-and-azure-key-vault-oak</link>
      <guid>https://dev.to/425show/encryptdecrypt-data-with-net-6-and-azure-key-vault-oak</guid>
      <description>&lt;p&gt;Security is hard. It's hard because there are so many things that can go wrong along the way. Attackers only need to find one small gap to make it through whereas developers and IT Pros have to think about all the possible attack permutations and potential security vulnerabilities every step of the way. That's why we talk about &lt;a href="https://gomindsight.com/insights/blog/what-are-the-7-layers-of-security/" rel="noopener noreferrer"&gt;"security in layers"&lt;/a&gt; when it comes to building systems that handle &lt;del&gt;sensitive&lt;/del&gt; data. And unless you're creating static marketing pages, it's very likely that your solution will need to work with some data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where do I start?
&lt;/h2&gt;

&lt;p&gt;If you're running on Azure (or other cloud providers) there are tools to help you keep your data secure both at rest and in transit. This is great &lt;a href="https://docs.microsoft.com/en-us/azure/security/fundamentals/encryption-overview" rel="noopener noreferrer"&gt;document&lt;/a&gt; that can help you get a high level overview of Azure data security and encryption. And there are many more tools to help you lock down and tightly monitor access to your data: &lt;a href="https://docs.microsoft.com/en-us/azure/security-center/security-center-introduction" rel="noopener noreferrer"&gt;Azure Security Center&lt;/a&gt;, [Azure Advisor] and &lt;a href="https://docs.microsoft.com/en-us/azure/security/fundamentals/overview" rel="noopener noreferrer"&gt;more&lt;/a&gt; etc etc.&lt;/p&gt;

&lt;p&gt;In this blog post we're going to look at client data encryption/decryption using .NET and Azure key Vault. However, if you're not a .NET developer, the practices and ideas in this blog post are applicable and available to every language that's supported by the Azure SDK and since everything is a wrapper around our Azure REST API, you can even roll out your own libraries (if you decide to choose so)&lt;/p&gt;

&lt;p&gt;The main point of this blog post is to help developers implement a robust solution to encrypt/decrypt data without having to worry about the underlying cryptographic implementation. Therefore, instead of spending weeks or months learning how cryptography works (symmetric, asymmetric, recommended algorithms and hard maths), you delegate the work to a service like Azure Key Vault. This way, you have a reliable and scalable service to manage your keys and perform complex operation outside your code! And that's the key: removing sensitive operations from you code makes it more robust&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To be able to use the code in this solution you'll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Azure Subscription &lt;a href="https://azure.microsoft.com/free" rel="noopener noreferrer"&gt;get a FREE one&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An Azure Key Vault (&lt;a href="https://docs.microsoft.com/en-us/azure/key-vault/general/quick-create-cli" rel="noopener noreferrer"&gt;create one&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;.NET 6 &lt;a href="https://dotnet.microsoft.com/download/dotnet/6.0" rel="noopener noreferrer"&gt;Download&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;VS Code &lt;a href="https://code.visualstudio.com/Download" rel="noopener noreferrer"&gt;Download&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing we haven't discussed yet is that this solution &lt;strong&gt;requires internet access&lt;/strong&gt; to call into Key Vault. Consequently, if you have an on prem app that needs to run in isolation and not call into Azure, you'll need to look at equivalent, on prem solutions like HashiCorp Vault etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Account security and best practices
&lt;/h2&gt;

&lt;p&gt;Most developers when working with Azure tend to use their own accounts out of convenience. However, this is not ideal. Instead, they should use Service Principals with restricted access rights to only the necessary resources. When moving to production, the Azure.Identity library makes it extremely easy to switch to Managed Identities without changing the code. Security end-to-end.&lt;/p&gt;

&lt;p&gt;Let's create a Service Principal with the right permissions:&lt;/p&gt;

&lt;p&gt;Open your favorite terminal (that has the Azure CLI installed) or jump straight to Azure Cloud Shell and run the following commands:&lt;/p&gt;

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

az ad sp create-for-rbac -n "cm-keyvault-crypto" --role "Key Vault Crypto User"
az keyvault set-policy --name cm-identity-kv --object-id a4e0e9c6-c507-4449-a9c4-25243ef61fe9 --key-permissions decrypt encrypt list get
az login --service-principal -u 2ff15c46-97bd-424a-b97a-433c8e5640d7 -p &amp;lt;your secret&amp;gt; --tenant 72f988bf-86f1-41af-91ab-2d7cd011db47


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

&lt;/div&gt;

&lt;p&gt;The first command creates a service principal account and assigns it to Crypto user RBAC role. Although we will not be using RBAC for this example, it's recommended practice to assign the appropriate roles to your SPs. Also note that the default &lt;code&gt;az ad sp create-for-rbac&lt;/code&gt; command behavior will change and stop assigning &lt;strong&gt;Contributor&lt;/strong&gt; role by default - a great security measure going forward! Contributor is an overprivileged role and we want to avoid using such accounts for dev/test/prod.&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%2Fq2bk1l3dg3tmmnpqmqo6.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%2Fq2bk1l3dg3tmmnpqmqo6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second command assigns the appropriate Access Policies to Azure Key Vault to allow us retrieve keys to use for encryption/decryption. &lt;/p&gt;

&lt;p&gt;The final command signs in the Service Principal in the Azure CLI as we will be using this to provide credentials to our code. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's write some code
&lt;/h2&gt;

&lt;p&gt;For this solution we are going to use the .NET CLI and VS Code. In your terminal type the following:&lt;/p&gt;

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

dotnet new console -n EncryptDecryptSample
dotnet add package install Azure.Identity
dotnet add package Azure.Security.KeyVault.Keys -v 4.3.0-beta.2 


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

&lt;/div&gt;

&lt;p&gt;Open the project in VS Code with &lt;code&gt;code .&lt;/code&gt;. Now we can write the necessary code to encrypt and decrypt data. Update the &lt;code&gt;Program.cs&lt;/code&gt; file with the following code:&lt;/p&gt;

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

using System.Text;
using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;

// vault URL could be passed as a parameter
var KeyVaultUrl = "https://cm-identity-kv.vault.azure.net";
// using Azure AD to support secretless authentication to Azure Key Vault
var credentials = new ChainedTokenCredential(
                        new AzureCliCredential(),
                        new ManagedIdentityCredential()
                );

var client = new KeyClient(new Uri(KeyVaultUrl), credentials);

//this could be parametarized as you may wish to pass different keys for different operations
var keyName = "MyEncryptionKey";

//get the key (or create one on the fly - very unlikely in a production environment)
KeyVaultKey key;
try 
{
    key = await client.GetKeyAsync(keyName); 
} 
catch (RequestFailedException ex) when (ex.Status == 404) 
{
    key = await client.CreateRsaKeyAsync(new CreateRsaKeyOptions(keyName));
} 

//get the crypto client of the key
var cryptoClient = client.GetCryptographyClient(key.Name, key.Properties.Version);

//do the fun stuff
var plainText = "My secret message";
var byteData = Encoding.Unicode.GetBytes(plainText);

Console.WriteLine("Encrypting...");
var encryptedResult = await cryptoClient.EncryptAsync(EncryptionAlgorithm.RsaOaep, byteData);
Console.WriteLine($"Encrypted data: {Convert.ToBase64String(encryptedResult.Ciphertext)}");
Console.WriteLine("Decrypting...");
var decryptedResult = await cryptoClient.DecryptAsync(EncryptionAlgorithm.RsaOaep, encryptedResult.Ciphertext);
Console.WriteLine($"Decrypted data: {Encoding.Unicode.GetString(decryptedResult.Plaintext)}");


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

&lt;/div&gt;

&lt;p&gt;If the Service Principal is configured correctly then running the code with &lt;code&gt;dotnet run&lt;/code&gt; should yield the following output:&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%2Fe8aeiae8gqomx63esn5a.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%2Fe8aeiae8gqomx63esn5a.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the Key Vault permissions are wrong (they shouldn't be if you followed the instructions above and signed in with the right account), you may receive the following error:&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%2Fyza4yvkr7svmfqfa1zdb.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%2Fyza4yvkr7svmfqfa1zdb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code makes use of the Azure.Identity library to authenticate to Azure Key Vault and then instantiate a &lt;code&gt;KeyClient&lt;/code&gt; and a &lt;code&gt;CryptographyClient&lt;/code&gt; to perform the necessary operations. This way, we never have to use and Keys or Secrets to authenticate to Key Vault making our application even more secure. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: this code attempts to retrieve a key and, if not found, it creates a new one. The current Service Principal (as configured earlier) doesn't have the appropriate permission to create keys so the code will fail. We can either create a key using a more privileged account, or temporarily update the SP with a &lt;code&gt;Create&lt;/code&gt; permission. In real world scenarios, the IT Admins or Security team will be responsible for creating (and rolling) keys in Key Vault.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where is the code?
&lt;/h2&gt;

&lt;p&gt;You can grab the code from [this GitHub repo] - notice how it jumps straight to the (&lt;a href="https://github.dev/425show/EncryptDecryptDataWithKeyVault" rel="noopener noreferrer"&gt;https://github.dev/425show/EncryptDecryptDataWithKeyVault&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Application security is hard but we shouldn't be intimated by it, especially since, as developers we are spoiled for choice these days! Many of the hard problems that we had to solve in the past are now a service or product that we can easily pull off the shelf and add it to our solution. Therefore, if you need to encrypt/decrypt data in your application, you can now do it with less than 20 lines of code using Azure Key Vault backed by Azure AD. Let me know in the comments if you have any Qs :)&lt;/p&gt;

</description>
      <category>security</category>
      <category>azure</category>
      <category>cloud</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Working with Python Jupyter Notebooks and MS Graph in VS Code</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Tue, 28 Sep 2021 20:59:21 +0000</pubDate>
      <link>https://dev.to/425show/working-with-python-jupyter-notebooks-and-ms-graph-in-vs-code-4oog</link>
      <guid>https://dev.to/425show/working-with-python-jupyter-notebooks-and-ms-graph-in-vs-code-4oog</guid>
      <description>&lt;p&gt;Lately I find myself falling in love with Python more and more. It's simple, fast and super powerful. I know I'm late to the game but you know the saying: "better late than never" :)&lt;/p&gt;

&lt;p&gt;Since Python is my go-to language these days, I decided to use it to automate one of the mundane and tricky parts of working with Azure AD - creating an App Registration for app authentication. Every time you need to implement authentication and authorization in your applications, be it a web app, api, desktop, mobile etc, you need to register an app, or possibly multiple apps in Azure AD. This is how you create the 1:1 relationship between your code and Azure AD and where you also configure api permissions, flows etc. This can get tricky since there are multiple steps and missing one can break things. What if there was a way to automate all that and avoid human errors?&lt;/p&gt;

&lt;p&gt;Enter the world of MS Graph and Jupyter Notebooks. &lt;/p&gt;

&lt;h2&gt;
  
  
  Set up your environment
&lt;/h2&gt;

&lt;p&gt;You'll need to install the latest &lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;Python&lt;/a&gt;. I'm using Python 3.9.x and since I'm late to the game, I'm happy to avoid the whole 2v3 debacle. Straight to Python 3! &lt;/p&gt;

&lt;p&gt;In VS Code, you also want to install the following extensions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python" rel="noopener noreferrer"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter" rel="noopener noreferrer"&gt;Jupyter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter-keymap" rel="noopener noreferrer"&gt;Jupyter Keymap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance" rel="noopener noreferrer"&gt;Pylance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the project
&lt;/h2&gt;

&lt;p&gt;Crate a new directory and open it in VS Code. Here, we're going to create our Python virtual environment and install our dependencies. To create and activate a virtual environment, type the following commands:&lt;/p&gt;

&lt;p&gt;PS - I'm working on Windows so the commands are slightly different&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m venv .venv
.venv/scripts/activate.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll create a &lt;code&gt;requirements.txt&lt;/code&gt; file and add the following dependencies/packages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ipykernel&amp;gt;=6.4.1
msgraph-core&amp;gt;=0.2.2
azure-identity&amp;gt;=1.6.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this command to install the dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get prompted to upgrade your &lt;code&gt;pip&lt;/code&gt; to stop being pestered every time you run the pip command, now is a good time. In your terminal, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;path to your current directory&amp;gt;\.venv\scripts\python.exe -m pip install --upgrade pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can use the command palette to create a new Jupyter Notebook&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%2Fo5grq0qhqai9246ftyib.gif" 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%2Fo5grq0qhqai9246ftyib.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's write some MS Graph code
&lt;/h2&gt;

&lt;p&gt;To automate the Azure AD App Registration code, we can use MS Graph - the one API to rule them all! But before we write any code, we first need to.... register an app in Azure AD. Confused? I'm sure you are but let me break it down for you. To interact with Azure AD we need to be in an authenticated context. We need a way to authenticate as a user and consent to the right permissions so that we can programmatically configure Azure AD. And for this to happen, we need an App Registration. &lt;/p&gt;

&lt;p&gt;I have created a multitenant app registration so if you have the right permissions, you should be able to sign in with your own organizational account and run the notebook. However, if you need to create your own App Registration, then these are the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the browswer and navigate to your Azure AD Portal&lt;/li&gt;
&lt;li&gt;Navigate to App Registrations&lt;/li&gt;
&lt;li&gt;Create a new App Registration&lt;/li&gt;
&lt;li&gt;Navigate to the Authentication tab&lt;/li&gt;
&lt;li&gt;Add a new Platform&lt;/li&gt;
&lt;li&gt;Select Desktop and Mobile&lt;/li&gt;
&lt;li&gt;Set the Redirect Uri to Custom -&amp;gt; &lt;code&gt;http://localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save everything&lt;/li&gt;
&lt;li&gt;From the Overview tab, copy the Client ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now we can write some code :)&lt;/p&gt;

&lt;p&gt;In the first code segment of our Jupyter Notebook, we'll initialize our Graph client and set some variables to use later. Something that you may notice is that MS Graph now relies on the &lt;code&gt;Azure.Identity&lt;/code&gt; library, which is part of the Azure SDKs, for authenticating and acquiring tokens which is super neat!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from azure.identity import InteractiveBrowserCredential
from msgraph.core import GraphClient
import uuid
import json

browser_credential = InteractiveBrowserCredential(client_id='7537790f-b619-4d30-a804-1c6b8b7f1523')
graph_client = GraphClient(credential=browser_credential)
scopes = ['Application.ReadWrite.All', 'User.Read']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the next code segment, we'll create an API App Registration and set a custom API permission. Client apps should use this scope to call our API in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiAppName='automation - Python API'
apiIdentifier = f"api://{uuid.uuid4()}"
permissionId = f"{uuid.uuid4()}";

body = {
    'displayName': apiAppName,
    'identifierUris': [
        apiIdentifier           
    ], 
    'api': {
        'acceptMappedClaims': None,
        'knownClientApplications': [],
        'requestedAccessTokenVersion': 2,
        'oauth2PermissionScopes': [
            {
                'id': permissionId,
                'adminConsentDescription':'access the api as a reader',
                'adminConsentDisplayName':'access the api as a reader',
                'isEnabled': True,
                'type': 'User',
                'userConsentDescription': 'access the api as a reader',
                'userConsentDisplayName': 'access the api as a reader',
                'value':'api.read'
            }],
        'preAuthorizedApplications':[]
    }
}

result = graph_client.post('/applications',
                data=json.dumps(body),
                headers={'Content-Type': 'application/json'}
                )
appJson = json.dumps(result.json())
application = json.loads(appJson)

response = graph_client.get('/organization')
tenantJson = json.dumps(response.json())
tenant = json.loads(tenantJson)

print(f"Client Id: {application['appId']}")
print(f"Domain: {application['publisherDomain']}")
print(f"Tenant Id: {tenant['value'][0]['id']}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For your example, you'll have to change the &lt;code&gt;ApiAppName&lt;/code&gt; and &lt;code&gt;ApiPermission&lt;/code&gt; variable values to make them meaningful to you and you're ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me teh c0dez
&lt;/h2&gt;

&lt;p&gt;If you want to grab the Notebook and run it on your end, check out the &lt;a href="https://github.com/425show/PythonInteractiveGraphSample" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Secure Minimal APIs with .NET 6 and Azure AD B2C</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Wed, 08 Sep 2021 00:37:59 +0000</pubDate>
      <link>https://dev.to/425show/secure-minimal-apis-with-net-6-and-azure-ad-b2c-2cb9</link>
      <guid>https://dev.to/425show/secure-minimal-apis-with-net-6-and-azure-ad-b2c-2cb9</guid>
      <description>&lt;p&gt;Minimal APIs are all the rage these days. Python and Node.js have had a much simpler model for creating APIs for a while. And now .NET 6 joins this trend - which is a welcome change. I streamed about this on our &lt;a href="https://aka.ms/425Show" rel="noopener noreferrer"&gt;425Show Twitch channel&lt;/a&gt; so if you prefer video over text, you can watch all the action on our YouTube channel:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wvS4emg69VA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You'll need the following to follow along:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dotnet.microsoft.com/download/dotnet/6.0" rel="noopener noreferrer"&gt;.NET 6 Preview 7&lt;/a&gt; (as of writing this blog post)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/Download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; (or any other .NET IDE)&lt;/li&gt;
&lt;li&gt;And Azure AD B2C (as part of your Azure subscription - get a free one &lt;a href="https://azure.microsoft.com/free/" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the Azure AD B2C App
&lt;/h2&gt;

&lt;p&gt;We'll start by creating the two App Registrations needed for our API and our API client. In the Azure AD B2C portal, navigate to the &lt;strong&gt;App Registrations&lt;/strong&gt; blade and create a new one by clicking on the &lt;strong&gt;+ New Registration&lt;/strong&gt;. Give it a meaningful name, leave the default for &lt;strong&gt;Supported Account Types&lt;/strong&gt; and press &lt;strong&gt;Register&lt;/strong&gt;. In the newly created App Registration, navigate to the &lt;strong&gt;Expose an API&lt;/strong&gt; and Set the Application ID URI. &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%2Fw6agtzxr0or59wi9t1e4.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%2Fw6agtzxr0or59wi9t1e4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now add a &lt;strong&gt;Scope&lt;/strong&gt;. Since we'll be pulling weather data, we can use something like &lt;code&gt;Weather.Read&lt;/code&gt; for the scope name.&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%2Fg1ok1gxinvdeorkj7ag0.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%2Fg1ok1gxinvdeorkj7ag0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a note of the following information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application (Client) ID (App Registration Overview Tab)&lt;/li&gt;
&lt;li&gt;Azure AD B2C Instance name (e.g https://[YourB2CName].b2clogin.com)&lt;/li&gt;
&lt;li&gt;B2C Domain (e.g [YourB2CName].omicrosoft.com)&lt;/li&gt;
&lt;li&gt;User flow name (e.g B2C_1_susi)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Using Thunder Client in VS Code to test a secure API
&lt;/h2&gt;

&lt;p&gt;What good is it if we can't test/use our secure API? When I work with APIs, I like to use &lt;a href="https://www.thunderclient.io/" rel="noopener noreferrer"&gt;Thunder Client&lt;/a&gt;, a VS Code extension that provides a GUI based REST Client. Unlike Postman, I don't have to install it on every machine and it is available in CodeSpaces too! For Thunder Client to be able to call an Azure AD B2C secure API we we need a client API App Registration. Let's do this!&lt;/p&gt;

&lt;p&gt;Create a new App Registration, give it a meaningful name and press &lt;strong&gt;Register&lt;/strong&gt;. Then navigate to the &lt;strong&gt;Authentication&lt;/strong&gt; tab and press the &lt;strong&gt;+ Add a platform&lt;/strong&gt; button. Make sure to select &lt;strong&gt;Web&lt;/strong&gt; and add the following for the &lt;strong&gt;Redirect URI&lt;/strong&gt;: &lt;code&gt;https://www.thunderclient.io/oauth/callback&lt;/code&gt;. This is the URL that Thunder Client is expecting to receive the Access Token. &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%2Fw7zxb8xu0hrix8kfmxpj.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%2Fw7zxb8xu0hrix8kfmxpj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, navigate to the &lt;strong&gt;Certificates &amp;amp; Secrets&lt;/strong&gt; tab and create a new secret. Make sure to copy it as we'll need it to configure Thunder Client. &lt;/p&gt;

&lt;p&gt;Finally, we need to add our API permissions. Navigate to the &lt;strong&gt;API permissions&lt;/strong&gt; tab and press the &lt;strong&gt;Add a permission&lt;/strong&gt;. Select &lt;strong&gt;My APIs&lt;/strong&gt;, find the name of the App Registration you created at the previous step and select 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%2Fyb9r6ip4dhe4xp2eaiqp.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%2Fyb9r6ip4dhe4xp2eaiqp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Expand the permissions, select the name of your permission (in your case it should be &lt;code&gt;Weather.Read&lt;/code&gt;). Then press the &lt;strong&gt;Add Permission&lt;/strong&gt; button.&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%2F2dextsuvw8h17e60awqf.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%2F2dextsuvw8h17e60awqf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final, and most important, step in the process is to give  Admin Consent to our custom API Permission.&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%2Fydrhyjbtms5n3rthepl0.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%2Fydrhyjbtms5n3rthepl0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The information we need from this App Registration is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application (Client) ID (App Registration Overview Tab)&lt;/li&gt;
&lt;li&gt;Auth endpoint (e.g &lt;a href="https://cmatdevb2c.b2clogin.com/cmatdevb2c.onmicrosoft.com/YourB2CPolicyName/oauth2/v2.0/authorize" rel="noopener noreferrer"&gt;https://cmatdevb2c.b2clogin.com/cmatdevb2c.onmicrosoft.com/YourB2CPolicyName/oauth2/v2.0/authorize&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Token endpoint (e.g  &lt;a href="https://cmatdevb2c.b2clogin.com/cmatdevb2c.onmicrosoft.com/YourB2CPolicyName/oauth2/v2.0/token" rel="noopener noreferrer"&gt;https://cmatdevb2c.b2clogin.com/cmatdevb2c.onmicrosoft.com/YourB2CPolicyName/oauth2/v2.0/token&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Client Secret&lt;/li&gt;
&lt;li&gt;API Permission (e.g &lt;a href="https://cmatdevb2c.onmicrosoft.com/b332fc47-cfff-4f57-bb0f-7b6ccea75521/weather.read" rel="noopener noreferrer"&gt;https://cmatdevb2c.onmicrosoft.com/b332fc47-cfff-4f57-bb0f-7b6ccea75521/weather.read&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Thunder Client, create a new Request and navigate to the Auth tab, select OAuth2 and configure the settings as shown in the pic below:&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%2Fk5hkc9peh30yxtsijs1e.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%2Fk5hkc9peh30yxtsijs1e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
We can now test it out. If all is configured correctly, you should see the following:&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%2F3z5jyzm337bcs43208nz.gif" 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%2F3z5jyzm337bcs43208nz.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create and secure the minimal API
&lt;/h2&gt;

&lt;p&gt;Open your favorite terminal (mine is Windows Terminal) and type the following:&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 webapi --auth IndividualB2C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template does most of the work for us, but we can tweak the code to make it truly minimal! Update your &lt;code&gt;Program.cs&lt;/code&gt; to look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Identity.Web;
using Microsoft.Identity.Web.Resource;
using MinimalAPIWithB2C2;

string[] Summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration, "AzureAdB2C");

builder.Services.AddAuthorization();
builder.Services.AddCors(options =&amp;gt; options.AddPolicy("allowAny", o =&amp;gt; o.AllowAnyOrigin()));
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =&amp;gt;
{
    c.SwaggerDoc("v1", new() { Title = "MinimalAPIWithB2C2", Version = "v1" });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (builder.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c =&amp;gt; c.SwaggerEndpoint("/swagger/v1/swagger.json", "MinimalAPIWithB2C2 v1"));
}

app.MapGet("/weatherforecast",(HttpContext context) =&amp;gt; 
{
    context.VerifyUserHasAnyAcceptedScope(new[] {"access_as_user"});
    return Enumerable.Range(1, 5).Select(index =&amp;gt; new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    })
    .ToArray();
}).RequireAuthorization();

app.UseAuthentication();
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthorization();

app.MapControllers();

app.Run();

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

&lt;/div&gt;



&lt;p&gt;We can now delete the &lt;strong&gt;Controllers&lt;/strong&gt; folder and all it's contents. Finally, we need to update the &lt;code&gt;appsettings.json&lt;/code&gt; with the info we collected from the first step when we created the API App Registration. Your &lt;code&gt;appsettings.json&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "AzureAdB2C": {
    "Instance": "https://&amp;lt;yourB2CName&amp;gt;.b2clogin.com/tfp/",
    "ClientId": "&amp;lt;your client id&amp;gt;",
    "Domain": "&amp;lt;yourB2CName&amp;gt;.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_susi"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The policy name needs to match in both your API and your Thunder Client settings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's build and run the API so that we can test it :)&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then, let's switch to Thunder Client in VS Code and send a GET request to our API endpoint: &lt;code&gt;https://localhost:5001/weatherforecast&lt;/code&gt;. If everything was configured correctly, we should receive the following output from the API:&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%2Fexr07p3ycz67l52te3i9.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%2Fexr07p3ycz67l52te3i9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the Code!!
&lt;/h2&gt;

&lt;p&gt;If you want to go straight to the source code, check out our working sample in the &lt;a href="https://github.com/425show/minimalAPIWithB2C" rel="noopener noreferrer"&gt;425Show Github repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I really dig the new minimal API templates in .NET 6. And although this approach may not be for everyone, I can totally see the appeal. Also note that you don't have to stick with this design and you can refactor your code out to separate files to keep your files small and concise. Controllers are here to stay! In the end, it all comes down to personal preference and what works best for you and your team.   &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Calling an Azure AD secured API with Postman</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Thu, 02 Sep 2021 23:59:31 +0000</pubDate>
      <link>https://dev.to/425show/calling-an-azure-ad-secured-api-with-postman-22co</link>
      <guid>https://dev.to/425show/calling-an-azure-ad-secured-api-with-postman-22co</guid>
      <description>&lt;p&gt;Secure APIs are all the rage, but how can we easily test them. If you're using Postman, then this blog post will show you how to configure and use Postman to call an Azure AD-secured API.&lt;/p&gt;

&lt;p&gt;The secure API expects an access token to be passed. Therefore, Postman needs to acquire and use an Access Token when calling the API. If there is no token attached to the request, then you'll most likely receive an HTTP 401 error (unauthenticated) - which is right. If you pass an Access Token with your request but don't have the right scope, if your API has been coded correctly, you should receive an HTTP 403 error (unauthorized) - which is also right. Let's see how we can test our APIs with Postman!&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure the App Registration for Postman
&lt;/h2&gt;

&lt;p&gt;In order for Postman to be able to acquire an Access Token, it needs to have a corresponding Azure AD App Registration. In this section, we'll configure the App Registration in Azure AD. If you don't have an Azure AD already (I doubt it since you're reading this), you can get a FREE, full-blown P1 Azure AD Tenant through the &lt;a href="https://aka.ms/425Show/devevn" rel="noopener noreferrer"&gt;Microsoft 365 Developer Program&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sign in to your &lt;a href="//aad.portal.azure.com"&gt;Azure AD portal&lt;/a&gt;, navigate to &lt;strong&gt;App Registrations&lt;/strong&gt; and click on the &lt;strong&gt;+ New Registration&lt;/strong&gt; button. Give the app a meaningful name and press &lt;strong&gt;Register&lt;/strong&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%2Fuploads%2Farticles%2F2ox77mfdg495fb41shyu.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%2F2ox77mfdg495fb41shyu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, open the &lt;strong&gt;Authentication&lt;/strong&gt; tab and &lt;strong&gt;Add a platform&lt;/strong&gt;. Select &lt;strong&gt;Web&lt;/strong&gt; for the platform. In the &lt;strong&gt;Redirect URI&lt;/strong&gt; add the following &lt;code&gt;https://oauth.pstmn.io/v1/callback&lt;/code&gt; and then press &lt;strong&gt;Configure&lt;/strong&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%2Fuploads%2Farticles%2F1f0wbd8kpczq4xr0zfwn.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%2F1f0wbd8kpczq4xr0zfwn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need a client secret. Navigate to the &lt;strong&gt;Certificates and Secrets&lt;/strong&gt; tab and create a new secret. Make sure to copy the secret value as it will be unavailable once you navigate off this tab (but you can always delete it and recreate 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%2Foc37jzmqctbraccv4hru.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%2Foc37jzmqctbraccv4hru.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Information needed for Postman&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client Id: Can be found in the Overview Tab&lt;/li&gt;
&lt;li&gt;Client Secret: Was created and copied in the previous step&lt;/li&gt;
&lt;li&gt;Auth URL: In the Overview Tab, click on &lt;strong&gt;Endpoints&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Access Token URL: In the Overview Tab, click on &lt;strong&gt;Endpoints&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Scope: e.g &lt;code&gt;api://279cfdb1-18d5-4fd6-b563-291dcd4b561a/weather.read&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the right scope in your API App Registration in Azure AD -&amp;gt; open the &lt;strong&gt;Expose an API&lt;/strong&gt; tab -&amp;gt; Copy the &lt;strong&gt;Scope&lt;/strong&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%2Fuploads%2Farticles%2Fjonme1iz1uykonnjr1k2.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%2Fjonme1iz1uykonnjr1k2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the v2 URLs for the Authorization and Token endpoints as per the image below:&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%2Fcvduryqgaztv4192serw.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%2Fcvduryqgaztv4192serw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Postman
&lt;/h2&gt;

&lt;p&gt;We now have everything we need to configure our Auth settings in Postman. In your Postman, create a new Request and navigate to the &lt;strong&gt;Authorization&lt;/strong&gt; tab. Next populate the fields as shown in the image below, using all the settings we gathered in the previous section. &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%2Fq4gb3udoyova0doph47x.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%2Fq4gb3udoyova0doph47x.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you'll need to check the &lt;strong&gt;Authorize using browser&lt;/strong&gt; checkbox and ensure that your browser is not blocking any popups.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are now ready to test our configuration. Press the &lt;strong&gt;Get New Access Token&lt;/strong&gt; in Postman. If everything's configured correctly, you should see something similar as per the video below:&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%2Fvtta9gsqs737sfm7z9nh.gif" 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%2Fvtta9gsqs737sfm7z9nh.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now use Postman to call various API endpoints. Note that if you need different scopes for different parts of the API, you'll need to add them to the scopes which will need to be space delimited.&lt;/p&gt;

&lt;p&gt;Have fun securing and testing your APIs and make sure to join our &lt;a href="https://aka.ms/425Show/Discord/join" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; if you have any Identity or Azure related questions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Delete all users in an Azure AD Tenant programmatically</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Tue, 27 Jul 2021 00:33:17 +0000</pubDate>
      <link>https://dev.to/425show/delete-all-users-in-an-azure-ad-tenant-programmatically-3k33</link>
      <guid>https://dev.to/425show/delete-all-users-in-an-azure-ad-tenant-programmatically-3k33</guid>
      <description>&lt;p&gt;The first part of "deleting an Azure AD tenant programmatically" is here. Today, we're going to delete all Azure AD users (except our admin account). Me an JP streamed the whole process along with the steps necessary to achieve this, but you can always skip to the code or the blog post below:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LQUbSFjr2ds"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;.NET Core 3.1 (or later)&lt;/li&gt;
&lt;li&gt;An Azure AD B2C tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Azure AD App Registration
&lt;/h2&gt;

&lt;p&gt;To be able to interact with Azure AD, we need to create an App Registration. In Azure AD, got to &lt;strong&gt;App Registrations -&amp;gt; New Registration&lt;/strong&gt;. Give it a meaningful name and select &lt;strong&gt;multi-tenant&lt;/strong&gt; for supported account types. In the new App Registration, navigate to the &lt;strong&gt;Authentication&lt;/strong&gt; and &lt;strong&gt;Add a Platform&lt;/strong&gt;. Select &lt;strong&gt;Mobile &amp;amp; Desktop&lt;/strong&gt;, choose the URI that works best for you (I like the MSAL one) and then make sure to select the &lt;strong&gt;Enable Public Client Flows&lt;/strong&gt; option. Save this! Finally, we need to add and admin-consent to the necessary MS Graph permissions. In &lt;strong&gt;API Permissions&lt;/strong&gt; press the &lt;strong&gt;Add a permission&lt;/strong&gt; button, select &lt;strong&gt;Delegated permissions&lt;/strong&gt; and search for the &lt;code&gt;User.ReadWrite.All&lt;/code&gt; permission. Make sure to press the &lt;strong&gt;Add Permission&lt;/strong&gt; at the bottom of the window. &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%2Ferw30qlxi3ikegjrc35i.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%2Ferw30qlxi3ikegjrc35i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this is a Console app, we need to provide admin consent prior to authenticating. On the &lt;strong&gt;API Permissions&lt;/strong&gt; blade, press the &lt;strong&gt;Grant Admin consent for &lt;/strong&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%2Fuploads%2Farticles%2Ffti7j6s11uio0dqebqj2.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%2Ffti7j6s11uio0dqebqj2.png" alt="Alt Text"&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We are now ready to build our user deletion code...&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's write some code
&lt;/h2&gt;

&lt;p&gt;Our code needs to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate the current user (interactive auth)&lt;/li&gt;
&lt;li&gt;Retrieve all user objects in the directory&lt;/li&gt;
&lt;li&gt;Ensure we exclude our admin account (otherwise we lose access)&lt;/li&gt;
&lt;li&gt;batch up the delete operation and execute the batches. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open up your favorite Terminal and type:&lt;br&gt;
&lt;code&gt;dotnet new console -n tenant_deleter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also need to add a couple of NuGet packages to make our lives easier when interacting with Azure AD and MS Graph. In the Terminal, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.Graph
dotnet add package Microsoft.Identity.Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8bhm3svrkxkprh2e2ofs.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%2F8bhm3svrkxkprh2e2ofs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the project in your favorite code editor (I use VS Code) and add a new file: &lt;code&gt;MsalTokenProvider.cs&lt;/code&gt;. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Graph;
using Microsoft.Identity.Client;

namespace tenant_deleter
{
    // todo: stop building new MsalTokenProviders for every project
    public class MsalTokenProvider : IAuthenticationProvider
    {
        public readonly IPublicClientApplication _client;
        private readonly string[] _scopes = {
             "https://graph.microsoft.com/User.ReadWrite.All"
            };

        public MsalTokenProvider(string tenantId)
        {
            _client = PublicClientApplicationBuilder
               // mt app reg in separate tenant
               // todo: move to config
               .Create("&amp;lt;Your Azure AD App registration Client ID&amp;gt;")
               .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
               .Build();
        }

        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            AuthenticationResult token;
            try
            {
                // get an account ------ ??????
                var account = await _client.GetAccountsAsync();
                token = await _client.AcquireTokenSilent(_scopes, account.FirstOrDefault())
                    .ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                token = await _client.AcquireTokenWithDeviceCode(
                    _scopes,
                    resultCallback =&amp;gt;
                    {
                        Console.WriteLine(resultCallback.Message);
                        return Task.CompletedTask;
                    }

                ).ExecuteAsync();
            }
            request.Headers.Authorization =
                    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.AccessToken);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is responsible for signing in to Azure AD and acquiring the Access Token for MS Graph.&lt;/p&gt;

&lt;p&gt;Go back into &lt;code&gt;Program.cs&lt;/code&gt; to add the necessary code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Graph;

namespace tenant_deleter
{
    class Program
    {
        async static Task Main(string[] args)
        {
            string tenantId;
            if (args.Length &amp;lt; 1)
            {
                Console.WriteLine("gimme a tenant");
                tenantId = Console.ReadLine();
            }
            else
            {
                tenantId = args[0];
            }

            var graph = new GraphServiceClient(new MsalTokenProvider(tenantId));
            var td = new ThingDeleter(graph);
            await td.DeleteAllUsersFromTenant();
            Console.WriteLine("*fin*");
            Console.ReadLine();
        }
    }

    public class ThingDeleter
    {
        private readonly GraphServiceClient _graphServiceClient;
        public ThingDeleter(GraphServiceClient client)
        {
            _graphServiceClient = client;
        }

        // delete all users from tenant
        public async Task DeleteAllUsersFromTenant()
        {
            var me = await _graphServiceClient.Me.Request().Select(x =&amp;gt; x.Id).GetAsync();
            var users = await _graphServiceClient.Users.Request()
                .Select(x =&amp;gt; x.Id)
                .Top(20)
            .GetAsync();

            var batch = new BatchRequestContent();
            var currentBatchStep = 1;
            var pageIterator = PageIterator&amp;lt;User&amp;gt;
            .CreatePageIterator(
                _graphServiceClient,
                users,
                (user) =&amp;gt;
                {
                    if (user.Id == me.Id) return true; //don't delete me
                    var requestUrl = _graphServiceClient
                            .Users[user.Id]
                            .Request().RequestUrl;

                    var request = new HttpRequestMessage(HttpMethod.Delete, requestUrl);
                    var requestStep = new BatchRequestStep(currentBatchStep.ToString(), request, null);
                    batch.AddBatchRequestStep(requestStep);

                    if (currentBatchStep == users.Count)
                    {
                        _graphServiceClient.Batch.Request().PostAsync(batch).GetAwaiter().GetResult();
                        currentBatchStep = 1; // batches are 1-indexed, weird
                        return true;
                    }
                    currentBatchStep++;
                    return true;
                },
                (req) =&amp;gt;
                {
                    return req;
                }
            );
            await pageIterator.IterateAsync();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice that the Graph code uses batching to optimize the calls against MS Graph. This is necessary, especially for larger tenants with 1000s of users. The nice thing is that we can also parallelize this to make it ever more efficient :)&lt;/p&gt;

&lt;p&gt;Now, we can build the code with &lt;code&gt;dotnet build&lt;/code&gt; to make sure that everything builds and that we haven't missed anything. &lt;/p&gt;

&lt;p&gt;Finally, let's run the app with &lt;code&gt;dotnet run &amp;lt;your Tenant Id&amp;gt;&lt;/code&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%2Fuploads%2Farticles%2F5ogr9jzb0ru6vao9rkb3.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%2F5ogr9jzb0ru6vao9rkb3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Job done. One task down, a few more to go! Check the &lt;a href="https://dev.to/425show/delete-an-azure-ad-b2c-tenant-programmatically-4242"&gt;main blog&lt;/a&gt; post on how to delete an Azure AD Tenant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;

&lt;p&gt;If you want to clone and run the app, head out to the &lt;a href="https://github.com/jpda/tenant-deleter" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>identity</category>
      <category>security</category>
      <category>azuread</category>
    </item>
    <item>
      <title>Delete an Azure AD B2C tenant programmatically</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Mon, 26 Jul 2021 23:15:21 +0000</pubDate>
      <link>https://dev.to/425show/delete-an-azure-ad-b2c-tenant-programmatically-4242</link>
      <guid>https://dev.to/425show/delete-an-azure-ad-b2c-tenant-programmatically-4242</guid>
      <description>&lt;p&gt;There are many cases where you may want to programmatically delete an Azure AD B2C instance programmatically. Luckily, most of what we need to do is doable via MS Graph APIs. Quick reminder that MS Graph may not be available for client accounts that use B2C to sign up/in but it's available to admin accounts and can be used to automate or manage a B2C tenant. With that in mind, we're good to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;.NET Core (3.1 or later)&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;An Azure AD B2C tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Necessary steps
&lt;/h2&gt;

&lt;p&gt;Unlike other Azure Resources, Azure AD and B2C require more work to be deleted. When attempting to delete a B2C tenant, the portal present us with a list of actions that need to be completed before we're allowed to blast the resource off the face of the earth. Example below:&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%2Fq6q7gvl9tg75bqmcrpu0.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%2Fq6q7gvl9tg75bqmcrpu0.png" alt="Alt Text"&gt;&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%2Fuploads%2Farticles%2Fbjfgdfvkga3d9w83q1fx.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%2Fbjfgdfvkga3d9w83q1fx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Subsequently, we will be tackling these one at a time and in most cases, there will be an associated video stream to show you how we went about it. If you don't want to see me and JP struggling through the process, you can jump straight to the blog post and code repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/425show/delete-all-users-in-an-azure-ad-tenant-programmatically-3k33"&gt;Delete all users in an Azure AD Tenant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Delete all app registrations in an Azure AD Tenant&lt;/li&gt;
&lt;li&gt;Delete all associated Azure subscriptions in an Azure AD Tenant&lt;/li&gt;
&lt;li&gt;Delete all identity providers in an Azure AD Tenant&lt;/li&gt;
&lt;li&gt;Delete all user flows in an azure AD Tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, reach out to us if you have any questions and don't forget to join our &lt;a href="//aka.ms/425Show/Discord/join"&gt;Discord&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>identity</category>
      <category>azure</category>
      <category>azuread</category>
    </item>
    <item>
      <title>Secure Open API (Swagger) calls with Azure Active Directory</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Wed, 21 Jul 2021 00:52:18 +0000</pubDate>
      <link>https://dev.to/425show/secure-open-api-swagger-calls-with-azure-active-directory-jj7</link>
      <guid>https://dev.to/425show/secure-open-api-swagger-calls-with-azure-active-directory-jj7</guid>
      <description>&lt;p&gt;We have talked about secure web apps and APIs many times here. In this blog post we'll examine how to secure Swashbuckle (.NET's version of Open API/Swagger) with Azure Active Directory in order to make authenticated calls to secure APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the Azure AD App Registrations
&lt;/h3&gt;

&lt;p&gt;To enable end-to-end authentication ,we need to create 2 App Registrations in Azure AD. One for the API and one for the OpenAPI client. You can use the attached .NET Interactive Notebook &lt;strong&gt;app-registrations.ipynb&lt;/strong&gt; to automatically configure both the API and the Swagger App Registrations in Azure AD.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open API/Swagger with .NET
&lt;/h3&gt;

&lt;p&gt;When you create a new API in .NET Core, the default template adds the Open API configuration by default. This means that everything works out of the box. However, if you add authentication to the API then Open Api stops working and needs additional configuration to acquire the necessary access token from Azure AD to make authenticated calls to the API.&lt;/p&gt;

&lt;p&gt;Below we have the starting configuration of Open API in .NET&lt;/p&gt;

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
    services.AddControllers();
    services.AddSwaggerGen(c =&amp;gt;
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "VolcanoAPI", Version = "v1" });
        });
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c =&amp;gt; c.SwaggerEndpoint("/swagger/v1/swagger.json", "YouAPI v1"));
    }

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =&amp;gt;
    {
         endpoints.MapControllers();
    });
}


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

&lt;/div&gt;

&lt;p&gt;Let's implement authentication for our Open API middleware and UI. First, update the &lt;code&gt;Startup.cs&lt;/code&gt; with the necessary code. In the &lt;code&gt;ConfigureServices()&lt;/code&gt; method, add the following code:&lt;/p&gt;

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

services.AddSwaggerGen(c =&amp;gt;
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "swaggerAADdemo", Version = "v1" });            
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Description = "OAuth2.0 Auth Code with PKCE",
        Name = "oauth2",
        Type = SecuritySchemeType.OAuth2,
        Flows = new OpenApiOAuthFlows
        {
            AuthorizationCode = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new Uri(Configuration["AuthorizationUrl"]),
                TokenUrl = new Uri(Configuration["TokenUrl"]),
                Scopes = new Dictionary&amp;lt;string, string&amp;gt;
                {
                    { Configuration["ApiScope"], "read the api" }
                }
            }
        } 
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
            },
            new[] { Configuration["ApiScope"] }
        }
    });
});


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

&lt;/div&gt;

&lt;p&gt;Next step, update the &lt;code&gt;Configure()&lt;/code&gt; method to wire up the UI with the appropriate authentication settings. This bit will enable users to login in the UI before making API calls in the OpenAPI page. &lt;/p&gt;

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

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c =&amp;gt;
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "swaggerAADdemo v1");
        c.OAuthClientId(Configuration["OpenIdClientId"]);
        c.OAuthUsePkce();
        c.OAuthScopeSeparator(" ");
    });
}


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

&lt;/div&gt;

&lt;p&gt;As you may have noticed, both bits of code require some configuration settings. Open the &lt;code&gt;appsettings.json&lt;/code&gt; file and add the following json at the end:&lt;/p&gt;

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

"AuthorizationUrl":"https://login.microsoftonline.com/&amp;lt;your tenant Id&amp;gt;/oauth2/v2.0/authorize",
TokenUrl":"https://login.microsoftonline.com/&amp;lt;your tenant Id&amp;gt;/oauth2/v2.0/token",
"ApiScope": &amp;lt;your api scope(s)&amp;gt;,
"OpenIdClientId": "&amp;lt;your swagger app reg client id&amp;gt;"


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;APIScope&lt;/code&gt; property should have a value similar to this "api://cd28264c-2a31-49df-b416-bf6f332c716d/". This is the scope expected in the Access token by your API. &lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;OpenIdClientId&lt;/code&gt; should contain the Client ID from the Azure AD App Registration -&amp;gt; We did this as part of step 1 when we created the Azure AD App Registrations.&lt;/p&gt;

&lt;p&gt;See it in action below:&lt;br&gt;
Step 1 - Authenticate in Swagger UI&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%2Fosehksvj422ci61fbfau.gif" 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%2Fosehksvj422ci61fbfau.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Step 2 - Make an authenticated call to the API&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%2F13uq2pvn4jac3rv0ckef.gif" 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%2F13uq2pvn4jac3rv0ckef.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Code
&lt;/h3&gt;

&lt;p&gt;As always, if you want to clone the source code, you can find a working repo on &lt;a href="https://github.com/425show/SecureSwaggerWithAAD" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you found this useful but feel free to reach out to us on Twitter &lt;a href="https://twitter.com/christosmatskas" rel="noopener noreferrer"&gt;@christosmatskas&lt;/a&gt;, &lt;a href="https://twitter.com/azureandchill" rel="noopener noreferrer"&gt;@AzureAndChill&lt;/a&gt; or join us on &lt;a href="//aka.ms/425Show/Discord/join"&gt;Discord&lt;/a&gt; to let us know if you have any issues with authentication, Azure AD or B2C!&lt;/p&gt;

</description>
      <category>security</category>
      <category>azure</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A Python MSAL Token Cache for Confidential Clients</title>
      <dc:creator>Christos Matskas</dc:creator>
      <pubDate>Wed, 30 Jun 2021 17:15:58 +0000</pubDate>
      <link>https://dev.to/425show/a-python-msal-token-cache-for-confidential-clients-29c9</link>
      <guid>https://dev.to/425show/a-python-msal-token-cache-for-confidential-clients-29c9</guid>
      <description>&lt;p&gt;MSAL, the Microsoft Authentication Library, helps developers implement authentication and authorization using Azure AD or Azure AD B2C. With a few lines of code, you can add the necessary functionality sign in users and secure resources. MSAL comes with a lot of built-in capabilities to help you do as little work as possible. MFA, Conditional Access and advanced features are available out of the box - no code needed. In many cases, token caching is also provided out of the box. For example, the default cache is &lt;strong&gt;in memory&lt;/strong&gt;. This works great for most dev scenarios, like testing web apps and APIs. &lt;/p&gt;

&lt;p&gt;However, there are certain scenarios that in-memory token caching doesn't work. Ideally, any workload deployed to production should have a persisted and scalable token cache.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll look at how to setup a file-based token cache for our Python-based daemon app. The reason why we need a token cache is because daemon apps are ephemeral. The app runs for a bit to execute a certain task and then terminates. The problem here is that without a token cache, every time we run the daemon, we have to authenticate and acquire a token from Azure AD - which is not efficient!&lt;/p&gt;

&lt;p&gt;Let's build a cache. &lt;/p&gt;

&lt;h2&gt;
  
  
  Building the MSAL Python Cache
&lt;/h2&gt;

&lt;p&gt;The good news is that we don't really have to do a lot of work for this. The MSAL team has already built an &lt;a href="https://github.com/AzureAD/microsoft-authentication-extensions-for-python"&gt;extension library&lt;/a&gt; for Python to provide the basic plumbing for our token cache. &lt;/p&gt;

&lt;p&gt;In our existing Python app, we need to add the new library and implement a bit of code to set everything up.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;requirements.txt&lt;/code&gt;, add the following and save the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msal-extensions&amp;gt;=0.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now update our dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirement.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new file &lt;code&gt;msalcache.py&lt;/code&gt; and add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
import logging

from msal_extensions import *

def build_persistence(location, fallback_to_plaintext=False):
    if sys.platform.startswith('win'):
        return FilePersistenceWithDataProtection(location)
    if sys.platform.startswith('darwin'):
        return KeychainPersistence(location, "my_service_name", "my_account_name")
    if sys.platform.startswith('linux'):
        try:
            return LibsecretPersistence(
                location,
                schema_name="my_schema_name",
                attributes={"attr1": "hello", "attr2": "world"},
                )
        except:
            if not fallback_to_plaintext:
                raise
            logging.exception("Encryption unavailable. Opting in to plain text.")
    return FilePersistence(location)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. We can now use this code to instantiate a cache and assign it to our MSAL Confidential Client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the token cache with MSAL
&lt;/h2&gt;

&lt;p&gt;Before instantiating our MSAL &lt;code&gt;ConfidentialClient&lt;/code&gt; we need to create a cache. Add the following code to &lt;code&gt;console.py&lt;/code&gt; (or your main code file)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;persistence =msalcache.build_persistence("token_cache.bin")
print(f'The MSAL Cache supports encryption: {persistence.is_encrypted}')
cache = PersistedTokenCache(persistence)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we have to update our &lt;code&gt;ConfidentialClient&lt;/code&gt; client to use the cache. Update the code as per below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app = msal.ConfidentialClientApplication(
    client_id=config["client_id"],
    client_credential=aad_client_secret.value,
    authority=config["authority"],
    token_cache=cache
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;Running the code from now on will make use of the cache and the call the &lt;code&gt;acquire_token_silent()&lt;/code&gt; will yield an access token after the first time we run our daemon :)&lt;/p&gt;

&lt;p&gt;You can get the source code for this project from &lt;a href="https://github.com/425show/python-console-aad/tree/TokenSerialization"&gt;our GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn more about the MSAL for Python library, you can read the docs &lt;a href="https://msal-python.readthedocs.io/en/latest/"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
