CAMPUX Cloud Bootcamp Lab · Identity & Governance ← All labs
Hands-On Lab · Intermediate
~35 min · Free tier · Cloud Shell + browser
CLI & Bicep · torn down at the end
Identity & Governance · Lab B

Sign in with Microsoft, write no auth code.

Campux staff shouldn't get yet another password. They should sign in with the Microsoft identity they already have, and the app should never see it. That's single sign-on over OpenID Connect — and App Service can do the whole handshake for you, so the portal holds no login code at all.

Fig. 1 · App registration → SSO with Entra ID
sign inissues tokenUsera Campux engineerApp registrationMicrosoft Entra IDWeb portalprotected by sign-inthe portal trusts Entra, not a password table
● Screen walkthrough Not yet recorded · ~8 min
Reel · 00:00 / 08:00

Register an app, wire OIDC single sign-on to Azure, and complete a login round-trip end to end.

Placeholder — the page below stands alone until the reel lands
Why

An app registration is the front door to SSO

Before Microsoft Entra ID will sign users into your application, it has to know the application exists and is allowed to ask — that record is an app registration. With one in place, OpenID Connect lets a user authenticate with their existing Microsoft account; your app receives an ID token full of claims about who they are and never touches a password. You will wire this with App Service built-in authentication, which implements the entire OIDC flow at the platform layer, so the portal's own code stays about the portal. Then you'll sign in as yourself and read the claims Entra handed back.

The password the app never sees is the password it can never lose.

Certification is two parts — one of them is a browser

The config is CLI-verifiable (app registration, redirect URI, provider wired, login required, OIDC discovery reachable). But the payoff — the actual sign-in and the ID-token claims — lives behind an interactive browser flow that no script can drive. You'll do that pass by hand at the end. That's the nature of SSO, not a shortcut.

Before you begin — one-time setup

You need a free Azure account, the Azure CLI (az), then be signed in with az login. First time? The 15-minute Set up your machine page covers the account, the installs (winget / brew / apt), and sign-in. Prefer zero installs? Run everything in Azure Cloud Shell (Bash), preinstalled and already signed in.

Before you start

You need permission to register apps in Entra (e.g. Application Administrator, Cloud Application Administrator, or Global Administrator). On a personal tenant you have it; on a work tenant you likely don't — use a personal test tenant. Run in Cloud Shell (Bash), and have a browser you can sign into your tenant with. Cost: App Service F1 (Free). Repo: github.com/kloudcaptain/campux-labs.

Step 0

Variables

The app name is fixed here, so the redirect URI is stable — the app registration must reference it exactly.

# Windows/Git Bash: stop it mangling /subscriptions/... arguments (harmless on macOS/Linux)
export MSYS_NO_PATHCONV=1

SUFFIX=$RANDOM
RG="campux-lab-sso-rg"
LOCATION="eastus"
APP="campux-portal-$SUFFIX"       # globally unique across *.azurewebsites.net
PLAN="campux-plan-$SUFFIX"
APP_DISPLAY="Campux Staff Portal $SUFFIX"

TENANT_ID=$(az account show --query tenantId -o tsv)
REDIRECT="https://$APP.azurewebsites.net/.auth/login/aad/callback"
echo "App=$APP"; echo "Redirect=$REDIRECT"; echo "Tenant=$TENANT_ID"
Checkpoint All three echo non-empty. The redirect URI is now stable for the rest of the lab.
Step 1

Deploy the portal (still unprotected)

App Service quota can be 0 in your region

If az appservice plan create fails with "Current Limit (Total VMs): 0", that's a subscription limit, not a mistake. The loop creates the plan in the first region with free-tier quota. (If every region reports 0, request an increase under Quotas → App Service.)

az group create --name "$RG" --location "$LOCATION"

for LOC in "$LOCATION" eastus2 westus2 centralus westus3 northeurope westeurope; do
  echo "Trying $LOC ..."
  if az appservice plan create --name "$PLAN" --resource-group "$RG" --sku F1 --is-linux --location "$LOC" 1>/dev/null 2>&1; then
    echo ">>> Plan created in $LOC"; break
  else
    echo "    no F1 quota in $LOC — trying the next region"
  fi
done

az webapp create --name "$APP" --resource-group "$RG" --plan "$PLAN" --runtime "NODE:20-lts"

Get the tiny app and deploy it, then warm the free-tier container:

git clone https://github.com/kloudcaptain/campux-labs.git
cd campux-labs/lab-b-app-registration-oidc-sso/app
zip app.zip server.js package.json
az webapp deploy --name "$APP" --resource-group "$RG" --src-path app.zip --type zip

