【问题标题】:Active Directory Authentication Library Programmatic SSOActive Directory 身份验证库程序化 SSO
【发布时间】:2016-06-02 12:30:26
【问题描述】:

我们正在使用 ADAL C# 库来获取 Azure AD 应用程序(包括 Graph API)的令牌。

我们使用本地 ADFS 3.0 服务器通过 Azure AD 设置了 AD Connect。所以,当本地客户端应用程序调用......

var ourDomain = "abc.com";
var authority = "https://login.microsoftonline.com/" + ourDomain;
var authenticationContext = new AuthenticationContext(authority);

var graphResourceUri = "https://graph.windows.net";
var azureADApplicationClientId = "7718c738-0000-0000-0000-4382476f1c65";

var result = authenticationContext.AcquireToken(
   graphResourceUri, 
   azureADApplicationClientId, new Uri("https://localhost"),
   PromptBehavior.RefreshSession, 
   new UserIdentifier($"jdoe@{ourDomain}", UserIdentifierType.RequiredDisplayableId), 
   $"domain_hint={ourDomain}");

弹出一个 MSOnline 登录窗口,立即重定向到我们的 ADFS 服务器

https://ouradfs.abc.com/adfs/ls/wia?username=.......................

然后立即关闭,因为 NTLM(Windows 集成)身份验证发生并成功...并且result 包含在我们的abc.com 域上登录​​的 Windows 用户的有效访问令牌。

虽然这个过程不需要任何点击...它仍然是“交互式的”。我希望能够利用 Windows 集成身份验证在非交互式环境(例如 Windows 服务或计划任务)中以编程方式获取此类访问令牌。这样我就不必在我们的 Windows 服务或计划任务中嵌入客户端密码。

这可能吗?

更新: 这是代码行

var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/mycorpdev.onmicrosoft.com");

AuthenticationResult result = authenticationContext.AcquireToken(
  "https://graph.windows.net", 
  nativeApplicationClientId, 
  new Uri("https://localhost"),
  PromptBehavior.Never, 
  new UserIdentifier("jsmith@mycorp.com"), UserIdentifierType.RequiredDisplayableId), $"domain_hint=mycorp.com");

