3MW (Authentication for Quarto Projects on Azure)

3 Minute Wednesdays is brought to you by

R in 3 Months Starts March 13

The twice-annual cohort-based program that has helped hundreds of people from around the world learn R starts soon. Learn to wrangle, visualize, and report on data – all in R. Get 10% off with the coupon code 3MWSPRING2025.

Guten Tag!

Many greetings from Munich, Germany. In today’s newsletter, we want to add authentication to the Quarto project we deployed last week. If you recall, we took a simple Quarto book/website and deployed it via Azure Static Web Apps. And with that set up, it’s actually super easy to add a layer of authentication in front of that.

But before I show you how that works, it’s time for my regular announcements.

DCMC 4 finished

This week, I uploaded the final lesson of my data cleaning master class. It ties together all the things we have learned throughout the lessons of Part 4. What’s more is that it applies the lessons to a real-world scenario where we run an analysis on time series data.

If you’re interested in leveling up your skills regarding time-related data, then you can join 100+ learners via

And as a little celebration that Part 4 is complete now, you can use the code “DCMC4” to get 10% off. Also, this code is only valid until March 2.

PDFs to DataFrame

Also, this week I released a new video that shows viewers how to use the {ellmer} package to

  • extract specific informations from texts & PDFs and

  • bring that into a DataFrame format.

You can check out the video at

One config file to rule them all

Now, let’s get back to adding authentication to a Quarto website. It’s actually not as hard as you’d think. Everything is governed by one single JSON file called staticwebapp.config.json.

Basically, what you need to do is fill this JSON file with specific keywords and values. That way, your website will change all kinds of settings. And that’s how you can easily add authentication.

And the good news is that you don’t have to know all the keywords yourself. Inside the Azure documentation, there are lots of config snippets for all kinds of use cases. For example, there’s a config snippet to “restrict access to the entire application.”

Sounds exactly like the thing we want. Here’s how it looks.

Understanding the routes

Now, this might feel intimidating. But there’s actually a very simple logic to the snippet we’ve just seen.

You see, via the routes setting you can define specific rules for how website visitors should be routed. Here, the routes settings are only filled with one setting, namely this:

Here, the route is defined by / followed by anything (as denoted by the asterisk.) This means that users wanting to access, say, https://website.com/subsite, will be targeted by this rule. You know, because our URL root https://website.com is followed by /*.

And via the allowedRoles setting inside the routing rule, we can specify which kind of roles a user must have to access the desired page. Here, only users with the role “authenticated” are allowed. This role is already build into any Azure Static Web App.

Can I add other routes?

To make this example a little more clear, let’s play around with the routes. We could say that the start page index.html is available to anyone. But all other sites are restricted to authenticated users.

In that case we need to add more rules to the routes settings. Here’s how that could look:

In our Quarto book setting this would mean user can access the start page but no other. But due to the fact that Quarto saves all the style files of any website inside a separate directory and not directly in a file like index.html, the page will look ugly to the unauthenticated users.

This happens because the user then doesn’t have permissions to access the style files. You can avoid that kind of behavior by making only the index.html file self-contained by adding embed-resources: true inside the YAML header of index.qmd. But for now, let’s just assume that we want to restrict all pages.

What happens to unauthenticated users?

This begs the question “What happens to unauthenticated users?”. Well, the simple answer is that they get denied access. The more specific answer is that the server behind our Azure static web app will return a “401 Unauthorized” response.

Here, 401 is the standard status code that all web applications know and use. But we don’t want the user’s browser to just get this message. Instead, we want to tell it to maybe first authenticate somewhere else and come back after that.

This means that instead of serving the user with a “401 Unauthorized”, we want to serve the user’s browser with a “302 Moved Temporarily” status. Additionally, we want to tell the browser where things were moved to. That way, the browser knows where to redirect its request to.

Here, the redirect will lead to https://website.com/.auth/login/aad. This is the standard authentication with Azure Active directory (nowadays called EntraID). For now, you don’t need to know this service.

All you need to know is that it’s a service that can store user credentials. Also, the URL the user is then redirected to will prompt the user to authenticate with this service.

Integrate config into Quarto

So now that we know how to read the config file, let’s talk about how to integrate it into your Quarto project. You see, Azure static web apps currently only looks at the rendered _book directory in your repo on GitHub.

But your config file will not be automatically copied to this directory when the project is rendered. Hence, you need to do two things.

  1. Create the staticwebapp.config.json in the root directory of your project

  2. Modify your _quarto.yml file as follows:

This will instruct Quarto to copy the config file into the _book directory when the project is rendered. Now, all that’s left to do is to re-render your project and push all the changes to GitHub.

Did it work?

This begs the question: “Is our project secure now?” Well, let’s check. First, we make sure that the corresponding GH Action ran successfully:

Then, we can head to the URL of our hosted project. This is how we’re greeted now:

You may have seen such a window at your workplace before. Congrats, you now understand that the service behind this is Azure Active Directory (EntraID).

Now you’ll have to login with a Microsoft account. Once you click the button, you’ll see that it asks you to grant permissions.

And once you grant the permissions, you are redirected to your website. This time you can see your Quarto project, though.

And in case you’re wondering: You really are authenticated at this point. You can check this by heading to https://website.com/.auth/me. This page now contains a JSON with your user credentials.

Hooray! We have a first layer of authentication now. But it doesn’t stop anyone with a Microsoft account to access our page. After all, we never specified a specific user pool that can authenticate successfully. Let’s talk about this next week.

As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me on LinkedIn or on Bluesky.

See you next week,
Albert 👋

Enjoyed this newsletter? Here are other ways I can help you:

Reply

or to participate.