如何动态配置Microsoft Graph API权限?替代Azure门户手动配置
问题
我编写了一个用于测试Microsoft Graph API的基础C#程序,当前通过Azure门户手动配置API调用权限。是否存在更优方案?能否根据代码中新增的API调用动态配置权限,而非手动在Azure门户操作?
代码实现
GraphHandler.cs
public class GraphHandler { public GraphServiceClient GraphClient { get; private set; } public GraphHandler(string tenantId, string clientId, string clientSecret) { GraphClient = CreateGraphClient(tenantId, clientId, clientSecret); } public GraphServiceClient CreateGraphClient(string tenantId, string clientId, string clientSecret) { var options = new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }; var clientSecretCredential = new ClientSecretCredential( tenantId, clientId, clientSecret, options); var scopes = new[] { "https://graph.microsoft.com/.default" }; return new GraphServiceClient(clientSecretCredential, scopes); } public async Task<User?> GetUser(string userPrincipalName) { return await GraphClient.Users[userPrincipalName].GetAsync(); } public async Task<(IEnumerable<Site>?, IEnumerable<Site>?)> GetSharepointSites() { var sites = (await GraphClient.Sites.GetAllSites.GetAsync())?.Value; if(sites == null) { return (null, null); } sites.RemoveAll(x => string.IsNullOrEmpty(x.DisplayName)); var spSites = new List<Site>(); var oneDriveSites = new List<Site>(); foreach (var site in sites) { if (site == null) continue; var compare = site.WebUrl?.Split(site.SiteCollection?.Hostname)[1].Split("/"); if (compare.All(x => !string.IsNullOrEmpty(x)) || compare.Length < 1) { continue; } if (compare[1] == "sites" || string.IsNullOrEmpty(compare[1])) spSites.Add(site); else if (compare[1] == "personal") oneDriveSites.Add(site); } return (spSites, oneDriveSites); } }
Program.cs
string tenantId = "INPUT TENANT ID"; string clientId = "INPUT CLIENT ID"; string clientSecret = "INPUT CLIENT SECRET"; var graphHandler = new GraphHandler(tenantId, clientId, clientSecret); Console.WriteLine("Get display name of user:"); var user = await graphHandler.GetUser("mail@example.com"); Console.WriteLine(user?.DisplayName); Console.WriteLine("Get all sharepoint sites in tenant"); var spSites = (await graphHandler.GetSharepointSites()).Item1; foreach (var site in spSites) { Console.WriteLine(site.DisplayName); } Console.ReadLine();
解决方案
首先明确:完全自动动态配置权限是无法实现的,因为Azure AD的权限管理出于安全考虑,要求应用权限必须经过租户管理员授权(委派权限部分场景允许用户自行同意,但应用权限必须管理员确认)。不过可以通过以下方案减少手动操作的繁琐:
1. 用Microsoft Graph API自动化权限配置
你可以编写代码来管理应用注册和权限,前提是执行操作的服务主体拥有Application.ReadWrite.All这类管理应用的权限:
- 调用
POST /applications/{appId}/appRoleAssignments接口为应用添加应用权限 - 调用
POST /servicePrincipals/{spId}/oauth2PermissionGrants接口添加委派权限 - 注意:添加权限后仍需管理员完成同意操作(可以通过调用对应API或门户完成批量同意)
2. 使用ARM模板标准化应用配置
将应用注册、权限配置写成ARM模板,每次部署时自动创建或更新应用:
- 在模板的
Microsoft.AAD/directoryApplications资源中,通过requiredResourceAccess节点定义需要的Graph权限 - 新增API调用时,只需修改模板中的权限列表,重新部署即可完成配置,无需手动操作门户
3. 用Azure CLI/PowerShell脚本自动化
编写脚本实现应用注册和权限配置的自动化:
- 用Azure PowerShell的
New-AzADApplication、New-AzADServicePrincipal命令创建应用和服务主体 - 用
New-AzADAppPermission等命令添加所需权限 - 新增权限时,修改脚本中的权限ID,运行脚本即可完成更新
4. 结合配置文件关联代码与权限
针对你现有代码的优化:
- 当前使用的
https://graph.microsoft.com/.default范围会包含所有已配置的应用权限,所以新增API调用后,只需确保对应权限已配置(手动或自动化方式) - 可以将所需权限整理到配置文件(如
appsettings.json)中,让自动化脚本读取该配置来添加权限,实现代码与权限配置的联动,新增API时只需更新配置文件和脚本即可
内容的提问来源于stack exchange,提问作者dev4Life
相关产品推荐
相关产品推荐

