微软动态CRM专家罗勇 ,回复332或者20190505可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!

本文很多内容来自 John Towgood 撰写的Dynamics 365 Online Authenticate with Client Credentials ,也着重参考了官方的 Use Single-Tenant server-to-server authentication ,我根据新的Azure Portal界面做了一些操作上的变化,并且改了一些代码,还使用ADAL来简化代码。

登录 https://portal.azure.com ,点击左边的 【Azure Active Directory】 ,然后再点击 【App registrations】 ,再点击【New registration】

输入一个合适的名称,Supported account types保持默认的 Accounts in this organizational directory only (Orgname) 不变,点击【Register】按钮。因为Redirect URI用不上所以不输入。

注册成功后会产生 Application (client) ID,记录下来备用,同时也记录下 Directory (tenant) ID。

再点击左边的【API Permissions】,再点击右边的 【+ Add a permission】按钮。

选择 【Dynamics CRM】  (也可以选择使用 PowerApps Runtime Serive 这个权限),

选择 【Delegated permissions】 > 【user_impersonation】后点击【Add permissions】按钮。

然后点击【Grant admin consent for Orgname】,

在弹出的提示中选择【Yes】。

然后点击【Certificates & secrets】 > 【+ New client secret】,输入合适的Description,在点击【Add】按钮。

会自动生成Client secrets,这里需要点击生成的secret旁边的【copy to clipboard】图标将其复制下来,记得在这个步骤复制下来,因为离开这个页面后就看不到这个secret了。

然后需要创建 一个Azure AD 用户,点击左侧的【Azure Active Directory】> 【Users】。

然后点击【New user】。

为用户输入Name,User Name,然后点击【Create】按钮。

最后还需要到Dynamics 365 Customer Engagement中创建一个Application User。导航到 Settings > Security > Users,切换到【Application Users】,点击命令栏的【NEW】按钮。

记得要切换到 APPLICATION USER这个窗体,输入的内容如下,Application ID就是前面步骤记录的Application (client) ID,其余的就是前面步骤创建的Azure AD user信息。

保存后会自动填充 Application ID URI 和 Azure AD Object ID 字段的值。

当然还需要给这个用户授予至少一个角色才行,官方建议不要授予系统标准角色,我这里复制了一个标准角色授予给他。

如果用Postman来获取access token的话,如下图:

下面就是用代码如何做了,不多说,看代码:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks; namespace UsingWebAPI
{
public class AuthenticationResponse
{
public string access_token { get; set; }
public int expires_in { get; set; }
public int expires_on { get; set; }
public int ext_expires_in { get; set; }
public int not_before { get; set; }
public string resource { get; set; }
public string token_type { get; set; }
}
class Program
{ static string resourceUrl = "https://crm219270.crm5.dynamics.com/";
static string clientId = "de8dd947-a3e3-48ec-8602-c3063f11dc29";
static string clientSecret = "5FsXh2*oNyLRm]Go1a9hD.[]=k54GNOZ";
static string tenantId = "3e28b187-1c5c-42f5-a1be-3f47570da35d";
static void Main(string[] args)
{
GetAuthenticationResponse();
Console.ReadKey();
} private static async void GetAuthenticationResponse()
{
List<KeyValuePair<string, string>> vals = new List<KeyValuePair<string, string>>(); vals.Add(new KeyValuePair<string, string>("client_id", clientId));
vals.Add(new KeyValuePair<string, string>("resource", resourceUrl));
vals.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
vals.Add(new KeyValuePair<string, string>("client_secret", clientSecret));
string tokenUrl = string.Format("https://login.windows.net/{0}/oauth2/token", tenantId); using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
HttpContent content = new FormUrlEncodedContent(vals);
HttpResponseMessage hrm = httpClient.PostAsync(tokenUrl, content).Result;
AuthenticationResponse authenticationResponse = null;
if (hrm.IsSuccessStatusCode)
{
string data = await hrm.Content.ReadAsStringAsync();
authenticationResponse = JsonConvert.DeserializeObject<AuthenticationResponse>(data);
await DataOperations(authenticationResponse);
}
else
{
Console.WriteLine("Error." + hrm.ReasonPhrase);
}
}
} private static async Task DataOperations(AuthenticationResponse authResult)
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(resourceUrl);
httpClient.Timeout = new TimeSpan(, , ); //2 minutes
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.access_token);
string content = JsonConvert.SerializeObject(new { name = "A Account", telephone1 = ""});
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "api/data/v9.1/accounts");
request.Content = new StringContent(content);
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
HttpResponseMessage response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Account created.");
}
else
{
Console.WriteLine(String.Format("Failed to create account, reason is '{0}'.", response.ReasonPhrase));
}
}
}
}
}

当然,如果使用ADAL的话,代码会更加简单点:

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers; namespace UsingWebAPI
{
class Program
{ static string resourceUrl = "https://crm219270.crm5.dynamics.com/";
static string clientId = "de8dd947-a3e3-48ec-8602-c3063f11dc29";
static string clientSecret = "5FsXh2*oNyLRm]Go1a9hD.[]=k54GNOZ";
static string tenantId = "3e28b187-1c5c-42f5-a1be-3f47570da35d"; static void Main(string[] args)
{
AuthAndInvoke();
Console.ReadKey();
} private static async void AuthAndInvoke()
{
var credentials = new ClientCredential(clientId, clientSecret);
var authContext = new AuthenticationContext("https://login.microsoftonline.com/" + tenantId);
var result = await authContext.AcquireTokenAsync(resourceUrl, credentials);
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(resourceUrl);
httpClient.Timeout = new TimeSpan(, , ); //2 minutes
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
string content = JsonConvert.SerializeObject(new { name = "A Account", telephone1 = "" });
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "api/data/v9.1/accounts");
request.Content = new StringContent(content);
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
HttpResponseMessage response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Account created.");
}
else
{
Console.WriteLine(String.Format("Failed to create account, reason is '{0}'.", response.ReasonPhrase));
}
}
}
}
}

