Month: August 2026

Using built-in Authorization in Azure Web Apps

If you publish an Azure web app, it becomes public. If you need to protect your web app to only allow domain-based users to access the application, you can use standard functionality in Azure and Entra. You can even configure the application, so it can only be accessed by either specific users, or users in a specific group.

The steps

Here are the overarching steps:

  1. Create a new Application Registration to represent the web app.
  2. Configure settings in the Application registration and the Enterprise application.
  3. Update Authorization settings in the Web application.

Create a new application registration and Enterprise Application

  1. Create a new app and give it a good name. A recommended pattern is app-FullNameOfTheApplication-ENV-serviceTypeAbbriviation, such as: app-CoolAIStuff-DEV-web.
  2. During creation, you can ignore the value for Redirect URI. for now.

Configure the Application Registration

Branding and properties

Update the Home page URL to point to your web app.

Under Authentication
  1. Click + Add a Platform and choose Web from the fly-out to the right.
  2. The Redirect URIs needs to be the full URL to the startpage of the app with this suffix: /.auth/login/aad/callback. If the url is https://coolaistuff-dev-web.azurewebsites.net the Redirect URI will be https://coolaistuff-dev-web.azurewebsites.net/.auth/login/aad/callback
  3. This following part is due to how you want to implement authentication within your app. This way you can protect your app without any code changes. Under Implicit grant and hybrid flows select ID Tokens (used for implicit and hybrid flows)
  4. Click Configure to proceed.
  5. Under Supported account types make sure to only select the single tenant option. unless you actually need to support other tenants. Lastly make sure that public client flows is not allowed.
Under Expose an API

The setting here is how your web application will communicate with Azure Entra. Make sure you configure everything correctly.

Application ID URI: Simply click the Add-link and then click save in the fly-out to the right. The URI should contain the client ID of the application registration.

Add a scope

  1. Scope name: user_impersonation
  2. Who can consent: Admins and users
  3. Admin consent display name: Access [name of your web app]
  4. Admin consent description: Allow access to [name of your web app]
  5. Repeat for the User settings.
  6. Click Add scope to save it.
Grant consent

To allow the application to use user impersonation, and make it possible for a user to login, you need to grant consent for the application. Under API Permissions, find and click on the “Grant admin consent for [domain name]“ option.

Under Owners

Assign one or more users to be responsible. This is only used for reference, if we want to know who owns an app.

Configure the Enterprise Application

This part is only needed if you want to add functionality to only allow specific users to access your web app. If not, everyone at the connected Entra domain has access. Finding the Enterprise application: Search for the application registration name on the Entra overview page.

Under Properties

Slide Assigment required to Yes. This will stop everyone in the connected Entra domain from gaining access. It will lock access to the users defined under the next step.

Under Users and Groups

Here you configure which users should have access to your web application.

  1. To add a user or a group, simply click + Add user/group at the top.
  2. Click on non selected under Users and groups.
  3. In the fly-out find the user or group you want to add.
  4. Click select and the Assign to add the user/group as being able to access the app.

When you assign a group to an application, only users directly in the group will have access. The assignment does not cascade to nested groups. As a bonus, in any Entra Group you can assing an owner and allow that owner to add or remove users in the group, effectively making them responsible for their own application. This is something that can be blocked by IT security policies though.

Update Authentication settings in the Web application

It is now time to add the protection you configured during application registration setup.

Authentication

  1. Click Add identity provider
  2. Select Microsoft as the identity provider
  3. App registration type, select the Pick an existing… option.
  4. In the dropdown, find your app registration you created earlier. You must use the name.
  5. Client secret expiration. Select Recommended 180 days.
  6. Client application requirement. Make sure Allow requests only from this application itself is selected.
  7. Identity requirement. Make sure Allow requests from any identity is selected.
  8. Tenant requirement. This depends on your needs. Usually you just have your own tenant.
  9. Pick save and start testing the application protection. The first sign is that you might need to login to the application.

If you update any access settings, such as adding a user to a group you have assigned to be able to access the application, it may take some time before the update is picked up and implemented by the app.

Password free connections to SQL databases

In the old days, we used SQL Server Logins to access information. You usually sent the name and password in clear text as part of a connection string. That was 15 years ago.

