$npx -y skills add microsoft/power-platform-skills --skill set-app-registration-nativeUse when the user wants to wire a Power Apps Wrap mobile app to an Entra ID app registration by opening the Power Apps Wrap app-registration page, pasting the resulting client ID, and updating auth.config.json.
| 1 | **Shared instructions: [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)** — read first. |
| 2 | |
| 3 | # Set App Registration Native |
| 4 | |
| 5 | Wire `auth.config.json` to an Entra ID app registration for a Power Apps Wrap mobile app. |
| 6 | |
| 7 | This skill is manual by design: |
| 8 | - Do **not** create or patch app registrations from this skill. |
| 9 | - Use the public Power Apps Wrap app-registration page to create/configure the |
| 10 | registration, then write the pasted client ID into `auth.config.json`. |
| 11 | - Do not direct the user to add redirect URIs or API permissions manually. |
| 12 | Tenant-wide admin consent is not required for this Wrap registration flow. |
| 13 | |
| 14 | ## Workflow |
| 15 | |
| 16 | 1. Verify app root -> 2. Resolve environment + tenant -> 3. Open Wrap registration URL -> 4. Capture client ID -> 5. Write `auth.config.json` -> 6. Validate JSON -> 7. Summary |
| 17 | |
| 18 | --- |
| 19 | |
| 20 | ## Step 1 — Verify app root |
| 21 | |
| 22 | From the current directory, verify a generated mobile app root: |
| 23 | |
| 24 | ```bash |
| 25 | test -f auth.config.json && test -f app.config.js && test -f power.config.json |
| 26 | ``` |
| 27 | |
| 28 | If this fails, stop and tell the user to run `/create-mobile-app` first or open the generated app folder. |
| 29 | |
| 30 | ## Step 2 — Resolve environment + tenant |
| 31 | |
| 32 | Use the same environment selected by the generated app. Prefer `.resolved-environment.json`, then `auth.config.json.environment`, then `power.config.json` + resolver: |
| 33 | |
| 34 | ```bash |
| 35 | ENV_ID=$(node -e "console.log(require('./power.config.json').environmentId || '')") |
| 36 | TENANT_ID=$(node -e "try { const j=require('./.resolved-environment.json'); console.log(j.tenantId || '') } catch { console.log('') }" 2>/dev/null) |
| 37 | if [ -z "$TENANT_ID" ]; then |
| 38 | TENANT_ID=$(node -e "try { const j=require('./auth.config.json'); console.log((j.environment && j.environment.tenantId) || '') } catch { console.log('') }" 2>/dev/null) |
| 39 | fi |
| 40 | if [ -z "$TENANT_ID" ] && [ -n "$ENV_ID" ]; then |
| 41 | node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$ENV_ID" > .resolved-environment.json |
| 42 | TENANT_ID=$(node -e "const j=require('./.resolved-environment.json'); console.log(j.tenantId || '')") |
| 43 | fi |
| 44 | echo "$ENV_ID" |
| 45 | echo "$TENANT_ID" |
| 46 | ``` |
| 47 | |
| 48 | If `ENV_ID` is empty, stop: `power.config.json` is not initialized. |
| 49 | |
| 50 | If `TENANT_ID` is empty, stop: environment resolution failed. Do not guess the tenant and do not use a stale `msal.tenantId` as the authority source. |
| 51 | |
| 52 | ## Step 3 — Open Wrap app-registration page |
| 53 | |
| 54 | Print the public Power Apps Wrap URL for the active environment: |
| 55 | |
| 56 | ```text |
| 57 | https://make.powerapps.com/environments/<environment-id>/wraps#create-app-registration |
| 58 | ``` |
| 59 | |
| 60 | Tell the user: |
| 61 | |
| 62 | ```text |
| 63 | Open the Power Apps Wrap app-registration page for this environment: |
| 64 | https://make.powerapps.com/environments/<environment-id>/wraps#create-app-registration |
| 65 | |
| 66 | Create/register the app there, then paste the Application (client) ID here. |
| 67 | The Wrap page configures the native registration. Do not add redirect URIs or |
| 68 | API permissions manually; tenant-wide admin consent is not required. |
| 69 | If you already have a client ID, paste it directly. |
| 70 | If you cannot configure auth now, type skip. |
| 71 | ``` |
| 72 | |
| 73 | ## Step 4 — Capture client ID |
| 74 | |
| 75 | Ask: |
| 76 | |
| 77 | ```text |
| 78 | Paste the Entra ID app registration client ID for tenant <tenant-guid> (GUID format), or type skip: |
| 79 | ``` |
| 80 | |
| 81 | - If the user enters `skip`, leave `msal.clientId` blank, ensure `msal.tenantId` is set to the resolved tenant, preserve/add the `environment` cache, print the skip warning in Step 7, and stop. |
| 82 | - Otherwise validate GUID format before editing. |
| 83 | |
| 84 | ## Step 5 — Write `auth.config.json` |
| 85 | |
| 86 | Update `auth.config.json`: |
| 87 | - `msal.clientId` = pasted client ID |
| 88 | - `msal.tenantId` = resolved tenant ID from Step 2 |
| 89 | - Preserve any top-level `environment` object. |
| 90 | - If `environment` is missing and `.resolved-environment.json` exists, copy the non-secret resolved environment fields into top-level `environment`. |
| 91 | |
| 92 | Use structured JSON editing. Do not store tokens, secrets, or current-user Dataverse identity fields. |
| 93 | |
| 94 | Example target shape: |
| 95 | |
| 96 | ```json |
| 97 | { |
| 98 | "msal": { |
| 99 | "clientId": "<client-id>", |
| 100 | "tenantId": "<tenant-guid>" |
| 101 | }, |
| 102 | "environment": { |
| 103 | "environmentId": "<environment-id>", |
| 104 | "environmentUrl": "https://org.crm.dynamics.com", |
| 105 | "tenantId": "<tenant-guid>", |
| 106 | "cachedAt": "<iso timestamp>" |
| 107 | } |
| 108 | } |
| 109 | ``` |
| 110 | |
| 111 | Do not touch `src/playerConfig.ts`; auth identifiers live in `auth.config.json` only. |
| 112 | |
| 113 | ## Step 6 — Validate JSON |
| 114 | |
| 115 | ```bash |
| 116 | node -e "JSON.parse(require('fs').readFileSync('auth.config.json','utf8')); console.log('auth.config.json OK')" |
| 117 | ``` |
| 118 | |
| 119 | If dependencies are installed, optionally run: |
| 120 | |
| 121 | ```bash |
| 122 | npx tsc --noEmit |
| 123 | ``` |
| 124 | |
| 125 | Do not run npm install or native builds from this skill. |
| 126 | |
| 127 | ## Step 7 — Summary |
| 128 | |
| 129 | If a client ID was written: |
| 130 | |
| 131 | ```text |
| 132 | App registration wired. |
| 133 | Client ID : <client-i |