使用C# WSManConnectionInfo通过BasicAuthToOAuth连接Exchange Online失败
问题排查:C#通过WSManConnectionInfo连接Exchange Online(现代认证)失败
我们的代码原本使用WSManConnectionInfo类连接O365,此前采用Basic Auth,现租户已关闭Basic Auth,计划升级至现代认证。通过PowerShell可成功获取AccessToken并使用New-PSSession cmdlet连接,但C#实现相同逻辑时,打开Runspace抛出异常。
PowerShell 成功实现代码
Add-Type -Path 'C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.2.140\Microsoft.IdentityModel.Clients.ActiveDirectory.dll' $authContext45 = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList " https://login.windows.net/mytenant.onmicrosoft.com" $secret = Get-ChildItem cert://localmachine/my/thumbprint $CAC = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate]::new(appId,$secret) $authenticationResult = $authContext45.AcquireTokenAsync("https://outlook.office365.com",$CAC) $token = $authenticationResult.Result.AccessToken $Authorization = "Bearer {0}" -f $Token $Password = ConvertTo-SecureString -AsPlainText $Authorization -Force $Ctoken = New-Object System.Management.Automation.PSCredential -ArgumentList "OAuthUser@tenantGUID",$Password $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/PowerShell-LiveId?BasicAuthToOAuthConversion=true -Credential $Ctoken -Authentication Basic -AllowRedirection -Verbose Import-PSSession $Session
C# 失败实现代码
获取OAuth Token并创建连接信息
public static Collection<PSObject> GetUsersUsingOAuthPublic() { var authContext = new AuthenticationContext("https://login.windows.net/mytenant.onmicrosoft.com"); X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine); certStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false); certStore.Close(); var cac = new ClientAssertionCertificate(appId, certCollection[0]); var authResult = authContext.AcquireTokenAsync("https://outlook.office365.com", cac); var token = authResult.Result.AccessToken; string auth = string.Format("Bearer {0}", token); System.Security.SecureString password = new System.Security.SecureString(); foreach (char c in auth) { password.AppendChar(c); } PSCredential psCredential = new PSCredential(string.Format("OAuthUser@{0}", tenantId), password); WSManConnectionInfo connectionInfo = new WSManConnectionInfo( new Uri("https://outlook.office365.com/powershell-liveid?BasicAuthToOAuthConversion=true"), "https://schemas.microsoft.com/powershell/Microsoft.Exchange", psCredential ); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic; connectionInfo.SkipCACheck = true; connectionInfo.SkipCNCheck = true; using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo)) { return GetUserInformation(10, runspace); } }
Runspace打开与命令执行逻辑
public static Collection<PSObject> GetUserInformation(int count, Runspace runspace) { using (PowerShell powershell = PowerShell.Create()) { powershell.AddCommand("Get-Users"); powershell.AddParameter("ResultSize", count); runspace.Open(); powershell.Runspace = runspace; return powershell.Invoke(); } }
抛出的异常信息
System.Management.Automation.Remoting.PSRemotingTransportException
HResult=0x80131501
Message=Connecting to remote server outlook.office365.com failed with the following error message : The WS-Management service cannot process the request. Cannot find the https://schemas.microsoft.com/powershell/Microsoft.Exchange session configuration in the WSMan: drive on the outlook.office365.com computer. For more information, see the about_Remote_Troubleshooting Help topic.
排查方向与解决办法
- 补充重定向配置:PowerShell中使用了
-AllowRedirection参数,C#的WSManConnectionInfo需要添加connectionInfo.AllowRedirection = true;,缺失该配置可能导致无法正确跳转至目标端点,找不到会话配置。 - 修正命令拼写:C#中调用的
Get-Users是错误的,Exchange Online的正确命令为Get-User(单数),虽然异常发生在Runspace打开阶段,但该错误可能影响后续会话初始化逻辑,建议先修正。 - 验证认证头一致性:对比PowerShell与C#生成的PSCredential内容,确保Bearer token完整无截断。可在C#中输出token内容(仅调试用),与PowerShell中获取的token对比,确认手动构建SecureString时无字符遗漏。
- 统一ADAL库版本:确保C#项目引用的
Microsoft.IdentityModel.Clients.ActiveDirectory库版本与PowerShell中加载的2.0.2.140一致,版本差异可能导致token格式不兼容。 - 检查权限与Token有效性:通过JWT解码工具检查获取的token,确认包含
https://outlook.office365.com/.default的scope,且应用程序已被授予Exchange Online管理权限(如Exchange Administrator角色)。 - 确认连接URI格式:确保连接URI中的
BasicAuthToOAuthConversion=true参数未被编码错误修改,可直接复制PowerShell中使用的URI到C#代码中,避免手动输入导致的拼写错误。
内容的提问来源于stack exchange,提问作者onyx12
相关产品推荐
相关产品推荐

