Application Registrations

Modified on Wed, 15 Jul at 4:18 PM

ILAP Analytics authenticates users and services with Microsoft Entra ID, which requires two app registrations — one for the analytics API and one for the analytics UI. This page shows how to create and configure both with the Azure CLI (az), including the app roles, exposed API scopes, Microsoft Graph permissions, redirect URIs, and admin consent. It is written for the IT administrator (or identity administrator) preparing an ILAP Analytics environment. Repeat the process once per environment (Dev, Beta, Test, Prod).

Run the script, or run the commands step by step

The commands below are also packaged as ready-to-run scripts in the deployment package under Azure.IaC/Scripts/:

  • Bash (Linux/macOS): setup-app-registrations.azcli
  • PowerShell (Windows): setup-app-registrations.ps1

Edit the CONFIG block at the top of the script (app names, UI URL, tenant), run it, and it performs every step on this page and prints the values for your Bicep parameter file. The commands shown here are in Bash syntax; on Windows either use the PowerShell script or adjust the variable syntax ($env: / $var). The steps that patch nested properties (exposed scopes, app roles, redirect URIs) send a small JSON body to Microsoft Graph — the scripts build that JSON for you.

Prerequisites

You need the Application Developer role in Entra ID to create app registrations. If your organisation uses Privileged Identity Management, activate the role first (My roles → Application Developer → Activate). The final admin-consent step of each app additionally requires Global Administrator or Privileged Role Administrator — if you do not hold that role, ask someone who does to run those two commands.

Sign in to the target tenant:

az login --tenant '<your-tenant-id>'

# Well-known IDs used below
GRAPH_APP_ID='00000003-0000-0000-c000-000000000000'   # Microsoft Graph
GRAPH_EMAIL='64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0'
GRAPH_OFFLINE='7427e0e9-2fba-42fe-b0c0-848c9e6a8182'
GRAPH_OPENID='37f7f235-527c-4136-accd-4a02d197296e'
GRAPH_PROFILE='14dad69e-099b-42c9-810b-d002981feec1'

Set up the API app registration

Step 1: Create the API app registration

Create the registration for the current organisation only, and capture its application (client) ID and object ID into variables for the following steps.

API_APP_ID=$(az ad app create \
  --display-name 'ILAP Analytics API DEV' \
  --sign-in-audience AzureADMyOrg \
  --query appId -o tsv)

sleep 15   # allow Entra to replicate the new object
API_OBJ_ID=$(az ad app show --id "$API_APP_ID" --query id -o tsv)

Step 2: Set the Application ID URI

Expose the API under api://<api-app-id> so the UI can request its scopes.

az ad app update --id "$API_APP_ID" --identifier-uris "api://$API_APP_ID"

Step 3: Add the exposed scopes

Add two delegated scopes, user_impersonation and read. Both use type: User, which corresponds to Admins and users on the "who can consent" option. Generate a stable GUID for each scope and keep them — the UI app is granted these scopes later.

USER_IMP_SCOPE_ID=$(uuidgen)
READ_SCOPE_ID=$(uuidgen)

az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/$API_OBJ_ID" \
  --headers "Content-Type=application/json" \
  --body "{
    \"api\": { \"oauth2PermissionScopes\": [
      { \"id\": \"$USER_IMP_SCOPE_ID\", \"value\": \"user_impersonation\", \"type\": \"User\", \"isEnabled\": true,
        \"adminConsentDisplayName\": \"Access ILAP Analytics as the signed-in user\",
        \"adminConsentDescription\": \"Allow the application to access ILAP Analytics on behalf of the signed-in user.\" },
      { \"id\": \"$READ_SCOPE_ID\", \"value\": \"read\", \"type\": \"User\", \"isEnabled\": true,
        \"adminConsentDisplayName\": \"Read ILAP Analytics data\",
        \"adminConsentDescription\": \"Allow the application to read ILAP Analytics data on behalf of the signed-in user.\" }
    ] }
  }"

The two scopes you defined (user_impersonation and read) are needed later when configuring the UI application, and appear as api://<api-app-id>/user_impersonation and api://<api-app-id>/read.

Step 4: Add the application roles

Add the three app roles below. Use exactly these values (case sensitive). Readers and Writers allow both User and Application members so that applications using app-only tokens (for example managed-identity integrations) can be granted these roles; Admins is users only.

Display name Value Allowed member types Description
Admins Administrator Users/Groups Can read/write data and add Metadata and Metadata Fields/Values
Writers DataWriter Both (Users/Groups + Applications) Can write data to ILAP Analytics but cannot modify Metadata and Metadata Fields/Values
Readers DataReader Both (Users/Groups + Applications) Can read data from ILAP Analytics. Writing is not permitted
ADMIN_ROLE_ID=$(uuidgen); WRITER_ROLE_ID=$(uuidgen); READER_ROLE_ID=$(uuidgen)

