我正在尝试使用 AzureAD (仅单声道)身份验证为AD应用程序用户,以便向SharePoint发出请求。
Azure AD应用程序用户基本上需要您提供[clientID,证书路径,证书密码]。
以下代码在Windows上适用:
string siteUrl = "https://xxxxxxx.sharepoint.com";
string clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx";
string domain = "xxxxxxx.onmicrosoft.com";
string certificatePath = "/path/to/xxxxxxx.pfx";
string certificatePassword = "xxxxxxx";
using (var cc = new AuthenticationManager().GetAzureADAppOnlyAuthenticatedContext(siteUrl, clientId, domain, certificatePath, certificatePassword)) {
cc.Load(cc.Web, p => p.Title);
cc.ExecuteQuery();
Console.WriteLine(cc.Web.Title);
};
但是在Mono上,您会收到此错误:
System.Security.Cryptography.CryptographicException: Keyset does not exist
似乎与以下内容有关:
但是这些应该是固定的,但我仍然遇到这些问题。
完整错误堆栈:
System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.RSACryptoServiceProvider.Common (System.Security.Cryptography.CspParameters p) [0x00039] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (System.Int32 dwKeySize, System.Security.Cryptography.CspParameters parameters) [0x0001d] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (System.Security.Cryptography.CspParameters parameters) [0x00000] in <bb7b695b8c6246b3ac1646577aea7650>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.GetCryptoProviderForSha256 (System.Security.Cryptography.RSACryptoServiceProvider rsaProvider) [0x0007e] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.SignWithCertificate (System.String message, System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate) [0x0001b] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate.Sign (System.String message) [0x00007] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.JsonWebToken.Sign (Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate credential) [0x0002b] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.RequestParameters.AddClientKey (Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey clientKey) [0x000b7] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.RequestParameters..ctor (System.String resource, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey clientKey) [0x0001a] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+<SendTokenRequestAsync>d__9.MoveNext () [0x00024] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <bb7b695b8c6246b3ac1646577aea7650>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+<RunAsync>d__0.MoveNext () [0x004f3] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.RunAsyncTask[T] (System.Threading.Tasks.Task`1[TResult] task) [0x00031] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireToken (System.String resource, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate clientCertificate) [0x00014] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at pnp_test_2.Program.Main (System.String[] args) [0x000a8] in <8c5b1bd4cf9047a3868c8cacd6143dd1>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.RSACryptoServiceProvider.Common (System.Security.Cryptography.CspParameters p) [0x00039] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (System.Int32 dwKeySize, System.Security.Cryptography.CspParameters parameters) [0x0001d] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Security.Cryptography.RSACryptoServiceProvider..ctor (System.Security.Cryptography.CspParameters parameters) [0x00000] in <bb7b695b8c6246b3ac1646577aea7650>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.GetCryptoProviderForSha256 (System.Security.Cryptography.RSACryptoServiceProvider rsaProvider) [0x0007e] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.SignWithCertificate (System.String message, System.Security.Cryptography.X509Certificates.X509Certificate2 x509Certificate) [0x0001b] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate.Sign (System.String message) [0x00007] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.JsonWebToken.Sign (Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate credential) [0x0002b] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.RequestParameters.AddClientKey (Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey clientKey) [0x000b7] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.RequestParameters..ctor (System.String resource, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey clientKey) [0x0001a] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+<SendTokenRequestAsync>d__9.MoveNext () [0x00024] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <bb7b695b8c6246b3ac1646577aea7650>:0
at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <bb7b695b8c6246b3ac1646577aea7650>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+<RunAsync>d__0.MoveNext () [0x004f3] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.RunAsyncTask[T] (System.Threading.Tasks.Task`1[TResult] task) [0x00031] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireToken (System.String resource, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate clientCertificate) [0x00014] in <211fb7a0ce9049e5a2768849f2fd6a88>:0
at pnp_test_2.Program.Main (System.String[] args) [0x000a8] in <8c5b1bd4cf9047a3868c8cacd6143dd1>:0
我如何使用Mono上的Azure AD应用专用帐户+ pfx密钥进行身份验证?
答案 0 :(得分:0)
在这里查看我的评论:https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/509
我已经获得了可立即用于SharePoint Online的解决方法:
如果需要,可以删除CorePNP库。但是请不要将OfficeDevPnP.Core.AuthenticationManager用于Linux,因为它将无法工作!但是,该库对于Windows确实非常有用。
添加nuget依赖项:
Microsoft.IdentityModel.Clients.ActiveDirectory
Microsoft.IdentityModel.Tokens
c#代码以正确获取具有身份验证的客户端上下文:
using System;
using System.Text;
using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
using Microsoft.SharePoint.Client;
namespace PnpTest {
class ClientAssertionCertificate : IClientAssertionCertificate {
X509Certificate2 certificate;
public string ClientId { get; private set; }
public string Thumbprint {
get {
return Base64UrlEncoder.Encode(certificate.GetCertHash());
}
}
public ClientAssertionCertificate(string clientId, X509Certificate2 certificate) {
ClientId = clientId;
this.certificate = certificate;
}
public byte[] Sign(string message) {
using (var key = certificate.GetRSAPrivateKey()) {
return key.SignData(Encoding.UTF8.GetBytes(message), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
}
class Program {
static void Main(string[] args) {
string siteUrl = "https://xxxxxxxxxxxxxxx.sharepoint.com";
string clientId = "xxxxxxxxxxxxxxx";
string tenant = "xxxxxxxxxxxxxxx.onmicrosoft.com";
string certificatePath = "resources/xxxxxxxx.pfx";
string certificatePassword = "xxxxxxxx";
var certfile = System.IO.File.OpenRead(certificatePath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var certificate = new X509Certificate2(
certificateBytes,
certificatePassword,
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);
string authority = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/", "https://login.windows.net", tenant);
var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority);
var host = new Uri(siteUrl);
using (var clientContext = new ClientContext(siteUrl)) {
clientContext.ExecutingWebRequest += (sender, webRequestArgs) => {
var arFuture = authContext.AcquireTokenAsync(host.Scheme + "://" + host.Host + "/", clientAssertionCertificate);
var ar = arFuture.Result;
webRequestArgs.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + ar.AccessToken;
};
clientContext.Load(clientContext.Web, p => p.Title);
clientContext.ExecuteQuery();
Console.WriteLine(clientContext.Web.Title);
}
}
}
}