az webapp restart --name "$APP" --resource-group "$RG"
sleep 30
for i in 1 2 3 4 5; do
  curl -sS "https://$APP.azurewebsites.net" && break
  sleep 20
done
Checkpoint The curl says Signed-in user: (no authenticated user). The site loads and, right now, anyone can reach it. We'll fix that.
Step 2

Register the app in Microsoft Entra ID

The --enable-id-token-issuance true is not optional: Easy Auth uses the OIDC hybrid flow, and without it sign-in later fails with AADSTS700054.

APP_ID=$(az ad app create \
  --display-name "$APP_DISPLAY" \
  --sign-in-audience AzureADMyOrg \
  --web-redirect-uris "$REDIRECT" \
  --enable-id-token-issuance true \
  --query appId -o tsv)

# A just-created app registration can lag Graph replication; pause so the next calls don't 404.
sleep 15
az ad sp create --id "$APP_ID"                                          # the enterprise app; sign-in needs it
CLIENT_SECRET=$(az ad app credential reset --id "$APP_ID" --query password -o tsv)
echo "App (client) id: $APP_ID"
Checkpoint az ad app show --id "$APP_ID" --query "{redirect:web.redirectUris, idToken:web.implicitGrantSettings.enableIdTokenIssuance}" -o json shows your exact redirect URI and "idToken": true. Both are required for sign-in.
Step 3

Turn on sign-in

One command enables App Service authentication, sets Microsoft Entra as the provider, and requires every visitor to log in — the classic single-command form, no extension needed.

az webapp auth update \
  --resource-group "$RG" --name "$APP" \
  --enabled true \
  --action LoginWithAzureActiveDirectory \
  --aad-client-id "$APP_ID" \
  --aad-client-secret "$CLIENT_SECRET" \
  --aad-token-issuer-url "https://sts.windows.net/$TENANT_ID/" \
  --aad-allowed-token-audiences "$REDIRECT"

Confirm the config, and that Entra's OIDC discovery document — the metadata the whole flow relies on — is reachable:

az webapp auth show --name "$APP" --resource-group "$RG" \
  --query "{enabled:enabled, action:unauthenticatedClientAction, clientId:clientId}" -o json

curl -s "https://login.microsoftonline.com/$TENANT_ID/v2.0/.well-known/openid-configuration" | head -c 200; echo
Checkpoint (CLI-verifiable) The auth shows enabled: true, a redirect/login action, and your clientId; the discovery URL returns JSON beginning {"token_endpoint":.... Enabling auth restarts the app — give it ~30 seconds (sleep 30) before the browser step so you don't hit a cold-start mid sign-in.
Step 4

Sign in — the manual payoff

This part cannot be scripted; that's the nature of interactive SSO. In a browser:

  1. Open a new private/incognito window and go to https://<your app>.azurewebsites.net.
  2. You're redirected to the Microsoft sign-in page. Sign in with an account in your tenant (accept the consent prompt the first time).
  3. You land back on the portal, which now shows Signed-in user: your@email — the identity came from Entra, and the app never saw your password.
  4. View the claims Entra issued: browse to /.auth/me on the same site. You'll see JSON with name, preferred_username, oid, tid, and token expiry.
Certification checkpoint (manual) The portal shows your email after sign-in, and /.auth/me lists your claims. That is OIDC SSO working end to end.
Troubleshooting — the three usual failures, in order

1. AADSTS700054 → id-token issuance didn't take; re-run az ad app update --id "$APP_ID" --enable-id-token-issuance true. 2. Redirect mismatch → the registration's redirect URI must be exactly $REDIRECT. 3. Issuer/audience error → your app may issue v2 tokens; re-run Step 3 with --aad-token-issuer-url "https://login.microsoftonline.com/$TENANT_ID/v2.0". Try this first if sign-in completes but the app rejects the token.

Down

Tear it down

The app registration and service principal are directory objects — they survive az group delete, so delete them explicitly.

az group delete --name "$RG" --yes
az ad app delete --id "$APP_ID"   # also removes the service principal
Checkpoint az ad app list --app-id "$APP_ID" --query "[].appId" -o tsv is empty and az group exists --name "$RG" is false — no orphaned registration, no resources.
End

What you can now honestly claim

You registered an application in Microsoft Entra ID and configured OpenID Connect single sign-on for an App Service using built-in authentication, with no custom auth code. Keep four things: an app registration is how Entra knows about your app and will sign users into it; OIDC lets users sign in with their existing Microsoft identity while your app receives claims, never a password; App Service Easy Auth implements the whole flow and hands you the identity as request headers, with full claims at /.auth/me; and redirect URI, id-token issuance, and issuer/token-version are the three settings that make or break a sign-in. The Bicep piece declares the auth config as code, while the registration — a Graph object — stays CLI.