Tuesday, November 19, 2019

Azure @ Enterprise - Microsoft Identity Platform - Minimal configurations to enable AAD authentication in AppService WebApp

Welcome to Azure @ Enterprise series. In this post, we are going to discuss something about the Microsoft Identity Platform formerly known as Azure Active Directory Developer Platform or AAD v1. We will be seeing how to enable authentication to an Azure AppService Webapp using the Microsoft Identity Platform. There are many tutorials available on the internet to do the same thing. So why one more?

This tutorial is to demonstrate the procedure with minimal configuration settings. Please note that this is not the quickest. For the quickest, please refer to the link provided which uses the express configuration mode.

https://microsoft.github.io/AzureTipsAndTricks/blog/tip184.html

The problem with express settings is that we cannot understand what is going on behind the scene. Sometimes we don't get predictable results when we want to replicate in different environments.

Prerequisite

It would be really great if we have a basic understanding of some concepts to understand better.

- Basic knowledge about web applications and authentication
- Basic knowledge about Azure Web Apps and hosting to Azure
- Basic knowledge about Azure Active directory

Phase 1 - Create and host web application to Azure web app

The aim of this phase is clear as just hosting a new web application into the Azure web app. After hosting, the web application is expected to be accessible anonymously through the internet by just using its URL. Anonymous means without any login mechanism. We will be using Microsoft Visual Studio 2019 to complete the steps in this phase. It can create and host web applications to Azure as App Service Web App.

This phase has multiple steps. The first step open Visual Studio 2019, then creates a new web project. Do some changes to distinguish our application. Test by pressing the run button. It will start a development web server and open the browser pointing to the development server.

Once we feel comfortable with the application, we can publish it to Azure App Service Web App. 
  1. Right-click on the project
  2. Select publish
  3. It will open
Note the URL of the web app which is ending with .azurewebsites.net. Let's take the application URL as https://aadapp.azurewebsites.net/

Phase 2 - Create an Azure AD App Registration

The second phase is to create an App Registration in Azure Active directory. 

The first step here is to go to the Azure portal then to Active directory and click 'App registration' to reach the app registrations page. Create new app registration. Give the name. It is just a display name. For the time being, select the first option in the "Supported account types" radio button group. This will not help if we need to get users from other AAD tenants logged into our application. The next input which is Redirect URI labeled optional is the tricky one. For the use case in this post, we need to fill the URI. The URL is our Azure App Service Web app URI suffixed with '.auth/login/aad/callback'

In this case, the URI would be

Now its time to click the 'Register' button which creates app registration.

The next step is to clean up unwanted settings in App Registrations so that it has minimal settings. Go to 'Authentication'. Click on the 'Try out the new experience' button. This blade would someday get rid of the old experience so better to try the new experience at the earliest. We need the 'Redirect URI'. Logout URL we can skip for now. Make sure the ID Token is checked in the Implicit grant section. No need to treat as a public client as we are not using any of the flows listed. Supported account types section has the value which allows authentication of accounts in one AAD tenant. 

Now lets clean up the Certificates and secrets blade. Since this App registration is not going to be used for getting tokens it doesn't require any secrets.
Next blade called 'API permissions' will have some permissions filled up by default. For our use case that is not required. So let us remove it.
'Expose as API' blade has scopes and authorized client applications. Those are not required for our use case. Simply clean those too in case something there.
The other blades 'Owners', 'Roles and administrators' don't have anything with the auth flow. Manifest has the JSON representation of the resource. Nothing to do there.

Phase 3 - Enable Web App to authenticate via App Registration

Previous phases created a publicly accessible web application and app registration. Apart from Redirect URI, there is no relation between those 2 things. The web application still works anonymously. This phase is to connect the web application to the app registration so that it will force the users to get authenticated via Azure AD.

The first step is to go to the 'Authentication / Authorization' blade. Then turn the App Service Authentication on.
Now select the action to take when a request is not authenticated. It is 'Log in with Azure Active Directory'.
The next step is to configure the Active Directory provider. Click on the Activity Directory option to see the settings. Select the Advanced mode as we are all advanced users. Enter the App registration id into the 'Client ID' field. Isser Url is essential and it can be crafted by prefixing https://login.microsoftonline.com/ to the Azure Active Directory Tenant Id.  It will end up something like below.