az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/$API_OBJ_ID" \
  --headers "Content-Type=application/json" \
  --body "{
    \"appRoles\": [
      { \"id\": \"$ADMIN_ROLE_ID\",  \"displayName\": \"Admins\",  \"value\": \"Administrator\", \"isEnabled\": true,
        \"allowedMemberTypes\": [\"User\"],
        \"description\": \"Can read/write data and add Metadata and Metadata Fields/Values\" },
      { \"id\": \"$WRITER_ROLE_ID\", \"displayName\": \"Writers\", \"value\": \"DataWriter\",    \"isEnabled\": true,
        \"allowedMemberTypes\": [\"User\", \"Application\"],
        \"description\": \"Can write data to ILAP Analytics but cannot modify Metadata and Metadata Fields/Values\" },
      { \"id\": \"$READER_ROLE_ID\", \"displayName\": \"Readers\", \"value\": \"DataReader\",    \"isEnabled\": true,
        \"allowedMemberTypes\": [\"User\", \"Application\"],
        \"description\": \"Can read data from ILAP Analytics. Writing is not permitted\" }
    ]
  }"

Add the delegated Graph permissions email, offline_access, openid, and profile, create the service principal (enterprise application), then grant admin consent.

az ad app permission add --id "$API_APP_ID" --api "$GRAPH_APP_ID" \
  --api-permissions "$GRAPH_EMAIL=Scope" "$GRAPH_OFFLINE=Scope" "$GRAPH_OPENID=Scope" "$GRAPH_PROFILE=Scope"

az ad sp create --id "$API_APP_ID"

az ad app permission admin-consent --id "$API_APP_ID"   # needs Global Admin / Privileged Role Admin

Set up the UI app registration

Step 1: Create the UI app registration

UI_APP_ID=$(az ad app create \
  --display-name 'ILAP Analytics UI DEV' \
  --sign-in-audience AzureADMyOrg \
  --query appId -o tsv)

sleep 15
UI_OBJ_ID=$(az ad app show --id "$UI_APP_ID" --query id -o tsv)

Step 2: Configure the redirect URIs

Add the single-page-application (SPA) redirect URI (the URL of your web UI app) and a public-client / desktop redirect URI (http://localhost/oauth2/callback, used by the IlapAdapter desktop client), and enable the public-client flow. If you use a custom domain for the API, use your UI custom-domain URL as the SPA redirect.

UI_REDIRECT_URI='https://app-ilapanalytics-ui-dev.azurewebsites.net'
DESKTOP_REDIRECT_URI='http://localhost/oauth2/callback'

az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/$UI_OBJ_ID" \
  --headers "Content-Type=application/json" \
  --body "{
    \"spa\": { \"redirectUris\": [\"$UI_REDIRECT_URI\"] },
    \"publicClient\": { \"redirectUris\": [\"$DESKTOP_REDIRECT_URI\"] },
    \"isFallbackPublicClient\": true
  }"

Step 3: Add Microsoft Graph permissions

The UI needs the user's profile to sign them in — add the same delegated Graph permissions.

az ad app permission add --id "$UI_APP_ID" --api "$GRAPH_APP_ID" \
  --api-permissions "$GRAPH_EMAIL=Scope" "$GRAPH_OFFLINE=Scope" "$GRAPH_OPENID=Scope" "$GRAPH_PROFILE=Scope"

Grant the UI delegated access to both API scopes (user_impersonation and read) so it can call the API on behalf of the signed-in user, create the service principal, then grant admin consent.

az ad app permission add --id "$UI_APP_ID" --api "$API_APP_ID" \
  --api-permissions "$USER_IMP_SCOPE_ID=Scope" "$READ_SCOPE_ID=Scope"

az ad sp create --id "$UI_APP_ID"

az ad app permission admin-consent --id "$UI_APP_ID"   # needs Global Admin / Privileged Role Admin

Step 5: Application owners

Register at least one application owner on each registration. Some organisations require at least two permanent employees as owners — follow your corporate policy.

OWNER_OBJECT_ID=$(az ad user show --id 'owner@yourcompany.com' --query id -o tsv)
az ad app owner add --id "$API_APP_ID" --owner-object-id "$OWNER_OBJECT_ID"
az ad app owner add --id "$UI_APP_ID"  --owner-object-id "$OWNER_OBJECT_ID"

Assign users to the application roles

Users and groups are granted access on the API enterprise application by assigning them one of the app roles (Administrator, DataWriter, DataReader). Assign a user with the Azure CLI as follows (repeat per user/group, choosing the role ID from Step 4):

USER_OBJECT_ID=$(az ad user show --id 'user@yourcompany.com' --query id -o tsv)
API_SP_ID=$(az ad sp show --id "$API_APP_ID" --query id -o tsv)

az rest --method POST \
  --uri "https://graph.microsoft.com/v1.0/servicePrincipals/$API_SP_ID/appRoleAssignedTo" \
  --headers "Content-Type=application/json" \
  --body "{ \"principalId\": \"$USER_OBJECT_ID\", \"resourceId\": \"$API_SP_ID\", \"appRoleId\": \"$ADMIN_ROLE_ID\" }"

See User Permissions for what each role can do.

Record your app registration details

Once both app registrations exist, record the following for each environment you set up (Dev, Beta, Test, Prod). These values are needed when you configure the Bicep parameters and the IlapAdapter client software. The setup script prints them all at the end.

Name Environment Usage ClientId / Scope
ILAP Analytics api <env> e.g. DEV Api api://<api-app-client-id>/user_impersonation
ILAP Analytics ui <env> e.g. DEV Web UI and authentication for Winforms <ui-app-client-id>

Authentication settings

These settings are required for connecting to the different environments from the IlapAdapter client software. Record them per environment:

Property Value
Authority https://login.microsoftonline.com/<your-tenant-id>/v2.0
Scopes api://<api-app-client-id>/user_impersonation User.Read offline_access
Api Url Base URL of your analytics API app (use your custom domain if applicable), e.g. https://<api-app-name>.azurewebsites.net/api/
ClientId <ui-app-client-id>

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article