|
1 | 1 | using System.Collections.Generic; |
| 2 | +using System.Linq; |
2 | 3 | using AzureTray.Plugin.Contracts; |
3 | 4 |
|
4 | 5 | namespace AzureTray.AppRegistration; |
5 | 6 |
|
6 | | -// The minimum delegated permissions the host itself needs, independent |
7 | | -// of any loaded plugin. Currently just User.Read so the host can call |
8 | | -// /me to resolve the signed-in user's tenant/display name. Plugins add |
9 | | -// their own scopes via ITrayPlugin.RequiredPermissions and are |
10 | | -// aggregated alongside these in Fix Permissions / Create App Registration. |
| 7 | +// Splits the host's declared scopes into two layers so the consent |
| 8 | +// surface stays honest: |
| 9 | +// |
| 10 | +// Baseline — what every signed-in user needs just to operate the |
| 11 | +// tray (sign-in identity, tenant display name resolution). |
| 12 | +// This is the only set used by the runtime host code that |
| 13 | +// a non-admin user actually exercises. |
| 14 | +// |
| 15 | +// AdminTools — what the in-app admin features (Fix Permissions, |
| 16 | +// Create App Registration, App Registration search) |
| 17 | +// additionally need to function. A user who never uses |
| 18 | +// those features doesn't need these scopes. We still |
| 19 | +// add them to the app registration at provision time |
| 20 | +// so administrators can self-heal, but users with no |
| 21 | +// directory role to back them up get a clean "you |
| 22 | +// don't have authority" failure instead of a confusing |
| 23 | +// "Insufficient privileges" 403 with no context. |
| 24 | +// |
| 25 | +// All = Baseline ∪ AdminTools and is what AggregateRequiredPermissions() |
| 26 | +// in SettingsViewModel.cs / TestRegistry.cs already consumes, so this |
| 27 | +// reshuffle is a pure rename/documentation change at the call sites. |
| 28 | +// |
| 29 | +// Plugins declare their own scopes via ITrayPlugin.RequiredPermissions |
| 30 | +// and are folded into the same aggregate downstream — those are the |
| 31 | +// host's only "what does the runtime need" inputs aside from Baseline. |
11 | 32 | internal static class HostRequiredPermissions |
12 | 33 | { |
13 | | - public static IReadOnlyList<PluginPermissionRequirement> All { get; } = new[] |
| 34 | + // Always needed. Pure read of the signed-in user; required by /me |
| 35 | + // and by the /organization → /me companyName fallback. |
| 36 | + public static IReadOnlyList<PluginPermissionRequirement> Baseline { get; } = new[] |
14 | 37 | { |
15 | 38 | new PluginPermissionRequirement( |
16 | 39 | PermissionApi.MicrosoftGraph, |
17 | 40 | "User.Read", |
18 | 41 | "e1fe6dd8-ba31-4d61-89e7-88639da4683d", |
19 | 42 | "Sign in and read user profile (host /me lookup)"), |
20 | 43 | }; |
| 44 | + |
| 45 | + // Only needed for in-app administration of tenant app registrations. |
| 46 | + // The two scopes together let a holder of an appropriate directory |
| 47 | + // role (Application Admin / Cloud Application Admin / Privileged |
| 48 | + // Role Admin / Global Admin) run Fix Permissions and Create App |
| 49 | + // Registration end-to-end. Without these scopes consented, those |
| 50 | + // features return 403 with the underlying Authorization_RequestDenied |
| 51 | + // — surfaced to the user via the response-body capture in |
| 52 | + // AppRegistrationGraphClient. |
| 53 | + public static IReadOnlyList<PluginPermissionRequirement> AdminTools { get; } = new[] |
| 54 | + { |
| 55 | + new PluginPermissionRequirement( |
| 56 | + PermissionApi.MicrosoftGraph, |
| 57 | + "Application.ReadWrite.All", |
| 58 | + "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", |
| 59 | + "Read, search, and update tenant app registrations (in-app Fix Permissions / Create App Registration)"), |
| 60 | + new PluginPermissionRequirement( |
| 61 | + PermissionApi.MicrosoftGraph, |
| 62 | + "DelegatedPermissionGrant.ReadWrite.All", |
| 63 | + "41ce6ca6-6826-4807-84f1-1c82854f7ee5", |
| 64 | + "Grant tenant-wide admin consent for plugin scopes (in-app Fix Permissions / Create App Registration)"), |
| 65 | + }; |
| 66 | + |
| 67 | + // Union used by Create App Registration / Fix Permissions to provision |
| 68 | + // the full host-side scope set on the app reg. Plugins' own |
| 69 | + // requirements are appended downstream — this list is host-only. |
| 70 | + public static IReadOnlyList<PluginPermissionRequirement> All { get; } = |
| 71 | + Baseline.Concat(AdminTools).ToArray(); |
21 | 72 | } |
0 commit comments