参考资料
创建应用及赋予权限
首先,要进入Entra管理中心创建应用,并赋予对操作用户API所需的权限
填写显示名称,点击注册
定位到API权限,点击添加权限
选择 Microsoft Graph
选择应用程序权限
具体的权限可参考上面参考资料中的文档,不同的API可能需要的权限各不同
添加完所需权限后,点击 代表XXXXXX 授予管理员同意
导航定位到"证书和密码",点击新客户端密码
新增的密钥,记得将值复制存储好备用
除新增的密钥之外,还需记录好应用程序ID及目录ID
代码示例
定义Auth返回类
public class AuthResponse
{
public string access_token { get; set; }
public int expires_in { get; set; }
public int ext_expires_in { get; set; }
public string token_type { get; set; }
}
获取用户的示例代码
public void GraphQueryUsersTest()
{
string clientId = "72ba689***************82ce0a";
string tenantId = "15d17**************8495681";
string clientSecret = @"tqZ8Q~************tZ8nbFY";
//国际版和实际互联的地址可能有差异
string scope = @"https%3A%2F%2Fgraph.microsoft.com%2F.default";
//国际版和实际互联的地址可能有差异
string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
AuthResponse authRepsonse = null;
using (HttpClient httpClient = new HttpClient())
{
var authRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
var requestBody = new StringContent($"client_id={clientId}&scope={scope}&client_secret={clientSecret}&grant_type=client_credentials");
requestBody.Headers.ContentType.MediaType = "application/x-www-form-urlencoded";
authRequest.Content = requestBody;
var authResponseStr = httpClient.SendAsync(authRequest).Result.Content.ReadAsStringAsync().Result;
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(authResponseStr)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(AuthResponse));
authRepsonse = (AuthResponse)deseralizer.ReadObject(ms);
}
if (authRepsonse != null && !string.IsNullOrEmpty(authRepsonse.access_token))
{
var request = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/v1.0/users");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authRepsonse.access_token);
var getUserResponseStr = httpClient.SendAsync(request).Result.Content.ReadAsStringAsync().Result;
}
}
}
创建用户的示例代码
注意:报文中的usageLocation参数一定要加上,如果不加,后续分配Dynamics 365许可证的时候会报错,这个参数在原文档上没有。其中的值可参考《ISO标准3166》中的两位国家码,中国为CN
public void GraphCreateUsersTest()
{
string clientId = "72ba689***************82ce0a";
string tenantId = "15d17**************8495681";
string clientSecret = @"tqZ8Q~************tZ8nbFY";
//国际版和实际互联的地址可能有差异
string scope = @"https%3A%2F%2Fgraph.microsoft.com%2F.default";
//国际版和实际互联的地址可能有差异
string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
AuthResponse authRepsonse = null;
using (HttpClient httpClient = new HttpClient())
{
var authRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
var requestBody = new StringContent($"client_id={clientId}&scope={scope}&client_secret={clientSecret}&grant_type=client_credentials");
requestBody.Headers.ContentType.MediaType = "application/x-www-form-urlencoded";
authRequest.Content = requestBody;
var authResponseStr = httpClient.SendAsync(authRequest).Result.Content.ReadAsStringAsync().Result;
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(authResponseStr)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(AuthResponse));
authRepsonse = (AuthResponse)deseralizer.ReadObject(ms);
}
if (authRepsonse != null && !string.IsNullOrEmpty(authRepsonse.access_token))
{
var request = new HttpRequestMessage(new HttpMethod("POST"), "https://graph.microsoft.com/v1.0/users")
{
Content = new StringContent(@"{""accountEnabled"": true,
""displayName"": ""Test User 0011"",
""mailNickname"": ""TestUser0011"",
""userPrincipalName"": ""TestUser0011@XXXXX.com"",
""usageLocation"":""CN"",
""passwordProfile"" : {
""forceChangePasswordNextSignIn"": false,
""password"": ""PA$$w0rd123"" } }",
Encoding.UTF8,
"application/json"
)};
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authRepsonse.access_token);
// Send the request asynchronously and get the response.
var postUserResponseStr = httpClient.SendAsync(request).Result;
// Read the response content as a string.
var postUserResponseContent = postUserResponseStr.Content.ReadAsStringAsync().Result;
}
}
}
查询某一用户许可证详情的示例代码
如不清楚具体需要添加哪些许可证,可以先用此方法查询一下现有用户的许可证
public void GraphQueryLicenseDetailsTest()
{
string clientId = "72ba689***************82ce0a";
string tenantId = "15d17**************8495681";
string clientSecret = @"tqZ8Q~************tZ8nbFY";
//国际版和实际互联的地址可能有差异
string scope = @"https%3A%2F%2Fgraph.microsoft.com%2F.default";
//国际版和实际互联的地址可能有差异
string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
AuthResponse authRepsonse = null;
using (HttpClient httpClient = new HttpClient())
{
var authRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
var requestBody = new StringContent($"client_id={clientId}&scope={scope}&client_secret={clientSecret}&grant_type=client_credentials");
requestBody.Headers.ContentType.MediaType = "application/x-www-form-urlencoded";
authRequest.Content = requestBody;
var authResponseStr = httpClient.SendAsync(authRequest).Result.Content.ReadAsStringAsync().Result;
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(authResponseStr)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(AuthResponse));
authRepsonse = (AuthResponse)deseralizer.ReadObject(ms);
}
if (authRepsonse != null && !string.IsNullOrEmpty(authRepsonse.access_token))
{
var request = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/v1.0/users/095290b3-d393-4b99-bccf-16bca9753703/licenseDetails");
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authRepsonse.access_token);
var getUserResponseStr = httpClient.SendAsync(request).Result.Content.ReadAsStringAsync().Result;
}
}
}
为某一用户分配许可证
添加和移除许可证都为此请求
public void GraphAssignLicenseUsersTest()
{
string clientId = "72ba689***************82ce0a";
string tenantId = "15d17**************8495681";
string clientSecret = @"tqZ8Q~************tZ8nbFY";
//国际版和实际互联的地址可能有差异
string scope = @"https%3A%2F%2Fgraph.microsoft.com%2F.default";
//国际版和实际互联的地址可能有差异
string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
AuthResponse authRepsonse = null;
using (HttpClient httpClient = new HttpClient())
{
var authRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
var requestBody = new StringContent($"client_id={clientId}&scope={scope}&client_secret={clientSecret}&grant_type=client_credentials");
requestBody.Headers.ContentType.MediaType = "application/x-www-form-urlencoded";
authRequest.Content = requestBody;
var authResponseStr = httpClient.SendAsync(authRequest).Result.Content.ReadAsStringAsync().Result;
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(authResponseStr)))
{
DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(AuthResponse));
authRepsonse = (AuthResponse)deseralizer.ReadObject(ms);
}
if (authRepsonse != null && !string.IsNullOrEmpty(authRepsonse.access_token))
{
var request = new HttpRequestMessage(new HttpMethod("POST"), "https://graph.microsoft.com/v1.0/users/3362e765-e8a2-4df5-bd53-0b0d7a060a92/assignLicense")
{
//Content = new StringContent(@"{""addLicenses"": [],""removeLicenses"":[""a403ebcc-fae0-4ca2-8c8c-7a907fd6c235""]}",
// Encoding.UTF8,
// "application/json"
// )
Content = new StringContent(@"{""addLicenses"": [{ ""disabledPlans"": [],""skuId"":""05e9a617-0261-4cee-bb44-138d3ef5d965""}],""removeLicenses"":[]}",
Encoding.UTF8,
"application/json"
)
};
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authRepsonse.access_token);
// Send the request asynchronously and get the response.
var postUserResponseStr = httpClient.SendAsync(request).Result;
// Read the response content as a string.
var postUserResponseContent = postUserResponseStr.Content.ReadAsStringAsync().Result;
}
}
}
授予许可证后,用户在Dynamics 365的用户列表中可能不会马上出来,可能是异步的原因,需要等待几分钟
执行完上面操作,再基于Dynamics 365 的SDK进行角色及相关权限赋予操作即可。