App Registrations vs. Enterprise Applications

In Microsoft Entra ID (formerly Azure AD), there are two menu options that look very similar – App Registrations and Enterprise Applications. When I first started working with Azure – I wondered what Enterprise Applications were and the documentation wasn’t satisfactory.

Software development tutorials frequently had me add new App Registrations, so I had a pretty good idea what they were for – but Enterprise Applications were a mystery.

When you add a new App Registration, you are prompted to decide if you are publishing a Single tenant or Multitenant application. This is the key to understanding Enterprise Applications.

An App Registration is something the publisher of the application uses. An Enterprise Application represents the consumer’s view of that application. If you specify Single tenant – an Enterprise Application will be created in parallel with the App Registration once you (or any user from your Entra ID tenant) login to the application.

If you create a new App Registration called MyApp and login to that application and then go the Enterprise Applications section, you will see an Enterprise Application has been created for MyApp. The Enterprise Application is used by administrators to control user access to the application. For instance, an administrator can use the Enterprise Application to set up mapping so that only certain users or groups can access the application. In short, App Registration is used by software developers and Enterprise Applications are used by administrators.

The Multitenant application example may be more clear. If you publish your application as Multitenant, when someone from another Entra ID tenant logs in – an Enterprise Application will be created in their Entra ID tenant, but not an App Registration. The publisher is the only tenant where an App Registration exists, but (in a Multitenant scenario) – there can be many Enterprise Applications (one per consuming tenant) where administrators in different tenants can control their users’ access to the application.

Each of these unique Enterprise Application (in different consuming tenants) will get a unique Object ID, but the Application ID in the Enterprise Application points back to the Application (client) ID of the referenced App Registration.

Understanding B2B vs B2C authentication

When you have a “user account”, that really means that you are listed in an authentication directory. A directory is basically a list of usernames and passwords. (For simplicity, ignore SSO, MFA and “password-less” for sake of this discussion.)

B2C (Business to Consumer) can be thought of as a “two-party” relationship. When you sign-up for a Facebook account, you and Facebook are the only parties involved in that relationship. Other examples of B2C users are:

  • Instagram
  • Twitter/X
  • Microsoft*
  • Google*
  • GitHub

* These can be tricky because Microsoft and Google also offer B2B accounts.

B2B (Business to Business) can be thought of as a “three-party” relationship. If you’re company uses Microsoft 365, your user account for that involves Microsoft (who hosts the directory), your employer (who administers the directory), and you. Incidentally, this account has to do with Microsoft but isn’t a “Microsoft Account” because that’s the proper name for their B2C offering.

In a B2C system, you (the user) choose to sign up for the account and only you can delete your account. In the case of your job providing you a Microsoft 365 account (B2B), an administrator issues the account to you and, if you leave – they can (and should) delete your account.

Note that there are plenty of times that B2C authentication is used in a business environment. For instance, if you use GitHub to store source code for a work application – you grant permissions (which is authorization as opposed to authentication) to someone’s GitHub account, which they created themselves and wasn’t issued to them by your company, so – B2C.

Some larger companies have “approved vendor lists”. Instead of being able to purchase from any vendor, you are limited to approved vendors. This is kind of like B2B authentication. In a B2B authentication system, you can only grant permissions to users listed in your corporate directory. Note that – just like being listed on the approved vendor list doesn’t mean that anyone has bought anything from you, being part of the B2B directory doesn’t grant you permission to access anything – it’s a necessary first step.

.NET – Framework vs. Core

I find myself trying to explain this a lot, so I thought I’d put it “in writing” for future reference. This is not intended as a technically complete answer but a starting point to understanding what these terms refer to.

I usually start this by saying “Microsoft is bad at naming things”. The .NET Framework (.NET is a pretty bad name to begin with. Even DotNet would have been better. Who comes up with a name that begins with a period?) has been around since 2002. It evolved through many versions but around .NET 4.6 – Microsoft came up with a replacement framework that they decided to name “.NET Core”. It’s much easier to understand this with a visual, so take a look at this timeline in this Tweet –

The .NET Framework versions are in green. Then came the .NET Core versions in purple. Understanding the version sequence is confusing. For instance, .NET Core 3.1 is newer than .NET Framework 4.8.

