Client portal app registration
Client portal: Entra ID app registration
Each client gets a dedicated Static Web App at <slug>.docs.skarp.ch. Authentication delegates to the client's own Entra ID tenant via a custom OIDC provider — no B2B guest accounts required. This section covers the one-time setup needed per client.
Prerequisites
Before starting, confirm you have:
- The client's tenant ID (found in Entra ID > Overview)
- A user in the client's tenant with permission to register applications (Application Administrator or higher)
- The final subdomain decided, e.g.
brennwald-heilig.docs.skarp.ch - The SWA instance already created for this client (provisioned via the
20-docsstack in thecore-infrastructurerepo)
Step 1 — Register the app in the client's tenant
Perform these steps logged in to the client's Azure portal, or ask a client-side admin to do it and send you the output values.
- Go to Microsoft Entra ID > App registrations > New registration
-
Fill in the registration form:
Field Value Name Skarp Docs PortalSupported account types Accounts in this organizational directory only Redirect URI (type: Web) https://<slug>.docs.skarp.ch/.auth/login/<slug>/callback!!! note "Redirect URI must be exact" The path
/.auth/login/<slug>/callbackis fixed by Azure Static Web Apps. The<slug>segment must match the provider key used instaticwebapp.config.json. A mismatch here causes a redirect URI error during login. -
Click Register
- Note the Application (client) ID — you will need this shortly
Step 2 — Add API permissions
In the newly registered app:
- Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions
-
Add the following three permissions:
Permission Type Admin consent required openidDelegated No profileDelegated No emailDelegated No -
No admin consent grant is needed — these are standard OIDC scopes
Step 3 — Create a client secret
- Go to Certificates & secrets > Client secrets > New client secret
- Set a description, e.g.
skarp-docs-portal - Set expiry to 24 months (maximum)
- Click Add
- Copy the secret value immediately — it is only shown once
!!! warning "Track the expiry date"
Record the expiry date in the client record (clients/<slug>/client.yml). A lapsed secret silently breaks authentication for all users of that portal. Set a calendar reminder 4 weeks before expiry to rotate it.
Rotation procedure: create a new secret, update the `OIDC_CLIENT_SECRET` app setting in the SWA, verify login works, then delete the old secret.
Step 4 — Configure the SWA app settings
In the Skarp Azure subscription, navigate to the client's Static Web App and add the following application settings:
OIDC_CLIENT_ID = <Application (client) ID from Step 1>
OIDC_CLIENT_SECRET = <Secret value from Step 3>
Via Azure CLI:
az staticwebapp appsettings set \
--name swa-docs-<slug> \
--resource-group rg-msp-docs-prd-chn-01 \
--setting-names \
OIDC_CLIENT_ID="<client-id>" \
OIDC_CLIENT_SECRET="<client-secret>"
Step 5 — Verify staticwebapp.config.json
Confirm the config file at clients/<slug>/staticwebapp.config.json contains the correct provider key and tenant ID. The relevant section:
{
"auth": {
"identityProviders": {
"customOpenIdConnectProviders": {
"<slug>": {
"registration": {
"clientIdSettingName": "OIDC_CLIENT_ID",
"clientCredential": {
"clientSecretSettingName": "OIDC_CLIENT_SECRET"
},
"openIdConnectConfiguration": {
"wellKnownOpenIdConfiguration": "https://login.microsoftonline.com/<CLIENT_TENANT_ID>/v2.0/.well-known/openid-configuration"
}
},
"login": {
"nameClaimType": "preferred_username",
"scopes": ["openid", "profile", "email"]
}
}
}
}
}
}
Replace <slug> with the client identifier (e.g. brennwald-heilig) and <CLIENT_TENANT_ID> with the tenant ID noted in Step 1.
Step 6 — Smoke test
- Open a private/incognito browser window
- Navigate to
https://<slug>.docs.skarp.ch - Confirm you are redirected to Microsoft login automatically
- Sign in with a user account from the client's tenant
- Confirm you land on the docs home page and can navigate freely
- Sign in with a user account from a different tenant — confirm access is denied
Onboarding record
Update clients/<slug>/client.yml with the following values once setup is complete:
| Field | Value |
|---|---|
client_tenant_id |
Entra tenant ID |
app_registration_id |
Application (client) ID |
oidc_secret_expiry |
Secret expiry date |