A much cleaner and secure way is to use Azure Managed Identity. If your service supports it, use it. The following database services supports Managed Identity:

  • Azure SQL Database
  • Azure Database for MySQL
  • Azure Database for PostgeSQL

Example configuration using an Azure Function

Configure your Azure Function

Update the function to use system assigned managed identity. Simply navigate to Identity under settings and enable it.

1
2
This will create an enterprise application in Entra with the given Object ID.

Setting it up using Bicep

Here is a Function App fully configured:

resource azureFunctionApp 'Microsoft.Web/sites@2020-12-01' = { 
  name: funcName 
  location: location 
  kind: 'functionapp,linux' 
  identity: { 
    type: 'SystemAssigned' 
  } 

  properties: { 
    serverFarmId: funcServicePlan.id 
    siteConfig: { 
      linuxFxVersion: nodeVersion 
    } 
  } 
  tags: resourceGroup().tags 
} 

Create a user in your SQL Server

Open a query window into you SQL Server. Add the following query text:

CREATE USER [The-Name-Of-Your-Function] FROM EXTERNAL PROVIDER; 
ALTER ROLE db_datareader ADD MEMBER [The-Name-Of-Your-Function]; 
ALTER ROLE db_datawriter ADD MEMBER [The-Name-Of-Your-Function]; 
ALTER ROLE db_ddladmin ADD MEMBER [The-Name-Of-Your-Function]; 
GO 

The access rights might vary for you scenario. If you get and error about duplicate identities or similar see below.

Verify user creation

You can verify that the user has been added by running this script.

select name as username, 
       create_date, 
       modify_date, 
       type_desc as type, 
       authentication_type_desc as authentication_type 
from sys.database_principals 
where type not in ('A', 'G', 'R') 
      and sid is not null 
      and name != 'guest' 
order by username; 

The new user should show up in the resulting list.

Use it in your code

The easiest way to find what you need is to follow the documentation from Microsoft.

Here is a TypeScript example:

const { DefaultAzureCredential } = require("@azure/identity"); 
const credential = new DefaultAzureCredential(); // system-assigned identity 

export const connect = async (): Promise
<void> => { 
  const baseConfig = { 
    database: process.env.MSSQL_DATABASE, 
    server: process.env.MSSQL_HOST, 
    options: { 
      encrypt: process.env.MSSQL_ENCRYPT === "true", 
      trustServerCertificate: 
        process.env.MSSQL_TRUST_SERVER_CERTIFICATE === "true", 
    }, 
  }; 

  let config = {}; 

  if (process.env.AZURE_FUNCTIONS_ENVIRONMENT === "Development") { 
    // Running locally 
    config = { 
      ...baseConfig, 
      user: process.env.MSSQL_USER, 
      password: process.env.MSSQL_PASSWORD, 
    }; 
  } else { 
    // Running in Azure 
    const accessToken = await credential.getToken( 
      "https://database.windows.net/.default" 
    ); 
    config = { 
      ...baseConfig, 
      authentication: { 
        type: "azure-active-directory-access-token", 
        options: { 
          token: accessToken.token, 
        }, 
      }, 
    }; 
  } 

  return await sql.connect(config); 
}; 

Duplicate identities error

There is a problem when adding the identity as a user in SQL Server. The identity lookup in Entra is done using the name (not the object ID or client ID) and if you have multiple identities with the same name, you get an error.

This is usually due to you having configured the Azure Function to use the Authorization feature. (More information here). When you do this, out of the box, an Enterprise Application with the same name as the function is created. This is not the same Application as the managed identity created above.

The way to solve this is to:

  • Delete the automatically generated Enterprise Application created when you added Authorization. Remember to delete both the Enterprise application and the application registration.
  • Add the identity as a user in SQL Server, as described above.
  • Create a new application registration to be used in Authorization configuration. Tip: Use the same name as the function but put ‘app-’ as a prefix.
  • Configure the Authorization option in the Azure Function and make sure you use your new application identity.

New employer, same old me

vivicta-rgb-logo-green

I am back in consulting. On the 3rd of August 2026 I changed from Permobil to Vivicta. First of all, I would like to thank Permobil for five years of interesting and knowledgeable colleagues. Being part of building something that totally changed how the business do business. Good luck on your way forward.

I was always a consultant. Someone that people asked for to aid and support them, either with my time or my knowledge. I very much look forward to that being my life, even if I am now in the hands of the dreaded time report once again.