After .NET Core 3.1 – Microsoft decided to eliminate “Framework” and “CORE” and just call it .NET (starting with version 5). Since this timeline was produced, .NET 6 and .NET 7 have been released and .NET 8 is on the way. To be clear, .NET 5 and above are the later versions of .NET Core with the name changed. There won’t be any .NET Framework versions delivered after 4.8.

Short version:

.NET Framework is the older technology

.NET Core is the newer technology. Starting with version 5, they dropped the “Core” but you can think of .NET 5 as .NET Core 5, and .NET 6 as .NET Core 6, etc.

Azure B2C error: “The reason phrase must not contain new-line characters”

Hopefully this will save someone else some time. I started seeing this error message from Azure B2C when trying to authenticate a user. The error message wasn’t very helpful, but the cause was pretty simple. I had allowed a Client Secret to expire in the B2C App Registration. As soon as I generated a new one and started using that – authentication started working again.

Evaluation Environments

Almost everyone is familiar with the concept of a QA environment, but I’m going to bring up the need for what I’m going to call Evaluation environments. (If there’s already a industry term for this that I’m not famliar with – let me know at

I’m going to define an Evaluation environment as where the design of a new feature is evaluated. (QA is where the implementation or execution of that design is verified.)

With QA, the expectation is for this feature to continue downstream eventually ending up in production. We may have to correct some errors first, but the design has already been accepted and is expected to flow into production at some point.

Evaluation is a place to test a new feature’s design. Things often make sense in theory but once you see how they actually work, it may be obvious that the design is flawed and needs to be re-worked. In some cases the feature will just be abandoned.

I’m going to talk more about “environments” in a future post, but the short version might be “some kind of web server where the code can be deployed so that someone who’s not a developer can interact with the new feature”. An Evaluation environment should be considered “disposable”.


Alternative build agents for Azure Pipelines

Non-technical overview

Azure DevOps is a Microsoft service developed prior to their acquisition of GitHub. There’s a lot of overlap between the two services, and – even though it seems inevitable that GitHub is the future, there are a lot of organizations still using Azure DevOps.

Azure Pipelines is a part of Azure DevOps where you can build and test code projects. (When programmers use the word “build”, they mean to convert code written by a human programmer into something that can run on a computer.) “CI/CD” has recently become a buzzword in the software development community. It stands for Continuous Integration/Continuous Deployment. Azure Pipelines is the part of Azure DevOps that provides CI/CD services.

The “building software” part of CI/CD requires build agents. A build agent is a computer used to build software, but a it’s a different computer than one used by a human programmer to write code. Azure Pipelines maintains a pool of VMs that can serve as your build agent. When a build process is triggered, one of these is temporarily allocated to your process. It does your build and then reverts back to the pool. (CI/CD is all about automating processes. All of these happens “auto-magically” as directed by a script.)

The VMs provided by Microsoft will meet most needs, but not all. I’m working on project for a client where the amount of RAM provided in the Microsoft-hosted agents wasn’t enough and the build process was failing because it ran out of memory.

When the Microsoft-hosted agents won’t meet your needs, you can plug you own “Self-hosted agents” into the process. This can either be physical or virtual machines that you set up, configure and maintain, or – you can take advantage of Azure virtual machine scale set agents. This lets you specify a “size” of Azure VM (allowing you to specify the processor, amount of RAM, amount of storage, etc.) and tells Azure DevOps to use that for your build agent.

This option is more expensive and requires more administration on your part, but if you have needs beyond what the Microsoft-hosted agents can handle – it’s nice to have this option. The rest of this post will recap some of the technical issues I ran into setting this up recently.

Technical details

This is a good starting point for background on Azure Pipelines Agents. If you follow the link in the Microsoft-hosted agents section, you can find out about the specific hardware allocated to these VMs. As of this writing, the amount of RAM is 7GB. This client has a particularly large Angular project that required more RAM than that.

I didn’t want to actually “self-host” in a physical sense, so I went with the Azure virtual machine scale set option. Here is the page with the specific instructions. There’s a lot of information here, but basically it consisted of three steps:

  1. In the Azure portal, create the scale set.
  2. In the Azure DevOps portal, set up an agent pool pointing to what you created in #1.
  3. Change your pipelines to use the new agent pool.

Create the Scale Set in Azure

The instructions walk you through using the Azure Cloud Shell to create the scale set. The az vmss create statement is the one to focus on. The vm-sku setting is probably the most important one. This is what specifies the “size” of the VM. Start here to determine which size will work best for your needs. (Don’t agonize over this too long at the beginning. It’s pretty simple to change this setting on your scale set.) Make sure to pay attention to the usage price of your chosen size. (Here’s the pricing table for Linux VMs.)

The instance-count setting only specifies the number of instances initially created. Once you “hand control of the set over to Azure DevOps” (in step 2). It will override this instance count.

Once you’ve successfully run the az vmss create statement. You’re done with step 1. Azure DevOps will handle everything else (including installing required software on the VMs).

Create the Agent Pool in Azure DevOps

The instructions in the article above are pretty good. Here are some notes of things I ran into:

  • You will need to be an Agent Pool Administrator to create the new Agent Pool. If you are missing this, you will get to the end of the form and get an error when you submit saying you need “Manage permission”. If you get this, have the owner of the organization use the Security button on the Agent Pools page (top right – next to blue Add Pool button) to grant this permission to you.
  • The Maximum number of virtual machines in the scale set setting overrides the instance-count setting from step 1.

Change your Pipelines to use the new Agent Pool

Here is the relevant part of the Azure Pipelines YAML schema. Basically, if you are using a Microsoft-hosted agent pool, you only specify the vmImage value.

If you want to use a self-hosted agent pool, you need to specify the name. This is the name you provided in step 2 and the name that shows up in the list of Agent Pools in Azure DevOps.

In the case shown above, your YAML would contain this:

pool: Self Hosted Scale Set pool

Final Considerations

The 3 main settings on the Azure DevOps Agent Pool will probably involve some trial and error depending on your specific needs.

  • Maximum number of virtual machines in the scale set
  • Number of agents to keep on standby
  • Delay in minutes before deleting the excess idle agents

If you set the Number of agents to keep on standby to 0, you won’t be paying for instances to sit idle, but your Pipeline runs will sit in the Queued state for a little while to give Azure time to “spin up” an image for you. (In my case, this was about 5 minutes.) You can monitor the number (and status) of instances in the Azure portal by finding the Virtual machine scale set and clicking on Instances on the left-side menu. (Hint – if you can’t find it, look at the Resource Group you specified in the az vmss create statement.)

Authentication vs. Authorization

These aren’t just “10 dollar words” that both start with the letter “A”. If you have an application, you need to understand the difference between these two things.

Let me try to explain this way. Not too far from where I live is a semi-famous (infamous?) bar called the Flora-Bama, so named because it’s on the state line between Florida and Alabama. For purposes of this, imagine that the drinking age in Florida is 18 (it’s not) and that the drinking age in Alabama is 21 (it is). (The Flora-Bama is pretty big and I think there are bars on both sides of the state line. Let’s assume that’s true.) In this scenario, if you’re 19 – you can buy a beer from the bar on the Florida side, but not from one on the Alabama side.

Imagine the doorman out front is checking IDs and putting wristbands on everyone – yellow if you’re 18-20 and green if you’re 21+. That’s authentication. He checked your ID and identified you but didn’t make any decisions about what you could and couldn’t do.

If a yellow-banded 20 year old walks up to an Alabama-side bar, the bartender there will refuse to serve the patron based on the color of the wrist band. This is authorization. The bartender doesn’t check the ID again, but just makes an authorization decision based on the previous authentication.

You can (and in many cases probably should) outsource your application’s authentication function. When you see sites let you “Login with Google” or “Login with Facebook”, that’s what’s happening. They are letting Google or Facebook handle the authentication, but the actual site still has to decide what the user is permitted to do.

The simplest ramification of “outsourcing authentication” is – one less password for your site’s users to remember. More importantly, if you aren’t storing passwords – they can’t be stolen if your data is breached. Of course, you’ll need to decide if all of your users are likely to have a Google or Facebook account (or whatever service you choose to trust to authenticate).

What is Circlebox?

Circlebox is a web startup that I founded a couple of years ago. Hard to say exactly when, because I’ve been thinking about it for several years and have been actually writing code and using it myself for about a year and a half. I’m still honing my elevator pitch – this is the longer version. I’ll start with some examples of the problems it’s designed to solve.

Scenario #1: Headcount and $10

One of the earliest examples I can give is of coordinating a Cub Scout campout.  The pack leaders needed to know who was going.  At the pack meeting, we got a lot of “let me check our schedule with my wife and I’ll email you”.  Because there are multiple leaders, not everyone emails the same person, so the leaders keep emailing revisions of an Excel spreadsheet back and forth.

We also needed to collect $10/person to cover hot dogs, hamburger patties, buns, mustard, etc.  At the meeting, nobody has their checkbook with them.  At the campout, a few people remember to bring checks, but most people (of the people that pay) bring 20 dollar bills straight from the ATM so making change is a problem.

We looked at some existing websites, but couldn’t find anything that was just right.

What about Evite?

Sites like Evite would handle the head count, but not collecting the money.  In addition, Evite is really targeted at one user coordinating an event.  If you have multiple coordinators – you could share your password, but only one email address will get the notifications.

If you are a group leader for multiple groups, it might be OK to share your password with John, since John helps you run the Scout pack, but what if you are also the baseball coach and want to coordinate events for that. John isn’t affiliated with the baseball team and really shouldn’t see the contact info for the people in that group.

What about PayPal?

Sites that would collect money mostly used PayPal.  Not only is PayPal kind of expensive to use – I couldn’t even get our Pack set up with PayPal.I’ve had a personal PayPal account for years. When you are setting up a PayPal account for an organization, you have to say what kind of Business Type you are.  “Non-profit” was the closest match.  Apparently to PayPal, that means “charity” because now they wanted our 501c3 paperwork to prove that we were OK to accept donations. But I didn’t want to accept donations, I wanted to collect $8 for hot dog buns.

In my day job, I worked with accounting software and was familiar with ACH processing (how the gym automatically drafts your monthly membership fee from your checking account).  Since we wanted to collect money from people that we already knew in the real world (and would take a check from) – this seemed OK (and the transaction fees are significantly cheaper).

PayPal’s sweet spot is paying for a guitar amp that you bought from a guy in Seattle on eBay.  Since you don’ t know the guy in Seattle, you might need some recourse from PayPal if doesn’t actually ship the amp. Since we’re only exchanging money between people that already know each other in the real world, we don’t need that level of protection and the less expensive ACH funds transfer works perfectly for us.


  • Designed for multiple user accounts to administer the same Circles (groups) and for one user account to be able to administer multiple Circles without sharing passwords and emailing spreadsheets back and forth.
  • Will handle electronic invitations and responses to events, including allowing Circle members to pay online via ACH.

Scenario #2:

In other group that I help run, I remember the treasurer saying “I’ve got a good list of who hasn’t paid, but I don’t really have a good way of emailing them individually. BCC won’t work because different people owe different amounts. I really need to be able to email individual statements.”


  • Will let you email subsets of Circle members like “only those who haven’t paid” or “only those who haven’t replied to the invitation”.

Scenario #3:

Several years ago, I served on the governing board for our local youth baseball league.  I had been on the board for a couple of years and I knew that this was when we normally started meeting, but I hadn’t heard anything. When I finally talked to the president, she said “we’ve had 2 meetings and wondered where you were.”

Turns out, someone had entered my email address incorrectly on the first email and all communication from that point on had been “Reply to All” from the original email. I never got any of them.

There’s also a flip side to this issue. My kids are involved in Boy Scouts and the local council asked for volunteers to come to a meeting to discuss how they could better use technology. I thought “there’s something I can help with” so I went. When I got there, there were about 50 other guys there and the conversations I heard there were of the “my hard drive is bigger than yours” type. I quickly decided that they could make it without me. Unfortunately, I had put my email on a sign-in sheet which the leader then forwarded to everyone who attended.

Because these were technical types, just about everyone of them made their own personal distribution group from the list and the conversations began. There were many back and forth emails to the group and I had no way of getting my email address off of everyone’s list.


  • Will let you subscribe, unsubscribe and change the email address where you receive notifications.
  • Is “self-serve” so the group leader doesn’t have to make these updates for the group members

More to come, but this should give you the general idea of Circlebox.