https://login.microsoftonline.com/ea1945af-c42b-4482-89e8-abf25ba86249

Press 'OK' then click on 'Save' to save settings to the web application.

Testing

Make sure the cache is cleared in case it is the same browser instance that opened the page earlier. Better open an incognito window and browse the App Service Web App URL. It will redirect to the Azure AD login page. Enter the credentials of a user who is in the same Active Directory Tenant. Remember the setting we gave while creating App registration. If the credentials are right, the browser will redirect back to our Azure App Service Web application URL and shows the page.

More testing

How do we ensure the login really happened? Is it serving the page anonymously even after login? We can see the logged-in user details using a magic URL.
https://aadapp.azurewebsites.net/.auth/me

Video

Step by step video can be found on youtube.

References & Troubleshooting

Details about the openid configuration.
https://login.microsoftonline.com/{AAD Id}/v2.0/.well-known/openid-configuration

https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

Tuesday, November 12, 2019

Power BI Desktop Dashboard for IIS Log Analysis - Improved performance of PowerShell data prep script

This is the third post in the "Power BI Desktop Dashboard for IIS Log Analysis" series.

Power BI Desktop Dashboard for IIS Log Analysis
Power BI Desktop Dashboard for IIS Log Analysis - C# for IIS log parsing instead of PowerShell
Power BI Desktop Dashboard for IIS Log Analysis - Improved performance of PowerShell data prep script

Here we will be discussing how the data preparation process is enhanced by just using the LogParser command. In the initial versions, the time to prepare CSV from the .log file was high if the cs-byes and sc-bytes columns were missing. That is because the approach taken was to load the CSV file into PowerShell and add additional columns with a default value.

This time the approach changed a little bit and completely avoided the need to load CSV files into PowerShell. Logic is as follows

  1. Try to convert the input log files as-is on the assumption that the log contains all the required fields including cs-bytes and sc-bytes. This uses LogParser.exe
  2. In case of error, use the same LogParser.exe file with a slightly different query which selects '0 as cs-bytes, 0 as sc-bytes'
Click here to see the code changes in GitHub repo.

The fix is not rocket science. It is an obvious thing everybody knows but unfortunately missed in the earlier phase. Thanks, Wade Mascia for pointing out.


Happy Analyzing...

Tuesday, October 29, 2019

NewtonSoft Json Test pad

Nearly for the last 10 months half the time in my day job, I am working with Microsoft on optimizing the performance of our flagship application. Not really my current company's application but for the client which is one of the big 4 auditing firms. Sorry, as per NDA, I am not allowed to reveal the client name:)

It is a legacy application someone started in what we now call classic VB when I was in high school. It then converted to .Net then to WPF, then made SOA finally in AngularJS 1.X. I don't think its really converted but people started calling it in different technology. Nothing in WPF blocks you writing code in the WinForms way. It's really a legacy giant with 100s of .vbproj & .csproj files.

One of the problems we discovered was the JSON serialization. Though developers wanted to use NewtonSoft.JSON, they were using JavaScript serializer as that is the built-in JSON serializer in .Net. For using built in things, they don't need additional permissions. At some point, Microsoft figured out from the performance tuning data (perfview.exe) that the JavaScriptSerializer is slow than the NewtonSoft.JSON serializer. Though we all knew the fact, we never expected Microsoft telling that it is the bottleneck in the system and needs to be fixed.

It is declared that the NewtonSoft.JSON serializer would be the defacto serializer going forward. Developers started changing JavaScriptSerializer to NewsonSoft. 

One of the tools which came to demand is a test pad for NewtonSoft.JSON. Given a JSON string, how to easily develop the query to find something in JSON via NewtonSoft.JSON. We can easily use Linq but some are easy with the SelectToken(). We started searching for an online NewtonSoft test pad something similar to JSFiddle. Or some desktop tools similar to LINQPad.

After a good amount of googling ended up using https://dotnetfiddle.net. That has support to add nuget packages. Even we didn't have to start from scratch. Fork the below snippet to start with. 

https://dotnetfiddle.net/QQbpk5

Happy coding...