The idea for this blog originated from a POC (proof-of-concept) project that we started internally for one of our clients. This Onepoint client has a web application written with the Meteor framework and wants to integrate its authentication component with Azure Active Directory (Azure AD). 

The Challenge

This is the challenge we were given: how can you integrate Meteor with Azure AD?

We started investigating and discovered the there are already some Meteor plugins, which integrate Meteor's authentication with external platforms with Google, Facebook, Github and some more authentication providers (see https://guide.meteor.com/accounts.html#supported-login-services). But unfortunately, there are no officially supported Azure AD authentication plugins. Initially, we have tried one of these plugins, the accounts-google plugin, and it works well.

Two Strategies

There are two ways to integrate Meteor with Azure AD login:

  1. You can create a Meteor application, which embeds the Microsoft Authentication Library for JavaScript version 1.4.1 and uses it to authenticate the users.
  2. You can use Azure App Service's built-in authentication and authorisation support

The first option involves writing code for triggering the login popup and then handling the events triggered by the login event. Using this option, you need to retrieve the profile information from Active Directory using the access token, and this requires a bit of code. Apart from coding, you also need to set up an App Registration in Azure with its authentication properly configured.

The second option requires you to write no authentication code, but you need to create an App Service as well as an App Registration in Azure.

We are going to explore the second option.

Azure App Service with built-in Authentication

The usually excellent Azure documentation explains how the built-in authentication works:

"The authentication and authorisation module runs in the same sandbox as your application code. When it's enabled, every incoming HTTP request passes through it before being handled by your application code."

What does this mean in our case? The application code is, in our case, the Meteor web application. This web application will only be accessed when Azure's authentication and authorisation module authenticated the user.


There is a complete separation of concerns here: authentication and application code are independent. Citing the Azure documentation again:

"The authentication and authorisation module runs in a separate container, isolated from your application code. ... Because it does not run in-process, no direct integration with specific language frameworks is possible; however, the relevant information that your app needs is passed through using request headers ..."

Even though both modules are completely separate, and there is no sharing of code, data is passed from the authentication and authorisation module to the application module. So we can use the data that is passed from the authentication and authorisation module to the application module to support user authentication and management in our Meteor web application.

Azure Meteor Web App Workflow

Now that we have an idea of how you can setup the Web application in Azure and setup its authentication, we are going to present the whole workflow using BPMN:

These are the steps highlighted in the diagram:

  1. The user opens the application URL
  2. The user gets redirected to the Azure AD Login page
  3. If the user is already logged in to Azure AD, he /she is asked to choose an account
  4. If the user is not logged in to Azure AD, he /she logs in and chooses the account this way
  5. The user is asked whether he / she wishes to remain logged in.
  6. The business application (in our case, the Meteor application) is accessed.
  7. The business application fetches the JWT (JSON Web Token) token (See more info on JWT tokens: https://jwt.io/).
  8. The user details get extracted from the JWT token. This may include email, first, last name,  etc.
  9. If the user does not exist, it gets created in the Meteor database (MongoDB).
  10. The Meteor user is propagated on the server and client side. So the user data is at this point available in-memory both on the client and server-side.

Steps for Creating a Meteor Azure App Service

Creating a Meteor Azure App Service involves some steps:

  1. Creating a Meteor web application.
  2. Creating a Docker image where the Meteor web application is deployed.
  3. Create an Azure Container Registry
  4. Create an Azure App Service plan with a web application using the docker image from the create container registry

We are not going to detail all steps in the next chapters, just focus on some of the steps.

These next sections assume that you are familiar with the concepts of Docker. If not we suggest you read about it.

Creating a Meteor web application

We have provided an example application that you can access on:

https://github.com/onepointconsulting/azure-meteor-login

This is a React Meteor web application created with the command:

meteor create --react <app-name>

More information about how to create React applications can be found here:

https://www.meteor.com/tutorials

Creating a Docker Image

This involves creating a Dockerfile file in your project. The file we used in our demo project is here:

https://github.com/onepointconsulting/azure-meteor-login/blob/main/Dockerfile

This Docker file then needs to be built and pushed to the Azure Container. We have automated this process using a simple batch file. This batch file is available here:

https://gist.github.com/onepointconsulting/91b31cc10ff8d1b1e95be1abafd1d9fc

Create an Azure Container Registry

The Azure Container Registry can be created using the UI (see here) or optionally you can also use the Azure az command-line tool. The command looks something like this:

az acr create --name <registry-name> --resource-group <resource-group> --sku Basic --admin-enabled true

You can view the credentials of the newly created resource with:

az acr credential show --resource-group <resource-group> --name <registry-name>

And then you  can login to it using the docker command:

docker login <registry-name>.azurecr.io --username <username>

Create an Azure App Service plan with a web application

The Azure App Service plan can be created using the UI (see here) or optionally you can also use the Azure az command-line tool:

az appservice plan create --name <plan-name> --resource-group <resource-group> --is-linux

Finally, you can create the web application in your App Service, which uses a specific Docker image in your registry:

az webapp create --resource-group <resource-group> --plan <plan> --name <webapp-name>  --deployment-container-image-name <registry-name>.azurecr.io /<image-name>:latest

After going through all of the creation steps, you should end up with an Azure App Service that looks like this:

Adding Authentication to the Azure Service

At this point in time, we should have a Docker based Azure Service and a Docker image with a Meteor application inside of it.

Now it is time to add the authorisation / authentication layer to it. This can all be done using the Azure UI itself.

You need to access in the Azure portal your App Service. 


Then you look for the Authorisation / Authentication menu item on the left:


You turn the App Service Authentication on:

Then you have to select an authentication provider. We selected "Azure Active Directory" and "Express" Management Mode:

The Express mode will effectively create an Azure App Registration in the background and associate it with your Azure App Service.

This is the Azure App Registration we created in our project:

Finally, we need to set the "Allowed External Redirect URLs" without which you cannot get your web application working:

Meteor User Login

As we have mentioned in the "Azure Meteor Web App Workflow" section, the Meteor application needs to get the user profile data and create a user object which is propagated on the client and server side.

This is done in three steps:

  • Fetching the JWT token

In this step, we send from the client to the server a request to a REST method implemented in Meteor, which reads all the headers and returns these to the client as JSON. The code for the REST method looks like:

The resulting JSON looks like:

  • Invoke the Meteor login method with data extracted from the above JSON (e.g., principal name):

  • Register a login handler on the server side, which checks if the user is already in Meteor's user account database and if not, creates it. Whether the user is in the database or not, the login handler returns the user id. The rest is handled automatically by the Meteor framework, which registers the user on the client and server side.

Conclusion

Azure is a very powerful, well-documented platform which offers authentication / authorisation services, that act independently from web applications running in Docker containers. This allows code-free authentication / authorisation integration with your web applications.

If these applications then need to access the output of the authentication process, they can do so via standard JWT tokens again without direct integration with any Azure API.

At a more personal level, it took me some time to grasp all Azure and Docker related concepts, that you need to be able to perform this type of integration. So this high-level of integration "comfort", needs a good measure of training and domain knowledge.

Appendix

We have also created a small video that shows how our toy app works in real life. Please check it out.