<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Michael Hansen (CSA/ASA)</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/mihansen/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/mihansen/feed.xml</link>
    <description>Application Development on Azure</description>
    <lastBuildDate>Tue, 07 Aug 2018 01:01:45 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Generating and Loading Synthetic Patient to FHIR Server using Azure Container Instances</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/generating-and-loading-synthetic-patient-to-fhir-server-using-azure-container-instances</link>
      <pubDate>Mon, 06 Aug 2018 18:27:48 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2795</guid>
      <description><![CDATA[Fast Healthcare Interoperable Resources (FHIR) is a new HL7 standard for exchanging information...]]></description>
      <content:encoded><![CDATA[<a href="https://www.hl7.org/fhir/index.html">Fast Healthcare Interoperable Resources (FHIR)</a> is a new HL7 standard for exchanging information between healthcare systems. If you are a regular reader, you will have noticed that I have been working on <a href="https://blogs.msdn.microsoft.com/mihansen/2018/04/20/fhir-server-in-azure-paas/">setting up FHIR servers in Azure</a> and <a href="https://blogs.msdn.microsoft.com/mihansen/2018/05/10/loading-synthea-fhir-data-with-logic-apps-and-functions-in-azure-government/">loading data into FHIR servers</a>. When testing FHIR servers and applications, it is important to be able to load synthetic patient data. The <a href="https://github.com/synthetichealth/synthea">Synthea project</a> has a great generator, which can be used to create large patient datasets with realistic but not real data. In this blog post, I will discuss how to orchestrate patient data generation and upload to a FHIR server, which uses <a href="https://azure.microsoft.com/en-us/services/active-directory/">Azure Active Directory (AAD)</a> as an identity provider. Specifically, I will show how to create a Docker container that will generate the patient data, authentication with AAD, and upload the data to the FHIR server. You can run this Docker container locally on your own computer or deploy it as an <a href="https://azure.microsoft.com/en-us/services/container-instances/">Azure Container Instance (ACI)</a>. I have posted a GitHub repository with the code at <a href="https://github.com/hansenms/SyntheaGenerator">https://github.com/hansenms/SyntheaGenerator</a>.

The source code repository contains a Dockerfile, which installs Synthea and a .NET Core command line application. When running the container, a script will first call the Synthea tool to generate population of patients and it will then call the command line application to upload to a FHIR server.

&nbsp;

<img width="300" class="aligncenter size-full wp-image-2805" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/08/synthea-aad-fhir-docker.png" />

&nbsp;

The command line application requires some settings for AAD Authentication. They can be provided as environment variables:

[js]
{
    &quot;AzureAD_Authority&quot;: &quot;https://login.microsoftonline.com/TENANT-ID/&quot;,
    &quot;AzureAD_ClientId&quot;: &quot;ClientAppId&quot;,
    &quot;AzureAD_ClientSecret&quot;: &quot;SECRET&quot;,
    &quot;AzureAD_Audience&quot;: &quot;FHIR Server App ID&quot;
}
[/js]

The application will use the client id and client secret to authenticate with Azure AD and try to obtain a JWT with audience (claim <code>aud</code>) corresponding to the FHIR server. At the moment, the command line application is effectively authenticating as the application with the provided client id and as such, it cannot be provided any specific scopes on behalf of a user/patient, but it would be assigned any application roles granted to the client application. The command line application could be modified to have a <a href="https://github.com/Azure-Samples/active-directory-dotnet-deviceprofile">user sign in using the device login flow</a>, but it would require a user to be present when initiating the application.

The Docker container needs the environment variables listed above and also <code>FHIR_SERVER_URL</code> and <code>NUMBER_OF_PATIENTS</code>. To run a pre-built version of the Docker image on a local computer, you can use a command like:

[shell]
docker run --name synthea --rm -t \ 
-e AzureAD_ClientSecret='AAD-CLIENT-SECRET' \ 
-e AzureAD_ClientId='AAD-CLIENT-ID' \ 
-e AzureAD_Authority='https://login.microsoftonline.com/TENANT-ID/' \ 
-e AzureAD_Audience='AAD-FHIR-API-APP-ID' -e NUMBER_OF_PATIENTS='100' \ 
-e FHIR_SERVER_URL='https://my-fhir-server/com/' hansenms/synthegenerator
[/shell]

You can also start the container in an Azure Container Instance:

[shell]
az container create --resource-group RgName \ 
--image hansenms/syntheagenerator --name ContainerInstanceName \ 
--cpu 2 --memory 4 --restart-policy Never \ 
-e AzureAD_ClientSecret='CLIENT-SECRET' \ 
AzureAD_ClientId='CLIENT-ID' \ 
AzureAD_Authority='https://login.microsoftonline.com/TENANT-ID/' \ 
AzureAD_Audience='FHIR-SERVER-API-APP' \ 
FHIR_SERVER_URL='https://my-fhir-server.com/' \ 
NUMBER_OF_PATIENTS='100'
[/shell]

In the <a href="https://github.com/hansenms/SyntheaGenerator">GitHub repository</a>, there is also a link to deploy the Azure Container Instance using a template and the portal. After starting the container, you should be able to monitor the progress of patient generation and uploading:

<img width="768" class="aligncenter size-large wp-image-2835" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/08/synthea-upload-output2-1024x517.png" />

And that's it. You now have a fully automated way of generating and uploading synthetic patient data to a FHIR server using Azure Active Directory as an identity provider. Let me know if you have questions/comments/suggestions.]]></content:encoded>
    </item>
    <item>
      <title>Automated Deployment of Gadgetron Workstation in Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/automated-deployment-of-gadgetron-workstation-in-azure</link>
      <pubDate>Sat, 28 Jul 2018 17:11:16 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2765</guid>
      <description><![CDATA[A while back, I helped start the Gadgetron project. It is an open source medical image...]]></description>
      <content:encoded><![CDATA[A while back, I helped start the <a href="https://github.com/gadgetron/gadgetron">Gadgetron</a> project. It is an open source medical image reconstruction engine, which has been used for MRI reconstruction. The build pipeline for the Gadgetron produces Docker images that allow users to easily run the Gadgetron without setting up the required dependencies (there are a few). I showed recently how you can <a href="https://blogs.msdn.microsoft.com/mihansen/2018/07/22/running-gadgetron-in-kubernetes-in-azure/">run the Gadgetron in Kubernetes in Azure</a>. Users that would like to develop the Gadgetron and contribute to the project will need to set up a workstation with all the dependencies installed. It is a bit involved if you want to be able to work with all the pieces including the <a href="https://github.com/ismrmrd/ismrmrd">ISMRMRD Raw Data</a> format and the associated data converters for commercial MRI systems.

To make this process easy, I have created a push button template for deploying a Gadgetron workstation in Azure. You can find it as part of my <a href="https://github.com/hansenms/iac">Infrastructure as Code repository</a>. Specifically, go to <a href="https://github.com/hansenms/iac/tree/master/gadgetron-workstation">https://github.com/hansenms/iac/tree/master/gadgetron-workstation</a> and there will be a button to click to deploy a workstation in Azure:

<img width="512" class="aligncenter size-large wp-image-2775" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/deploy-gadgetron-workstation-1024x671.png" />

This button will take you to the Azure Portal (<a href="https://portal.azure.com">https://portal.azure.com</a>), where you will need to fill in a few details like the resource group where you would like to deploy, the username of your user, an SSH key, and the virtual machine type (size). The automated deployment will:
<ol>
 	<li>Create a Linux Ubuntu 18.04 VM with all the Gadgetron dependencies installed.</li>
 	<li>Install an <a href="https://wiki.x2go.org/doku.php">x2go</a> server to allow you to connect to a graphical desktop.</li>
 	<li>Download the source code for Gadgetron, ISMRMRD, converters, etc. into the users home and compile. The binaries will be installed in <code>~/local</code></li>
</ol>
The deployment and compilation of code will take 20-60 minutes (depending on the size of VM you have chosen) and once complete, you can sign in and either run the Gadgetron or start working on the code.

To connect to the remote desktop, download the x2go client from <a href="https://wiki.x2go.org/doku.php">https://wiki.x2go.org/doku.php</a>. The Ubuntu MATE desktop is installed, and you can pick that desktop type when creating the connection. Supply your SSH private key and username and once connected you should see a desktop environment. Here is an example of running the Gadgetron in one terminal and sending data from another:

<img width="768" class="aligncenter size-large wp-image-2785" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/gadgetron-workstation-desktop-1024x643.png" />

And that's it. You are ready to do development and contribute to the Gadgetron project. The current setup does not install NVIDIA CUDA drivers or libraries, but you could easily add that by <a href="https://github.com/gadgetron/gadgetron/blob/master/docker/base/ubuntu_1804_cuda90/Dockerfile">looking at one of the Docker files</a> that include CUDA.

Let me know if you have questions/comments/suggestions. If you want additional tools added, put up a pull request and I am happy to merge it in.]]></content:encoded>
    </item>
    <item>
      <title>Running Gadgetron in Kubernetes in Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/running-gadgetron-in-kubernetes-in-azure</link>
      <pubDate>Sun, 22 Jul 2018 13:14:59 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2725</guid>
      <description><![CDATA[In my not so distant past, I started an Open Source project called the Gadgetron. There is a...]]></description>
      <content:encoded><![CDATA[In my not so distant past, I started an Open Source project called the <a href="https://github.com/gadgetron/gadgetron">Gadgetron</a>. There is a <a href="https://onlinelibrary.wiley.com/doi/abs/10.1002/mrm.24389">scientific publication</a> that lays out the motivation and use cases. It is a medical image reconstruction engine, which has been used primarily for processing of Magnetic Resonance Imaging (MRI) raw data. Specifically, it is used to transform (reconstruct) the raw data in to images that can be viewed by a clinician.

We showed that the <a href="https://onlinelibrary.wiley.com/doi/abs/10.1002/mrm.25213">Gadgetron can be deployed in the cloud</a> and that doing so enabled clinical deployment of advanced reconstruction techniques that required far more computing power than would typically be available on a modern MRI system. The deployment was based on Docker containers, but a the time we used custom orchestration scripts and tools. In this blog post, I will discuss my initial attempt at using <a href="https://kubernetes.io/">Kubernetes</a> running in <a href="https://azure.microsoft.com/en-us/">Azure</a> for deploying the Gadgetron.

I have created a repository with the necessary artifacts and instructions, you can find it at <a href="https://github.com/hansenms/gadgetron-kubernetes">https://github.com/hansenms/gadgetron-kubernetes</a>.

The deployment to Kubernetes in Azure is a two-step process:
<ol>
 	<li>Creating the Kubernetes cluster.</li>
 	<li>Deploying the Gadgetron.</li>
</ol>
<strong>Creating the Kubernetes Cluster</strong>

There are a several different ways to do this in Azure. If you are using the public Azure Cloud (Commercial Azure), then you can use the managed <a href="https://azure.microsoft.com/en-us/services/kubernetes-service/">Azure Kubernetes Service (AKS)</a>. If you choose this route, please consult the <a href="https://docs.microsoft.com/en-us/azure/aks/">AKS documentation</a> for details. In the <a href="https://github.com/hansenms/gadgetron-kubernetes">repository</a>, I am also including instructions for setting up the cluster using <a href="https://github.com/Azure/acs-engine">ACS Engine</a>, which is the open source engine that underpins services such as AKS. In additions to provisioning Kubernetes clusters, it can be used to provision other orchestration frameworks, e.g., Docker Swarm, DC/OS, etc.

You will find the <a href="https://github.com/hansenms/gadgetron-kubernetes/tree/master/acs-engine">instructions for deploying a Kubernetes cluster</a> within the repository. Briefly, the steps are:

Clone the repository:

[shell]
git clone https://github.com/hansenms/gadgetron-kubernetes
cd gadgetron-kubernetes
[/shell]

Create resource group and service principal:

[shell]
subscription=$(az account show | jq -r .id)

#Name and Location
rgname=gtkubernetes$RANDOM
loc=eastus

#Create Group
rg=$(az group create --name $rgname --location $loc)
rgid=$(echo $rg | jq -r .id)

#Create the Service Principal and assign as contributor on group
sp=$(az ad sp create-for-rbac --role contributor --scopes $rgid)
[/shell]

Convert the template ACS Engine API model:

[shell]
cd acs-engine
./convert-api.sh -c $(echo $sp | jq -r .appId) \
-s $(echo $sp | jq -r .password) -f kubernetes.json -l $loc \
-d &quot;${rgname}DNS&quot; | jq -M . &gt; converted.json
[/shell]

Deploy the cluster:

[shell]
acs-engine deploy --api-model converted.json \
--subscription-id $subscription --resource-group $rgname \
--location $loc --azure-env AzurePublicCloud
[/shell]

The deployed cluster will have <a href="https://github.com/Azure/acs-engine/blob/master/examples/addons/cluster-autoscaler/README.md">cluster autoscaling</a> on. What this feature does is to add more agent nodes when a request to deploy a pod (with a Gadgetron container) would exceed the currently available resources in the cluster. With this feature on, we can use <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">Kubernetes Horizontal Pod Autoscaling</a> to add more Gadgetron pods when needed and more underlying VMs will be added as needed. More on that below.

<strong>Deploying the Gadgetron</strong>

After deploying the cluster itself, we are ready to deploy the Gadgetron components into the cluster. The end result will look conceptually like this:

<img width="768" class="aligncenter size-large wp-image-2755" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/gadgetron-kubernetes-1024x700.png" />

There are really 3 components in the deployment:

1. Some shared storage. Gadgetron pods need a shared storage location to store dependent measurements (noise data, etc.). In this case, we are using <a href="https://azure.microsoft.com/en-us/services/storage/files/">Azure Files</a> to store this data. There is a <a href="https://github.com/hansenms/gadgetron-kubernetes/blob/master/create_shared_storage.sh">script in the repository for creating the shared storage</a>.

2. Some pods with the Gadgetron itself. These pods are exposed with a <a href="https://kubernetes.io/docs/concepts/services-networking/service/">Kubernetes Service</a>  of type "ClusterIP". This means that the Gadgetron pods will not be accessible from outside the cluster.

You can see the details of what is deployed in the <a href="https://github.com/hansenms/gadgetron-kubernetes/blob/master/gadgetron-kubernetes.yaml">gadgetron-kubernetes.yaml</a> manifest. You can apply this manifest with:

[shell]
kubectl apply -f gadgetron-kubernetes.yaml
[/shell]

Importantly, this manifest defines a) the image being used, b) the resources required for a pod to run the Gadgetron, and c) a Horizontal Pod Autoscaler, that will automatically add more pods when a certain average CPU load is reached for the deployed Gadgetron instances. Since we also have cluster autoscaling deployed, more VMs will be added to the agent pool if the required resources exceed available capacity.

2. An SSH jump server. This is essentially an SSH server running in a pod in the cluster. This is exposed with service of type "LoadBalancer", which means that it will get a public IP address. To deploy the server allowing the current user to connect:

[shell]
#Get an SSH key, here we are using the one for the current user
#Replace with other key as needed
SSHKEY=$(cat ~/.ssh/id_rsa.pub |base64 -w 0)
sed &quot;s/PUBLIC_KEY/$SSHKEY/&quot; gadgetron-ssh-secret.yaml.tmpl &gt; gadgetron-ssh-secret.yaml

#Create a secret with the key
kubectl create -f gadgetron-ssh-secret.yaml

#Deploy the jump server
kubectl apply -f gadgetron-ssh-jump-server.yaml
[/shell]

<strong>Connecting to the Gadgetron</strong>

It is beyond the scope of this blog post to explain how to create and send data to the Gagetron, but you will want to establish an SSH tunnel (through the jump server). By default the jump server gets deployed with a public key from the current user. You can connect with:

[shell]
#Public (external) IP:
EXTERNALIP=$(kubectl get svc sshd-jumpserver-svc --output=json | jq -r .status.loadBalancer.ingress[0].ip)

#Internal (cluster) IP:
GTCLUSTERIP=$(kubectl get svc gadgetron-frontend --output=json | jq -r .spec.clusterIP)

#Open tunnel:
ssh -L 9022:${GTCLUSTERIP}:9002 root@${EXTERNALIP}
[/shell]

After this you should be able to send some data with:

[shell]
ismrmrd_generate_cartesian_shepp_logan -r 10
gadgetron_ismrmrd_client -f testdata.h5 -p 9022 -o myoutput.h5
[/shell]

<strong>Conclusions and Next Steps</strong>

I have demonstrated the basics steps of deploying the Gadgetron in a Kubernetes cluster in Azure. The current configuration includes the elements needed for automatic scaling of the cluster. However, the scaling criteria are pretty simplistically based on some CPU utilization criteria. While this may suffice for some basic scenarios, it may be worth considering using <a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-custom-metrics">custom metrics for Horizontal Pod Autoscaling</a>. It would be necessary to implement some custom metrics server, which would include Gadgetron specific metrics such as the current number of the Gadgetron reconstructions, etc. Another possible optimization would be to add some node discovery service to allow the Gadgetron to do more sophisticated load balancing. At the moment, jobs are simply distributed through the ClusterIP service (effectively doing round robin load balancing), which may suffice in many case but it could prove less than optimal.

Let me know if you have questions/comments/suggestions.]]></content:encoded>
    </item>
    <item>
      <title>.NET Core Angular App with OpenID Connection Implicit Flow Authentication (angular-auth-oidc-client)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/net-core-angular-app-with-openid-connection-implicit-flow-authentication-angular-auth-oidc-client</link>
      <pubDate>Thu, 12 Jul 2018 19:07:52 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2695</guid>
      <description><![CDATA[The purpose of this blog post is to discuss Azure Active Directory authentication for Angular Single...]]></description>
      <content:encoded><![CDATA[The purpose of this blog post is to discuss Azure Active Directory authentication for <a href="https://angular.io/">Angular</a> Single Page Applications (SPAs) generated with the <code>dotnet</code> CLI. The .NET Core 2.1 distribution makes it easy to crate an Agular SPA with a .NET Core backend using a command like:

[shell]
dotnet new angular
[/shell]

However, the generated app does not have any authentication scheme defined and it is not presently possibly to generate a template with authentication enabled. <a href="https://damienbod.com/about/">Damien Bowden</a> has created an OpenID Connect Certified <a href="https://github.com/damienbod/angular-auth-oidc-client">angular-auth-oidc-client</a> library that can be used to enable authentication and he has even created a very nice example of <a href="https://github.com/damienbod/dotnet-template-angular">how to integrate with the Angular template</a> for Azure Active Directory authentication. There is also a <a href="https://damienbod.com/2018/01/23/using-the-dotnet-angular-template-with-azure-ad-oidc-implict-flow/">nice blog post about the example</a>.

I have created an updated version of this example, which you can find at: <a href="https://github.com/hansenms/dotnet-angular-oidc">https://github.com/hansenms/dotnet-angular-oidc</a>. The updated example has changes/enhancements (you can <a href="https://github.com/hansenms/dotnet-angular-oidc/compare/original-template...master">browse the changes that were made to the original template</a>).

<strong>UPDATE 2018-07-13: Damien Bowden has merged the changes that I made into his example, so at this point, either repository uses a backed AAD proxy to get the OpenId Configuration. </strong>

Damien Bowden's <a href="https://github.com/damienbod/dotnet-template-angular">original example</a> uses static (downloaded versions of the openid-configuration and keys). This is needed because the Azure Active Directory endpoints do not allow Cross Origin Resourece Sharing (CORS). In this my updated example, a <code>ConfigController</code> has been implemented to allow the backend application to do the discovery. That way changes to those backend configurations (such as keys) will be automatically loaded. The updated example allows both <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-compare">v1.0 and v2.0</a> of the Azure Active Directory Endpoints.

To use the example, define the following application settings:

[js]
{
  &quot;oidc&quot;: {
    &quot;issuer&quot;: &quot;Oauth2-Issuer-Url&quot;,
    &quot;client_id&quot;:&quot;CLIENT-APP-ID&quot;,
    &quot;scope&quot;: &quot;openid profile email https://graph.microsoft.com/User.Read&quot;,
    &quot;resource&quot;: &quot;&quot;
  }
}
[/js]

If you use a v1.0 AAD endpoint, you will need to create your application registration in the Azure Portal (e.g., https://portal.azure.com) in the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications#adding-an-application">Active Directory Application registration section</a>. <strong>Remember to edit the manifest to enable implicit flow</strong>. Subsequently, the configuration would look something like:

[js]
{
  &quot;oidc&quot;: {
    &quot;issuer&quot;: &quot;https://login.microsoftonline.com/TENANT-ID/&quot;,
    &quot;client_id&quot;:&quot;CLIENT-APP-ID&quot;,
    &quot;scope&quot;: &quot;openid&quot;,
    &quot;resource&quot;: &quot;https://graph.microsoft.com/&quot;
  }
}
[/js]

For a v2.0 AAD endpoint configuration, you will need to use the new Microsoft App Registration Portal (<a href="https://apps.dev.microsoft.com/">https://apps.dev.microsoft.com/</a>). The configuration would then look like:

[js]
{
  &quot;oidc&quot;: {
    &quot;issuer&quot;: &quot;https://login.microsoftonline.com/TENANT-ID/v2.0/&quot;,
    &quot;client_id&quot;:&quot;CLIENT-APP-ID&quot;,
    &quot;scope&quot;: &quot;openid profile email https://graph.microsoft.com/User.Read&quot;,
    &quot;resource&quot;: &quot;&quot;
  }
}
[/js]

The application settings can be defined in the <code>appsettings.json</code> file, using environment variables (app settings in a Web App), or using the <code>user-secrets</code> feature of the <code>dotnet</code> CLI:

[shell]
dotnet user-secrets set oidc:issuer &quot;https://login.microsoftonline.com/TENANT/v2.0/&quot;
dotnet user-secrets set oidc:client_id &quot;CLIENT-ID&quot;
dotnet user-secrets set oidc:scope &quot;openid profile email https://graph.microsoft.com/User.Read&quot;
[/shell]

The example can be run locally with <code>dotnet run</code>. Once you access the page, you will see a login menu item:

<img width="768" class="aligncenter size-large wp-image-2705" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/angular-oidc-login-1024x272.png" />

If you click the login link, you should be taken through the Azure Active Directory authentication and you will see that you now have access to some protected content:

<img width="768" class="aligncenter size-large wp-image-2715" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/angular-oidc-logout-1024x218.png" />

And that is it. I would encourage you to look at the <a href="https://github.com/hansenms/dotnet-angular-oidc">source code for details</a>, and follow <a href="https://github.com/hansenms/dotnet-angular-oidc/compare/original-template...master">the specific changes</a> if you would like to add authentication to your project. Let me know if you have questions/comments/suggestions.]]></content:encoded>
    </item>
    <item>
      <title>Publish SMART on FHIR OAuth2 URLs using Azure API Management</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/publish-smart-on-fhir-oauth2-urls-using-azure-api-management</link>
      <pubDate>Fri, 06 Jul 2018 14:47:46 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2675</guid>
      <description><![CDATA[Fast Healthcare Interoperable Resources (FHIR) is an emerging standard for describing healthcare...]]></description>
      <content:encoded><![CDATA[Fast Healthcare Interoperable Resources (FHIR) is an emerging standard for describing healthcare data (Resources) and an API for exchanging healthcare information. I have written several blog posts on running <a href="https://blogs.msdn.microsoft.com/mihansen/2018/04/20/fhir-server-in-azure-paas/">Firely FHIR servers in Azure</a> and <a href="https://blogs.msdn.microsoft.com/mihansen/2018/05/07/hapi-fhir-in-azure-paas/">HAPI FHIR servers in Azure</a>.  I have also described that you can <a href="https://blogs.msdn.microsoft.com/mihansen/2018/05/09/fhir-server-with-azure-api-management/">use Azure API Management in front of a FHIR server</a>.

<a href="https://docs.smarthealthit.org/">SMART on FHIR</a> is a tech stack for applications that build on the FHIR standard. It provides a framework and guidance on how applications should interact with Electronic Health Records (EHR) systems. Among other specific guidance, SMART on FHIR lays out the <a href="https://docs.smarthealthit.org/authorization/">authentication/authorization</a> flows bases on OAuth2. In a previous blog post, I discussed how Azure Active Directory could be used for <a href="https://blogs.msdn.microsoft.com/mihansen/2018/06/30/azure-active-directory-proxy-for-smart-on-fhir/">SMART on FHIR authorization through a proxy</a>. In this blog post I will add to this scenario by showing how Azure API Management can be used to publish the authorization and token endpoints for SMART on FHIR.

The SMART on FHIR security information can be <a href="https://docs.smarthealthit.org/authorization/conformance-statement/">included in the conformance statement</a>. This statement is generally available through the <code>/metadata</code> endpoint on the FHIR server. In order to modify the body of the message returned from the FHIR server, you can modify the outbound policy on the <code>/metadata</code> endpoint:

<img width="768" class="aligncenter size-large wp-image-2685" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/apim-edit-metadata-policy-1024x559.png" />

Depending on your backend FHIR server and the way that you imported the API, the <code>/metadata</code> endpoint may not be there. You can simply add a new endpoint pointing to the same path on the backend. In the <code>outbound</code> policy, you can modify the body of the message using the <code>set-body</code> tag:

[xml]
&lt;policies&gt;
    &lt;inbound&gt;
        &lt;base /&gt;
    &lt;/inbound&gt;
    &lt;backend&gt;
        &lt;base /&gt;
    &lt;/backend&gt;
    &lt;outbound&gt;
        &lt;set-body&gt;
              &lt;!-- TEXT OF BODY --&gt;
        &lt;/set-body&gt;
        &lt;base /&gt;
    &lt;/outbound&gt;
    &lt;on-error&gt;
        &lt;base /&gt;
    &lt;/on-error&gt;
&lt;/policies&gt;
[/xml]

The part where the "TEXT OF BODY" is generated can simply be replaced with the following C# snippet, where we add the <code>authorize</code> and <code>token</code> endpoints for SMART on FHIR:

[plain]
@{
            var response = context.Response.Body.As&lt;JObject&gt;();

            var rest = ((JArray)response[&quot;rest&quot;])[0] as JObject;

            var security = JObject.Parse(@&quot;{ 
                'service': [
                    {
                        'coding': [
                            {
                                'system': 'https://hl7.org/fhir/restful-security-service',
                                'code': 'SMART-on-FHIR'
                            }
                        ],
                        'text': 'OAuth2 using SMART-on-FHIR profile (see https://docs.smarthealthit.org)'
                    }
                ],
                'extension': [
                    {
                        'url': 'https://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris',
                        'extension': [
                            {
                                'url': 'token',
                                'valueUri': 'https://smart-on-fhir-login.azurewebsites.net/microsoft.onmicrosoft.com/oauth2/token'
                            },
                            {
                                'url': 'authorize',
                                'valueUri': 'https://smart-on-fhir-login.azurewebsites.net/microsoft.onmicrosoft.com/oauth2/authorize'
                            }
                        ]
                    }
                ]
            }&quot;);

            rest.Add(&quot;security&quot;, security);
            
            return response.ToString();
}
[/plain]

You should, of source replace the specific URLs to match your server. And that is it, you have now leveraged Azure API Management to update the conformance statement with the appropriate authorization endpoints. 

Let me know if you have questions/comments/suggestions.

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Open EMR in Azure PaaS (Commercial and Government)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/open-emr-in-azure-paas-commercial-and-government</link>
      <pubDate>Tue, 03 Jul 2018 12:30:09 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2535</guid>
      <description><![CDATA[Open EMR is a popular open source electronic health records and medical practice management...]]></description>
      <content:encoded><![CDATA[<a href="https://www.open-emr.org/">Open EMR</a> is a popular open source electronic health records and medical practice management solution. There are a <a href="https://www.open-emr.org/wiki/index.php/OpenEMR_Downloads">number of available distributions</a> based on Docker containers, Windows, or Linux installations. In this blog post, I will show that it is easy to install it in an <a href="https://azure.microsoft.com/en-us/services/app-service/web/">Azure Web App</a>. Open EMR is written in PHP and uses a MySQL backend database. I will show how to set it up in Azure Government using the in-app MySQL functionality in Azure Web Apps. You could of course choose to use the <a href="https://azure.microsoft.com/en-us/services/mysql/">managed MySQL service</a> in Azure (Commercial), the instructions would be very similar. I have previously described a similar procedure for <a href="https://blogs.msdn.microsoft.com/mihansen/2018/04/16/itop-itsm-in-azure-web-app-with-aad-authentication/">setting up iTop (ITSM) in Azure Web Apps</a>. If you read that blog post, this will seem very familiar.

<b>1. Create a new Web App</b>

<b></b>First create a new Azure Web App and an App Service Plan. Consider that the app service plan will be supporting both the MySQL database and the web app itself, so I would recommend going with at least an S1 plan.

<img width="384" class="aligncenter size-large wp-image-2555" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/new-web-app-685x1024.png" />

<b>2. Enable in-app MySQL</b>

<b></b>Azure Web Apps support "in-app" MySQL, which runs the database using the app service plan resources. I would not recommend this for production use due to the resource restrictions, but there is a good chance that you are setting up Open EMR for testing purposes or a demo, in which case it is perfectly fine.

<img width="768" class="aligncenter size-large wp-image-2545" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/enable-mysql-1024x565.png" />

After enabling the database, I recommend validating that you can access the web app site itself and also the Kudu console (the *.scm.azurewebsites.* site).

<b>3. Set the PHP version in the Web App</b>

<b></b><b></b>I recommend using PHP version 7.2, which you can pick in the application settings:

<img width="512" class="aligncenter size-large wp-image-2575" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/php-version-1024x731.png" />

<b>4. Locate the connection details for the MySQL database</b>

<b></b><b></b><b></b>Using the Kudu console, navigate to <code>D:\home\data\mysql</code>, where you will find a TXT file with the username and password for the MySQL database:

<img width="768" class="aligncenter size-large wp-image-2565" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/kudu-sql-connection-txt-1024x783.png" />

This file should contain a string that looks something like this:

[plain]
Database=localdb;Data Source=127.0.0.1:XXXXX;User Id=azure;Password=XXXXX
[/plain]

Make a note of the port number and the password.

<b>5. Create a database for Open EMR</b>

<b></b><b></b>The Open EMR installation actually has a feature for creating the database for you, but it requires a root user with GRANT privileges and the azure user in the file above does not have such privileges, so I recommend creating a new database manually. You can use the phpMyAdmin interface by clicking "Manage" on your in-app MySQL database:

<img width="512" class="aligncenter size-large wp-image-2585" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/manage-mysql-1024x460.png" />

Then create a new database, e.g. called "openemr":

<img width="512" class="aligncenter size-large wp-image-2595" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/create-new-database-1024x571.png" />

<b>6. Connect to Open EMR GitHub respository</b>

There are several ways to deploy the source code into the Web App. You can download the <a href="https://github.com/openemr/openemr/releases">latest release of Open EMR</a>, and drag and drop the zip file into <code>D:\home\site\wwwroot</code>. Alternatively, you can connect directly to the Open EMR GitHub repository. Click "Deployment Options" on web app and select and external repository as source:
<b></b>

<img width="384" class="aligncenter size-large wp-image-2605" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/configure-external-respository-1024x589.png" />

Then enter the appropriate settings for the Open EMR GitHub repo:

<img width="384" class="aligncenter size-full wp-image-2615" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/git-settings.png" />

Here the branch called "rel-501" was chosen, but you can select the version you want or go with the master branch if you want the latest snapshot. After selecting the repository, you will have to do a sync and it will take a little while before the code is downloaded and deployed.

<strong>7. Configure Open EMR</strong>

After the code has deployed, navigate to the URL of web app and the setup wizard should be initiated:

<img width="384" class="aligncenter size-large wp-image-2645" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/open-emr-setup-1-1024x504.png" />

Click continue and select the option where you have already created the database:

<img width="384" class="aligncenter size-large wp-image-2655" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/open-emr-setup-2-have-database.png" />

Then enter the database details. Remember to set the port. The default will not be correct:

<img width="384" class="aligncenter size-large wp-image-2665" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/open-emr-setup-3-database-settings-1024x735.png" />

The database setup may take a few minutes and there will be a few screens to click through after that, but eventually you should reach the end and be able to login to the Open EMR system:

<img width="384" class="aligncenter size-large wp-image-2625" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/open-emr-login-1024x640.png" />

After signing in, you can start adding patients, provider, etc.

<img width="768" class="aligncenter size-large wp-image-2635" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/07/open-emr-running-1024x338.png" />

And that's it. You now have your very own Open EMR system running in Azure PaaS services. Let me know if you have questions/comments/suggestions.

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Azure Active Directory Proxy for SMART on FHIR</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/azure-active-directory-proxy-for-smart-on-fhir</link>
      <pubDate>Sat, 30 Jun 2018 20:16:32 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2515</guid>
      <description><![CDATA[Fast Healthcare Interoperability Resources (FHIR) is a draft standard describing data formats and...]]></description>
      <content:encoded><![CDATA[Fast Healthcare Interoperability Resources (<a href="https://www.hl7.org/fhir/">FHIR</a>) is a draft standard describing data formats and elements (known as “resources”) and an application programming interface (API) for exchanging electronic health records. There is currently a lot of momentum behind this standard; most modern Electronic Health Records (EHR) systems and healthcare applications support some parts of the FHIR standard.

<a href="https://docs.smarthealthit.org/"> SMART on FHIR</a> is a tech stack for healthcare applications that build on the FHIR standard and provide a framework for integrating EHR systems, portals, and other applications. An important part of the SMART on FHIR standard is the formalized way that healthcare applications should obtain authorization to access a FHIR server holding health records. You can read all about that in the <a href="https://docs.smarthealthit.org/authorization/">SMART on FHIR authorization guide</a>.

The authorization is based on <a href="https://en.wikipedia.org/wiki/OAuth">OAuth 2.0</a> and <a href="https://en.wikipedia.org/wiki/OpenID_Connect">OpenID Connect</a>. Since <a href="https://azure.microsoft.com/en-us/services/active-directory/">Azure Active Directory (AAD)</a> <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code">supports OAuth 2.0</a>, it makes sense to explore if AAD can play the role of identity store and authorization server for SMART on FHIR applications. In this blog post, I will outline a few of the differences in parameter naming, etc. when comparing AAD and the SMART on FHIR flow and I will show how to use a web app proxy to bridge the gap between the SMART on FHIR conventions and AAD.

Before diving into the SMART on FHIR authorization flow, I would recommend browsing through the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-developers-guide">Azure Active Directory Developer docs</a>. There is a lot of detail in there, but for the purposes of this discussion, you should be aware that there are two different OAuth endpoints that one can use. There is the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-compare">original endpoint and the v2.0 endpoint</a>. There are some key differences/limitations:
<ol>
 	<li>Applications using the original endpoint will need to statically select which scopes from backend APIs that the application will need. The v2.0 endpoint allow incremental modifications of the scopes that an application may need.</li>
 	<li>When using the original endpoint, an application will need to specify a backend API that it needs to access using a <code>resource</code> parameter (more on that later). The version v2.0 endpoint does not support the resource parameter but expects fully qualified (including backend resource or audience) scopes.</li>
 	<li>When using v2.0 endpoint, the application registrations must be done using the Microsoft App Registration portal (<a href="https://apps.dev.microsoft.com">https://apps.dev.microsoft.com</a>). Applications using the original endpoint can be defined in the Azure Portal.</li>
</ol>
To make this a bit more concrete, an authorization flow using the original endpoint would be initiated with something like:

[plain]
GET https://login.microsoftonline.com/{TENANT}/oauth2/authorize?resource=https://resource-uri&amp;client_id=XXXX&amp;....
[/plain]

The <code>resource</code> parameter refers to an app registration representing a backend API (e.g., a FHIR server), and when obtaining a token from the token endpoint after authorization, it would have whatever scopes had been statically selected for the application in question. It is possible to supply a <code>scope</code> parameter, but it is ignored.

The flow using the v2.0 endpoint would start with something like:

[plain]
GET https://login.microsoftonline.com/{TENANT}/oauth2/v2.0/authorize?client_id=XXXX&amp;scope=https://resource-uri/access_as_user&amp;....
[/plain]

Here we are requesting a specific scope (<code>access_as_user</code>) on the backend API (audience or resource) identified by <code>https://resource-uri</code>. So there is no <code>resource</code> parameter anymore but we can incrementally select the scopes that an application needs.

The SMART on FHIR flow expects a different naming convention for these parameters. The authentication flow might be initiated with:

[plain]
GET https://auth-server-url/authorize?aud=https://fhir-server&amp;client_id=XXXX&amp;scope=patient/Observation.read&amp;....
[/plain]

Comparing to the original AAD flow, the <code>aud</code> (audience) parameter is equivalent to <code>resource</code> and the expectation is that scopes can be specified to incrementally add scopes as the application needs them.

To make this compatible with AAD, we can use a proxy between the SMART on FHIR application and AAD. I have made a simple example of such a proxy, which you can find in this GitHub repository: <a href="https://github.com/hansenms/SmartOnFHIR-AAD-Proxy">https://github.com/hansenms/SmartOnFHIR-AAD-Proxy</a>. It is a .NET Core Web API that can de deployed into an Azure Web App. The flow would look something like this:

<img width="384" class="aligncenter size-full wp-image-2525" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/AAD-SMART-On-FHIR-Proxy.png" />

The user (or user application) will interact with the web app proxy to authenticate and obtain a token, which is then used to authorize access to the FHIR server. If we suppose that the web app is deployed at the address https://smart-aad-proxy, then an authentication flow can be initiated with:

[plain]
GET https://smart-aad-proxy/{TENANT}/oauth2/authorize?aud=https://fhir-server&amp;client_id=XXXX&amp;scope=patient/Observation.read&amp;....
[/plain]

Or

[plain]
GET https://smart-aad-proxy/{TENANT}/oauth2/v2.0/authorize?aud=https://fhir-server&amp;client_id=XXXX&amp;scope=patient/Observation.read&amp;....
[/plain]

In both cases the request will be redirected to the AAD authorization endpoint and the parameters translated into a form that AAD will accept. In the case of the original endpoint, the scopes will be ignored (assumed statically defined) and in the case of the v2.0 endpoint, the <code>aud</code> and <code>scope</code> parameters will be combined into fully qualified scopes that AAD expects. In addition to this, any slashes (<code>/</code>) will be replaced with hyphens (<code>-</code>) since the slashes in the fully qualified scopes are confusing for AAD. So to make this work, you must name your scopes accordingly when registering the application. The request to the v2.0 endpoint in this case would get translated to something like:

[plain]
GET https://login.microsoftonline.com/{TENANT}/oauth2/v2.0/authorize?client_id=XXXX&amp;scope=https://fhir-server/patient-Observation.read&amp;....
[/plain]

The request to the authorization endpoint is redirected to the AAD endpoint. The web app proxy also supports the token endpoint, e.g. a token could be obtained from:

[plain]
POST https://smart-aad-proxy/{TENANT}/oauth2/v2.0/token
[/plain]

Since this is a <code>POST</code> request, it cannot be redirected, it has to be proxied. It is not a requirement to use the token endpoint of the proxy, that request could go directly to the AAD token endpoint. FHIR servers will announce their authorization and token endpoint as part of the conformance (metadata) statement. 

And that's it. You now have a set of SMART on FHIR compatible OAuth endpoints backed by Azure Active Directory. Let me know if you have questions/comments/suggestions.

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Azure Active Directory B2B Self Service Sign-Up using Logic Apps</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/azure-active-directory-b2b-self-service-sign-up-using-logic-apps</link>
      <pubDate>Thu, 14 Jun 2018 15:45:14 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2425</guid>
      <description><![CDATA[Azure Active Directory (AAD) is Microsoft’s multi-tenant, cloud based directory and identity...]]></description>
      <content:encoded><![CDATA[<a href="https://azure.microsoft.com/en-us/services/active-directory/">Azure Active Directory (AAD)</a> is Microsoft’s multi-tenant, cloud based directory and identity management service. It is used to manage access to services such as Office 365 and the Azure Cloud. Typically an instance of AAD (an AAD tenant) is used by a single organization for their users. In this blog post, I will discuss how to use <a href="https://azure.microsoft.com/en-us/services/logic-apps/">Azure Logic Apps</a> to create a self service sign-up system for adding users to AAD using AAD B2B.

When an organization wants to interact with external users, they can use <a href="https://azure.microsoft.com/en-us/services/active-directory-b2c/">Azure Active Directory B2C (Business to Consumer)</a> which is a cloud based identity service for customer facing applications. In AAD B2C, customers generally bring their own identity (Microsoft, Google, Facebook, Twitter, etc.), but it is also possible to invite external users into an organizations directory using <a href="https://docs.microsoft.com/en-us/azure/active-directory/b2b/add-users-administrator">Azure Active Directory B2B</a> (Business to Business). With AAD B2B, the invited users become (guest) members of an organizations Directory and can for instance be granted access to Azure resources or sign into applications that use the organizations AAD tenant as an identity source.

Let's suppose that an organization wanted to invite the participants at an event to join an Azure Active Directory. Rather than collecting email addresses from all the participants at the event, the organization would like to hand out a sign-up key or token and have them self-register on a web page to initiate the AAD B2B invitation process. This can be achieved using the Azure serverless platform:

&nbsp;

<img width="512" class="aligncenter size-full wp-image-2435" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-logic-app.png" />

The system consists of a relatively simple HTML page with a sign-up form. When the form is submitted, a JavaScript function will call a Logic App (thanks to <a href="https://blogs.msdn.microsoft.com/logicapps/2017/01/30/calling-a-logic-app-from-an-html-form/">Jeff Hollan for a blog on that</a>). The Logic App will check a key/token provided by the user and if it is valid, it will initiate the B2B invitation process using the <a href="https://docs.microsoft.com/en-us/azure/active-directory/b2b/customize-invitation-api">B2B invitation API</a>.

Before we dive into the implementation, let's start with what the user experience would look like. They would go to a web page and fill in a form:

<img width="512" class="aligncenter size-large wp-image-2445" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-user-signup-form-1024x525.png" />

After hitting submit, if the token is <strong>not</strong> valid, they would see a response like this:

<img width="512" class="aligncenter size-large wp-image-2455" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-user-signup-invalid-token-1024x600.png" />

If the token is valid, they would see a response like this:

<img width="512" class="aligncenter size-large wp-image-2465" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-user-signup-valid-token-1024x589.png" />

If successful the user would then have an invitation email to join the directory through the B2B process.

Let's dive into how all of this is put together. I will start with the JavaScript that calls the Logic App. I have reproduced it here in its entirety to make sure all the details (secrets have been X'ed out) are there:

[javascript]
        function processForm(e) {

            if (e.preventDefault) e.preventDefault();

            var alertDiv = document.getElementById(&quot;feedback&quot;);

            var xhr = new XMLHttpRequest();
            xhr.open(&quot;POST&quot;, &quot;https://prod-28.eastus.logic.azure.com:443/workflows/XXXXXX/triggers/manual/paths/invoke?api-version=2016-10-01&amp;sp=%2Ftriggers%2Fmanual%2Frun&amp;sv=1.0&amp;sig=XXXXX&quot;, true);
            xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=utf-8&quot;);
            xhr.timeout = 10000;
            xhr.onload = function (e) {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        alertDiv.innerHTML = 'Please check your email for an invitation.';
                        alertDiv.className  = 'alert alert-success';
                        alertDiv.style.visibility = 'visible';
                    } else {
                        alertDiv.innerHTML = 'An Error occurred (' + xhr.status.toString() + '). Please check that your token is valid.';
                        alertDiv.className  = 'alert alert-danger';
                        alertDiv.style.visibility = 'visible';
                    }
                }
            };

            xhr.ontimeout = function (e) {
                alertDiv.innerHTML = 'The request to server timed out. Please try again later.';
                alertDiv.className  = 'alert alert-danger';
                alertDiv.style.visibility = 'visible';
            };

            xhr.onerror = function (e) {
                alertDiv.innerHTML = 'An error occurred while contacting server.';
                alertDiv.className  = 'alert alert-danger';
                alertDiv.style.visibility = 'visible';
            };

            var item = {
                    firstName: document.getElementById(&quot;firstName&quot;).value,
                    lastName: document.getElementById(&quot;lastName&quot;).value,
                    emailAddress: document.getElementById(&quot;emailAddress&quot;).value,
                    signupToken: document.getElementById(&quot;signupToken&quot;).value,
                    emailUpdate: document.getElementById(&quot;emailUpdateCheck&quot;).value == &quot;on&quot; ? true : false
            };
            
            alertDiv.innerHTML = 'Processing request....';
            alertDiv.className  = 'alert alert-light';
            alertDiv.style.visibility = 'visible';

            xhr.send(JSON.stringify(item));

            return false;
        }

        function attachEvents() {
            var form = document.getElementById('signup-form');

            if (form.attachEvent) {
                form.attachEvent(&quot;submit&quot;, processForm);
            } else {
                form.addEventListener(&quot;submit&quot;, processForm);
            }
        }
[/javascript]

To make sure that it works, you need to have a form for holding the user provided information and call the <code>attachEvents()</code> function when the page loads, it could look something like <a href="https://gist.github.com/hansenms/395fbd2af4b6821c29f3457075431ec7">this</a>.

Next step is the Logic App doing the work. Here is a quick overview of the flow of the Logic App:

<img width="1024" height="705" class="alignnone size-large wp-image-2475" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-logic-app-overview-1024x705.png" />

The Logic App receives and HTTP request (from the JavaScript above). The flow splits in two; in one path (left) we read a list of valid tokens from Blob Storage (it is a JSON file and we parse it) and in the other path (right) we parse the JSON received from the JavaScript. We then loop through all valid tokens to see if there is a match (the "For Each" loop). If there is a match, we send an email and set a variable to indicate that the email was sent.

If we take a closer look at the loop, it looks like this:

<img width="1016" height="1024" class="alignnone size-large wp-image-2485" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-logic-app-token-loop-1016x1024.png" />

If a match is found, we do an HTTP call with Azure Directory OAuth. You will need to provide an application registration (client id and secret). This application registration must have "Application Permission" to invite users to the directory. You can read about <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications">how to create an application registration in the docs</a>. After creating the application and a key for it, you would select the permissions like this:

<img width="768" class="aligncenter size-large wp-image-2505" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/b2b-app-reg-graph-permissions1-1024x577.png" />

Please note that you need to select the "Invite guest users to the organization" privilege in the "Application Permissions" section. Also note that granting this privilege requires administrative privileges (as indicated by the "Yes") after the privilege. <strong>After saving the selection, you must hit the "Grant permissions" link to actually grant the privileges. </strong>

The HTTP request itself goes to the Microsoft Graph endpoint <code>https://graph.microsoft.com/v1.0/invitations</code>. You can read more about the message and the parameters <a href="https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/invitation_post">here</a>.

At the end we will return either a status 200 (OK) or 401 (Unauthorized) back to the browser, and the status is used in the web page to provide some feedback on the process to the user.

In the simple example I have done here, the token validation process is simply checking if the provided token is in a list of tokens stored in blob storage. Clearly this could be a lot more sophisticated. It would also be possible to add the people that sign up to a database and so on. For simplicity, we have skipped that here.
<h3>Conclusions</h3>
We have demonstrated that it is pretty easy to set up a self-service sign-up system for Azure Active Directory B2B. The system consists of an HTML form and a backend Logic App to process the request. While there are many additional features that can be added in terms of token security and database logging, it is fully functional.

Let me know if you have questions/comments/suggestions.]]></content:encoded>
    </item>
    <item>
      <title>New Web App SSL Settings (Government and Commercial)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/new-web-app-ssl-settings-government-and-commercial</link>
      <pubDate>Wed, 13 Jun 2018 13:13:41 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2115</guid>
      <description><![CDATA[It is well known that NIST recommends disabling TLS 1.0 and for many Government organizations it is...]]></description>
      <content:encoded><![CDATA[It is well known that <a href="https://www.nist.gov/news-events/news/2014/04/nist-revises-guide-use-transport-layer-security-tls-networks">NIST recommends disabling TLS 1.0</a> and for many Government organizations it is a requirement to do so. In the past, it was not easy to disable TLS 1.0 in Azure Web Apps, and I have spent some considerable effort describing how one could <a href="https://blogs.msdn.microsoft.com/mihansen/2017/12/01/disabling-tls-1-0-in-azure-web-app-using-application-gateway-powershell-automation/">control the TLS settings using an App Gateway</a>. Very recently, a new feature in Azure Web Apps let's you control the minimum TLS version directly in the portal. The feature is rolling out across both Azure Commercial and Azure Government. You can read more about it in <a href="https://blogs.msdn.microsoft.com/appserviceteam/2018/05/02/breaking-change-for-sni-ssl-hostnames-on-azure-app-service/">this blog post</a>.

I don't normally spend time on reporting every new feature of various services, but since I have suggested other solutions in the past I wanted to make sure that it is clear that if the main goal is to control the TLS version, you can simply use the settings in the portal. I will be demonstrating it here with a web app in usgovarizona. Make sure you validate in your region. If the update has not been rolled out yet, it will be soon.

If you create a new Azure Web App and scan it with <a href="https://www.ssllabs.com/ssltest/">SSLLabs excellent tool</a>. You will see that TLS 1.0 is enabled:

<img width="512" class="aligncenter size-large wp-image-2125" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/05/tls10-is-on-1024x238.png" />

In the portal you can change the minimum TLS version for your app:

<img width="768" class="aligncenter size-large wp-image-2345" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/05/tls-switch-1024x543.png" />

And if you repeat the SSLLabs test (give it a few minutes before you try and remember to clear the cache):

<img width="512" height="683" class="aligncenter size-full wp-image-2415" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/05/tls-12-only.png" />

Notice that only TLS 1.2 is on.

And that's it. If you have been using app gateways in front of your web apps with the sole purpose of turning off TLS 1.0, you can remove them and use the feature built into web apps. There of course many other uses of app gateway that you may be utilizing. You may for instance be using the WAF version of the app gateway, in which case you should keep the gateway and you can continue leveraging those features.

Let me know if you have questions/comments/suggestions.]]></content:encoded>
    </item>
    <item>
      <title>Firely Vonk FHIR Server adds Cosmos DB (Mongo API) Support</title>
      <link>https://docs.microsoft.com/archive/blogs/mihansen/firely-vonk-fhir-server-adds-cosmos-db-mongo-api-support</link>
      <pubDate>Fri, 08 Jun 2018 12:25:23 GMT</pubDate>
      <dc:creator><![CDATA[Michael S. Hansen]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mihansen/?p=2365</guid>
      <description><![CDATA[If you are regular reader, you will know that I have been working with Fast Healthcare...]]></description>
      <content:encoded><![CDATA[If you are regular reader, you will know that I have been working with <a href="https://www.hl7.org/fhir/">Fast Healthcare Interoperability Resources (FHIR)</a> servers. In one post, I discussed how to <a href="https://blogs.msdn.microsoft.com/mihansen/2018/04/20/fhir-server-in-azure-paas/">set up Firely's Spark and Vonk Servers using Azure PaaS services</a>. I tried to deploy the <a href="https://fire.ly/vonk/">Firely Vonk server</a> using both <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction">Cosmos DB</a> and <a href="https://azure.microsoft.com/en-us/services/sql-database/">Azure SQL</a> as backend stores. At the time, only SQL Server was officially supported, but Firely has since added support for Cosmos DB (Mongo API) as of <a href="https://docs.simplifier.net/vonk/releasenotes.html">release 0.6.5.0</a>. Please read about the <a href="https://docs.simplifier.net/vonk/configuration/db_cosmosdb.html#configure-cosmosdb">details and limitations of Cosmos DB support</a>. Here is the scenario that you can easily deploy using PaaS components in Azure:

&nbsp;

<img width="512" class="aligncenter size-large wp-image-2395" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/fhir-vonk-cosmos-1024x573.png" />

If you would like to try it out, you can start with my <a href="https://github.com/hansenms/fhir-azure">fhir-azure GitHub repository</a>. Specifically, have a look at the <a href="https://github.com/hansenms/fhir-azure/tree/master/vonk-cosmosdb">Vonk with Cosmos DB configuration</a>. You can deploy this in either Azure Commercial or <a href="https://azure.microsoft.com/en-us/global-infrastructure/government/">Azure Government</a> using the deploy buttons on the GitHub page.

The template will deploy the infrastructure (Web App and Cosmos DB) and configure application settings (connection strings, etc.), but it doesn't actually deploy the Vonk server itself. You will need to <a href="https://simplifier.net/vonk/download">download Vonk</a> and purchase a license or get trial license. After downloading you will have a zip file (<code>vonk_distribution.zip</code>) and a license file. Drag and drop the license file onto the zip file and it will be added to the archive. Then do a <a href="https://blogs.msdn.microsoft.com/benjaminperkins/2017/12/28/deploy-to-an-azure-app-service-using-kudu-and-a-zip-file/">zip deploy using the Kudu console</a> on your web app.

After deploying, direct your browser to the URL of the web app hosting the Vonk server. The first time it will take the Vonk server a few minutes to initialize. It may actually take long enough for your request to timeout, but give it a few minutes and try again. You should see the front page of the Vonk server:

<img width="512" class="aligncenter size-large wp-image-2405" alt="" src="https://msdnshared.blob.core.windows.net/media/2018/06/vonk-server-frontpage-1024x547.png" />

You can then use <a href="https://www.getpostman.com/">Postman</a> or your favorite API interaction tool to query the Vonk server.

If you would like to add API management to your Vonk server, you can read <a href="https://blogs.msdn.microsoft.com/mihansen/2018/05/09/fhir-server-with-azure-api-management/">my blog post about that</a>. The basic steps are:
<ol>
 	<li>Convert the FHIR server conformance metadata to a swagger file using <a href="https://github.com/bobby-brennan/fhir-swagger">fhir-swagger</a>.</li>
 	<li>Import API definition into <a href="https://azure.microsoft.com/en-us/services/api-management/">Azure API Management</a>.</li>
 	<li>Modify policies to make sure URIs are properly re-written on request and response.</li>
</ol>
<h3>Conclusions</h3>
This blog post is really just a bit of great news. You can now use Cosmos DB with Vonk server in Azure. It is easy to set up with the templates provided here. For Government agencies, all the services used <a href="https://github.com/hansenms/fhir-azure/tree/master/vonk-cosmosdb">here</a> (App Service, Cosmos DB, API Management) have <a href="https://www.fedramp.gov/">FedRAMP</a> accreditation.]]></content:encoded>
    </item>
  </channel>
</rss>