diff --git a/package.json b/package.json index ee12e44..fd7fb56 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "@azure/msal-node-extensions": "^1.2.0", "@microsoft/microsoft-graph-client": "^3.0.7", "azure-devops-node-api": "^15.1.2", - "jmespath": "^0.16.0" + "jmespath": "^0.16.0", + "minimatch": "^10.1.2" }, "author": { "name": "Sławomir Koszewski", diff --git a/src/graph/app.js b/src/graph/app.js index 0051d87..868c959 100644 --- a/src/graph/app.js +++ b/src/graph/app.js @@ -198,3 +198,60 @@ export async function listAppGrants(client, appId) { return Array.isArray(grantsResult?.value) ? grantsResult.value : []; } + +/** + * List available delegated scopes and app roles for a resource app. + * + * @param { Object } client + * @param { Object } options + * @param { string } [options.appId] + * @param { string } [options.displayName] + * @returns { Promise } + */ +export async function listResourcePermissions(client, options = {}) { + const { appId, displayName } = options; + if (!appId && !displayName) { + throw new Error("appId or displayName is required"); + } + + let request = client + .api("/servicePrincipals") + .select("appId,displayName,oauth2PermissionScopes,appRoles"); + + if (appId) { + request = request.filter(`appId eq '${appId}'`); + } else { + request = request.filter(`displayName eq '${displayName}'`); + } + + const result = await request.get(); + const servicePrincipals = Array.isArray(result?.value) ? result.value : []; + const rows = []; + + for (const sp of servicePrincipals) { + for (const scope of sp?.oauth2PermissionScopes ?? []) { + rows.push({ + permissionType: "Scope", + permissionId: scope.id ?? null, + permissionValue: scope.value ?? null, + permissionDisplayName: + scope.adminConsentDisplayName ?? + scope.userConsentDisplayName ?? + null, + isEnabled: scope.isEnabled ?? null, + }); + } + + for (const role of sp?.appRoles ?? []) { + rows.push({ + permissionType: "Role", + permissionId: role.id ?? null, + permissionValue: role.value ?? null, + permissionDisplayName: role.displayName ?? null, + isEnabled: role.isEnabled ?? null, + }); + } + } + + return rows; +}