以及确切的错误:

Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException occurred
  ErrorCode=user_interaction_required
  HResult=-2146233088
  Message=user_interaction_required: One of two conditions was encountered: 1. The PromptBehavior.Never flag was passed, but the constraint could not be honored, because user interaction was required. 2. An error occurred during a silent web authentication that prevented the http authentication flow from completing in a short enough time frame
  Source=Microsoft.IdentityModel.Clients.ActiveDirectory
  StackTrace:
       at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.RunAsyncTask[T](Task`1 task)

另一个更新:

这可行(其中客户端 ID 和租户与用户的主租户相同)

var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/mycorp.onmicrosoft.com");

AuthenticationResult result = authenticationContext.AcquireToken(
  "https://graph.windows.net", 
  nativeApplicationClientIdFromHomeTenantNotOtherTenant, 
  new Uri("https://localhost"),
  PromptBehavior.Never, 
  new UserIdentifier("jsmith@mycorp.com"), UserIdentifierType.RequiredDisplayableId), $"domain_hint=mycorp.com");

更新 - 这是 Fiddler 的捕获

GET https://login.microsoftonline.com/mycorpdev.onmicrosoft.com/oauth2/authorize?resource=https%3A%2F%2Fgraph.windows.net&client_id=78ebfdee-8144-48f8-9a96-1bd5418c0492&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%2F&login_hint=jsmith%40mycorp.COM&client-request-id=7a8878d4-2762-4784-9d29-6f49b147d474&prompt=attempt_none&x-client-SKU=.NET&x-client-Ver=2.19.0.0&x-client-CPU=x64&x-client-OS=Microsoft+Windows+NT+6.1.7601+Service+Pack+1&domain_hint=mycorpdev.onmicrosoft.com HTTP/1.1
Accept: */*
Accept-Language: en-US
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Win64; x64; Trident/7.0; .NET CLR 2.0.50727; SLCC2; Media Center PC 6.0; Tablet PC 2.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
Host: login.microsoftonline.com
Connection: Keep-Alive
Cookie: ESTSAUTHPERSISTENT=AAABAAEAiL9Kn2Z27UubvWFPbm0gLfZQz8hXb5bXR-iThmkV-FLuLx102LOLAWrogj3rvf40Xl0xjZntMo0Kzvbo0x38Z2CpfCjtOwyyVpp1DWlxyyRPBbl4Z4da5pFuYjfCLPqExGUvo5gBoMdeQ-0MobfbSV2GQCHgbL1CFRjOu6YJZUEgnk7Vyls4rOlHGaqEGpzm5OeFQj3acldcvD9C4PX1gGsV-2g5GU8Frx3co4YzqYHMbhp6fgzf18sfgWaaG9caWj756P2oDvqe9qAlehXk51cA2AUacM2h-k2rtN8F341p7tnOFkNBzCj_E4z3bTnwHodimoXLiDlDWjFWkzAANyAA


HTTP/1.1 302 Found
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: -1
Location: https://localhost/?error=login_required&error_description=AADSTS50058%3a+User+account+identifier+is+not+provided.%0d%0aTrace+ID%3a+133f0405-eb3d-452d-a8b6-b6ba6267af7c%0d%0aCorrelation+ID%3a+7a8878d4-2762-4784-9d29-6f49b147d474%0d%0aTimestamp%3a+2016-02-21+04%3a54%3a07Z
Vary: Accept-Encoding
Server: Microsoft-IIS/8.5
x-ms-request-id: 133f0405-eb3d-452d-a8b6-b6ba6267af7c
client-request-id: 7a8878d4-2762-4784-9d29-6f49b147d474
x-ms-gateway-service-instanceid: ESTSFE_IN_420
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
Set-Cookie: flight-uxoptin=true; path=/; secure; HttpOnly
Set-Cookie: x-ms-gateway-slice=productionb; path=/; secure; HttpOnly
Set-Cookie: stsservicecookie=ests; path=/; secure; HttpOnly
X-Powered-By: ASP.NET
Date: Sun, 21 Feb 2016 04:54:05 GMT
Content-Length: 0

还有一个更新...

如果我尝试使用集成身份验证(请注意,它确实会尝试正确重定向到我们的 ADFS...):

var authenticationContext = new AuthenticationContext(""https://login.microsoftonline.com/" + UserPrincipal.Current.UserPrincipalName.Split('@')[1]), false);
var nativeClientId = "00000000-0f32-4c38-bdb9-4ea5bd732c69";
var token = authenticationContext.AcquireTokenAsync(Constants.ReportingApplicationUri, nativeClientId, new UserCredential()).Result;

System.AggregateException occurred
  HResult=-2146233088
  Message=One or more errors occurred.
  Source=mscorlib
  StackTrace:
       at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
:line 68
  InnerException: 
       ErrorCode=federated_service_returned_error
       HResult=-2146233088
       Message=Federated service at https://ds1.mycorp.com/adfs/services/trust/2005/windowstransport returned error: The message with Action 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
       Source=Microsoft.IdentityModel.Clients.ActiveDirectory
       StatusCode=500
       StackTrace:
            at Microsoft.IdentityModel.Clients.ActiveDirectory.WsTrustRequest.<SendRequestAsync>d__1.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenNonInteractiveHandler.<PreTokenRequest>d__4.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<RunAsync>d__0.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenCommonAsync>d__0.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenAsync>d__14.MoveNext()
       InnerException: 
            HResult=-2146233079
            Message=The remote server returned an error: (500) Internal Server Error.
            Source=System
            StackTrace:
                 at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
                 at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
              --- End of stack trace from previous location where exception was thrown ---
                 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                 at Microsoft.IdentityModel.Clients.ActiveDirectory.HttpWebRequestWrapper.<GetResponseSyncOrAsync>d__2.MoveNext()
              --- End of stack trace from previous location where exception was thrown ---
                 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                 at Microsoft.IdentityModel.Clients.ActiveDirectory.WsTrustRequest.<SendRequestAsync>d__1.MoveNext()
            InnerException: 

【问题讨论】:

    标签: oauth azure-active-directory adfs azure-ad-graph-api


    【解决方案1】:

    当然。您可以通过 2 种替代方式进行操作。

    1. 通过PromptBehavior.Never。这将使用一个不可见的浏览器,使操作 100% 非交互式。这适用于 Kerberos 和任何其他会话类型(例如 cookie)。
    2. 使用接受UserCredentialAcquireToken 重载。将空的UserCredential 传递给它,如new UserCredential()。这将强制使用 Kerberos 身份验证。

    【讨论】:

    • 1 - 据我所知没有。实际上,只有当令牌位于 ADAL TokenCache 中时,才似乎永远不会起作用,否则会失败。
    • 关于 2 - 如果帐户名称当前绑定到多个 Azure AD 怎么办?有没有办法绕过询问您是要使用“工作帐户”还是“Microsoft 帐户”的屏幕
    • 不应该这样。您描述的行为适用于 AcquireTokenSilent,因为它只查看笼子,但 PromptBehavior.Never 中的不可见浏览器应该可以完成这项工作。你能抓住提琴手的踪迹,看看电线上发生了什么吗?另外,您尝试过#2 吗?
    • 关于 2,因为它使用 Kerberos,所以根本没有屏幕。租户由您通过的权限决定。如果您的用户是来自另一个租户的来宾,那么这将不起作用,因为您需要交互性来指定来自授权中指定的租户以外的租户的用户名
    • 应该是。这里的主要问题是在 mex 端点上,因此是关于 ADFS 设置或 ADAL 版本的评论。看起来这个讨论有点牵强。鉴于问题的要点已得到解决,如果您想深入了解特定方面,我建议您开始一个新问题
    猜你喜欢
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多