使用ADAL C#作为机密用户守护程序服务器服务器到服务器 – 401未经授权

使用ADAL C#作为机密用户守护程序服务器服务器到服务器 – 401未经授权,第1张

概述参考未回答的问题: 401- Unauthorized authentication using REST API Dynamics CRM with Azure AD 和 Dynamics CRM Online 2016 – Daemon / Server application Azure AD authentication error to Web Api 和 Dynamics CRM 20 参考未回答的问题:

401- Unauthorized authentication using REST API Dynamics CRM with Azure AD

Dynamics CRM Online 2016 – Daemon / Server application Azure AD authentication error to Web Api

Dynamics CRM 2016 Online Rest API with client credentials OAuth flow

我需要在天蓝云中的Web服务和Dynamics CRM Online 2016之间进行通信,而无需任何登录屏幕!该服务将有一个REST API,可以触发CRM上的CRUD *** 作(我也将实现身份验证)

我认为这称为“机密客户端”或“守护程序服务器”或只是“服务器到服务器”

我在Azure AD中正确设置了我的服务(“委托权限=在线访问动态作为组织用户”,没有其他选项)

我在VS中创建了一个ASP.NET WEB API项目,它在Azure中创建了我的WebService,并在CRM的Azure AD中创建了“应用程序”.

我的代码看起来像这样(请忽略EntityType和returnValue):