可以看到代码创建的account的owner是我们前面步骤的Application User,是以该用户身份在运行的。

Dynamics 365 Online通过OAuth 2 Client Credential授权(Server-to-Server Authentication)后调用Web API的更多相关文章

  1. 利用Fiddler模拟通过Dynamics 365的OAuth 2 Client Credentials认证后调用Web API

    微软动态CRM专家罗勇 ,回复337或者20190521可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me. 配置Dynamics 365 & PowerApps 支 ...

  2. Dynamics 365 CE的插件/自定义工作流活动中调用Web API示例代码

    微软动态CRM专家罗勇 ,回复325或者20190428可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! 现在Web API越来越流行,有时候为了程序更加健壮,需要在插件 ...

  3. Dynamics 365本地部署版本配置OAuth 2 Password Grant以调用Web API

    微软动态CRM专家罗勇 ,回复330或者20190504可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! 根据官方建议,不要再使用Dynamics 365 Custome ...

  4. Dynamics CRM中跨域调用Web API 2

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复224或者20160611可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  5. 用Web API Client 调用 Web API

    安装Web API客户端库 右键单击项目,选择管理 NuGet程序包,选择联机选项,选择全部,在搜索框中输入“Microsoft.AspNet.WebApi.Client”, 搜索结果就是要安装的类库 ...

  6. 解决Dynamics 365使用JS调用Web API时报no property value was found in the payload 错误。

    摘要: 微软动态CRM专家罗勇 ,回复323或者20190421可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me! 碰到如下报错: message: "An er ...

  7. 配置Postman通过OAuth 2 implicit grant获取Dynamics 365 CE Online实例的Access Token

    微软动态CRM专家罗勇 ,回复335或者20190516可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me. 对于测试Web API, Get 类型,不需要设定特别reque ...

  8. Dynamics CRM模拟OAuth请求获得Token后在外部调用Web API

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复233或者20161104可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  9. Dynamics 365 App for Outlook 与 Dynamics 365 for Outlook(已被弃用)

    在最新的版本中Dynamics 365 for Outlook(Outlook 客户端)已被弃用 随 Dynamics CRM 2016(版本 8.0)引入的 Dynamics 365 App for ...

随机推荐

  1. C# ling to sql 左表连接

    var begin_daily = from a in _postgreDbContext.tab1 join b in _postgreDbContext.tab2 on a.id equals b ...

  2. Dynamics 365 Portal 修改注册页面及Profile页面

    一,Profile页面 客户要求在Portal Profile页面上添加性别字段,通过查看源代码发现,中间的联系人信息部分是引用的CRM中Contact实体的Portal Web Form表单,直接把 ...

  3. Android 基于ksoap2的webservice请求的学习

    [学习阶段] WebService网络请求? 其实我也是第一次遇到,之所以有这个需要是因为一些与 ERP 相关的业务,需要用到这样的一个请求方式. 开始学习WebService ①当然是百度搜索,这里 ...

  4. Aiseesoft 4K Converter for Mac如何转换视频格式?Aiseesoft 4K使用方法

    Aiseesoft 4K如何转换视频格式?由于这款4K UHD转换器支持最新的4K编码/解码技术,因此您可以将4K视频转换为4K电视或其他设备支持的任何其他视频格式.Aiseesoft 4K使用方法分 ...

  5. Asp.Net MVC Webapi Eventsource 实现时效消息

    ApiController 后端API public System.Net.Http.HttpResponseMessage GetUnknownNotices() { var user = Form ...

  6. 一步一步搭建 Oracle Data Guard

    前言 为什么要写前言,因为我要吐槽一下.作为一个Java后端,搭建Oracle Data Guard真的是一件,嗯,既不专业也不擅长的事情,然而,为什么还是要我来弄? 因为DBA出差了,我们这边急着要 ...

  7. JVM学习分享-思考题

    package zero.desk.stringconstantpool; import org.junit.Test; /** * @author Zero * @since 2019-09-17. ...

  8. layui 滚动加载

    直接上核心代码,其实官网介绍的很详细: var pageSize = 5;//每次请求新闻的条数 flow.load({ elem: '#newsList' //指定列表容器 ,scrollElem: ...

  9. Android 项目优化(二):启动页面优化

    一.启动页黑屏的问题 1.1 问题现象描述 Android App 启动页面黑屏的问题,现象表现为:Android 开发 App 启动时若没有做特殊处理的话,会出现一瞬间的白屏现象.即使启动页界面就加 ...

  10. HIFIMAN TWS600A听感小记——测评出街Man

    HIFIMAN TWS600A听感小记——测评出街Man 几年前蓝牙耳塞在大哥苹果的带领下有着掀翻小池塘的气势.蓝牙耳塞完全替代了我在通勤路上用的有线塞子,当时随便买了一副两百多元的塞子,低音轰头就算 ...