public class WolfController : APIController  {    private static Readonly string Tenant = "xxxxx.onmicrosoft.com";    private static Readonly string ClIEntID = "dxxx53-42xx-43bc-b14e-c1e84b62752d";    private static Readonly string Password = "j+t/DXjn4PMVAHSvZGd5sptGxxxxxxxxxr5Ki8KU="; // clIEnt secret,valID for one or two years    private static Readonly string ResourceID = "https://tenantname-naosprevIEw.crm.dynamics.com/";    public static async Task<AuthenticationResult> AcquireAuthentificationToken()    {      AuthenticationContext authenticationContext = new AuthenticationContext("https://login.windows.net/"+ Tenant);      ClIEntCredential clIEntCredentials = new ClIEntCredential(ClIEntID,Password);         return await authenticationContext.AcquiretokenAsync(ResourceID,clIEntCredentials);    }    // GET: just for calling the DataOperations-method via a GET,ignore the return    public async Task<IEnumerable<Wolf>> Get()    {      AuthenticationResult result = await AcquireAuthentificationToken();      await DataOperations(result);          return new Wolf[] { new Wolf() };    }    private static async Task DataOperations(AuthenticationResult authResult)    {      using (httpClIEnt httpClIEnt = new httpClIEnt())      {        httpClIEnt.BaseAddress = new Uri(ResourceID);        httpClIEnt.Timeout = new TimeSpan(0,2,0); //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.Accesstoken);        Account account = new Account();        account.name = "Test Account";        account.telephone1 = "555-555";        string content = String.Empty;        content = JsonConvert.SerializeObject(account,new JsonSerializerSettings() {DefaultValueHandling = DefaultValueHandling.Ignore});                    //Create Entity/////////////////////////////////////////////////////////////////////////////////////        httpRequestMessage request = new httpRequestMessage(httpMethod.Post,"API/data/v8.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 '{0}' created.",account.name);        }        else //Getting Unauthorized here        {          throw new Exception(String.Format("Failed to create account '{0}',reason is '{1}'.",account.name,response.ReasonPhrase));        } ... and more code

在调用我的GET请求时,我获得了401 Unauthorized,尽管我已经获得并发送了Accesstoken.

有任何想法吗?

编辑:
我也试过这个博客中提供的代码(只有解决问题的来源,也没有用):

https://samlman.wordpress.com/2015/06/04/getting-an-azure-access-token-for-a-web-application-entirely-in-code/

使用此代码:

public class WolfController : APIController  {    private static Readonly string Tenant = System.Configuration.ConfigurationManager.AppSettings["IDa:Tenant"];    private static Readonly string TenantGuID = System.Configuration.ConfigurationManager.AppSettings["IDa:TenantGuID"];    private static Readonly string ClIEntID = System.Configuration.ConfigurationManager.AppSettings["IDa:ClIEntID"];    private static Readonly string Password = System.Configuration.ConfigurationManager.AppSettings["IDa:Password"]; // clIEnt secret,valID for one or two years    private static Readonly string ResourceID = System.Configuration.ConfigurationManager.AppSettings["IDa:ResourceID"];    // GET: API/Wolf    public async Task<IEnumerable<Wolf>> Get()    {      AuthenticationResponse authenticationResponse = await GetAuthenticationResponse();      String result = await DoSomeDataOperations(authenticationResponse);      return new Wolf[]      {              new Wolf()              {                ID = 1,name = result              }      };    }    private static async Task<AuthenticationResponse> GetAuthenticationResponse()    {      //https://samlman.wordpress.com/2015/06/04/getting-an-azure-access-token-for-a-web-application-entirely-in-code/      //create the collection of values to send to the POST      List<keyvaluePair<string,string>> vals = new List<keyvaluePair<string,string>>();      vals.Add(new keyvaluePair<string,string>("grant_type","clIEnt_credentials"));      vals.Add(new keyvaluePair<string,string>("resource",ResourceID));      vals.Add(new keyvaluePair<string,string>("clIEnt_ID",ClIEntID));      vals.Add(new keyvaluePair<string,string>("clIEnt_secret",Password));      vals.Add(new keyvaluePair<string,string>("username","someUser@someTenant.onmicrosoft.com"));      vals.Add(new keyvaluePair<string,string>("password","xxxxxx"));      //create the post Url         string url = string.Format("https://login.microsoftonline.com/{0}/oauth2/token",TenantGuID);      //make the request      httpClIEnt hc = new httpClIEnt();      //form encode the data we’re going to POST      httpContent content = new FormUrlEncodedContent(vals);      //plug in the post body      httpResponseMessage hrm = hc.PostAsync(url,content).Result;      AuthenticationResponse authenticationResponse = null;      if (hrm.IsSuccessstatusCode)      {        //get the stream        Stream data = await hrm.Content.ReadAsstreamAsync();        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (AuthenticationResponse));        authenticationResponse = (AuthenticationResponse) serializer.Readobject(data);      }      else      {        authenticationResponse = new AuthenticationResponse() {ErrorMessage = hrm.StatusCode +" "+hrm.RequestMessage};      }      return authenticationResponse;    }    private static async Task<String> DoSomeDataOperations(AuthenticationResponse authResult)    {      if (authResult.ErrorMessage != null)      {        return "problem getting AuthToken: " + authResult.ErrorMessage;      }      using (httpClIEnt httpClIEnt = new httpClIEnt())      {        httpClIEnt.BaseAddress = new Uri(ResourceID);        httpClIEnt.Timeout = new TimeSpan(0,authResult.access_token);        //Retreive Entity/////////////////////////////////////////////////////////////////////////////////////        var retrIEveResponse = await httpClIEnt.GetAsync("/API/data/v8.0/Feedback?$select=Title,rating&$top=10");        //var retrIEveResponse = await httpClIEnt.GetAsync("/API/data/v8.0/$Metadata");        if (!retrIEveResponse.IsSuccessstatusCode)        {          return retrIEveResponse.ReasonPhrase;        }        return "it worked!";      }    }
解决方法 我终于找到了解决方案.由Joao R.在这篇文章中提供:

https://community.dynamics.com/crm/f/117/t/193506

首先:忘记ADAL

我的问题是我一直使用“错误的”URL,因为在不使用Adal(或更一般的用户重定向)时,您似乎需要其他地址.

为令牌构造以下http-Reqest:

网址:
https://login.windows.net/MyCompanyTenant.onmicrosoft.com/oauth2/token

标题:

>缓存控制:无缓存
>内容类型:application / x-www-form-urlencoded

身体:

> clIEnt_ID:YourClIEntIDFromAzureAd
>资源:https://myCompanyTenant.crm.dynamics.com
> username:yourServiceUser@myCompanyTenant.onmicrosoft.com
>密码:yourServiceUserPassword
> grant_type:密码
> clIEnt_secret:YourClIEntSecretFromAzureAd

构造以下http-Request以访问WebAPI:

网址:https://MyCompanyTenant.api.crm.dynamics.com/api/data/v8.0/accounts

标题:

>缓存控制:无缓存
>接受:application / Json
> OData版本:4.0
>授权:Bearer TokenRetrIEvedFomrequestAbove

Node.Js解决方案(获取令牌的模块)

var https = require("https");var querystring = require("querystring");var config = require("../config/configuration.Js");var q = require("q");var authHost = config.oauth.host;var authPath = config.oauth.path;var clIEntID = config.app.clIEntID;var resourceID = config.crm.resourceID;var username = config.crm.serviceUser.name;var password = config.crm.serviceUser.password;var clIEntSecret =config.app.clIEntSecret;function retrIEvetoken() {    var deferred = q.defer();       var bodyDataString = querystring.stringify({        grant_type: "password",clIEnt_ID:  clIEntID,resource: resourceID,username: username,password: password,clIEnt_secret: clIEntSecret    });    var options = {        host: authHost,path: authPath,method: 'POST',headers: {            "Content-Type": "application/x-www-form-urlencoded","Cache-Control": "no-cache"        }    };          var request = https.request(options,function(response){        // Continuously update stream with data        var body = '';        response.on('data',function(d) {            body += d;        });        response.on('end',function() {            var parsed = JsON.parse(body); //todo: try/catch            deferred.resolve(parsed.access_token);        });                   });    request.on('error',function(e) {        console.log(e.message);        deferred.reject("authProvIDer.retrIEvetoken: Error retrIEving the authToken: \r\n"+e.message);    });   request.end(bodyDataString);   return deferred.promise;    }module.exports = {retrIEvetoken: retrIEvetoken};

C#-Solution(获取和使用令牌)

public class AuthenticationResponse  {    public string token_type { get; set; }    public string scope { get; set; }    public int expires_in { get; set; }    public int expires_on { get; set; }    public int not_before { get; set; }    public string resource { get; set; }    public string access_token { get; set; }    public string refresh_token { get; set; }    public string ID_token { get; set; }  }
private static async Task<AuthenticationResponse> GetAuthenticationResponse(){  List<keyvaluePair<string,string>>();  vals.Add(new keyvaluePair<string,ClIEntID));  vals.Add(new keyvaluePair<string,ResourceID));  vals.Add(new keyvaluePair<string,"yxcyxc@xyxc.onmicrosoft.com"));  vals.Add(new keyvaluePair<string,"yxcycx"));  vals.Add(new keyvaluePair<string,"password"));  vals.Add(new keyvaluePair<string,Password));  string url = string.Format("https://login.windows.net/{0}/oauth2/token",Tenant);  using (httpClIEnt httpClIEnt = new httpClIEnt())  {    httpClIEnt.DefaultRequestheaders.Add("Cache-Control","no-cache");    httpContent content = new FormUrlEncodedContent(vals);    httpResponseMessage hrm = httpClIEnt.PostAsync(url,content).Result;    AuthenticationResponse authenticationResponse = null;    if (hrm.IsSuccessstatusCode)    {      Stream data = await hrm.Content.ReadAsstreamAsync();      DataContractJsonSerializer serializer = new    DataContractJsonSerializer(typeof(AuthenticationResponse));      authenticationResponse = (AuthenticationResponse)serializer.Readobject(data);    }    return authenticationResponse;  }}private static async Task DataOperations(AuthenticationResponse authResult){      using (httpClIEnt httpClIEnt = new httpClIEnt())  {    httpClIEnt.BaseAddress = new Uri(ResourceAPIID);    httpClIEnt.Timeout = new TimeSpan(0,0); //2 minutes    httpClIEnt.DefaultRequestheaders.Add("OData-MaxVersion","4.0");    httpClIEnt.DefaultRequestheaders.Add("OData-Version","4.0");    httpClIEnt.DefaultRequestheaders.Add("Cache-Control","no-cache");    httpClIEnt.DefaultRequestheaders.Accept.Add(new MediaTypeWithQualityheaderValue("application/Json"));    httpClIEnt.DefaultRequestheaders.Authorization = new AuthenticationheaderValue("Bearer",authResult.access_token);    Account account = new Account();    account.name = "Test Account";    account.telephone1 = "555-555";    string content = String.Empty;    content = JsonConvert.SerializeObject(account,new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore });    httpRequestMessage request = new httpRequestMessage(httpMethod.Post,"API/data/v8.0/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 '{0}' created.",account.name);    }    else    {      throw new Exception(String.Format("Failed to create account '{0}',response.ReasonPhrase));    }(...)
总结

以上是内存溢出为你收集整理的使用ADAL C#作为机密用户/守护程序服务器/服务器到服务器 – 401未经授权全部内容,希望文章能够帮你解决使用ADAL C#作为机密用户/守护程序服务器/服务器到服务器 – 401未经授权所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1247452.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存