Office 365 API身份验证表格REST API



我正在尝试从Office 365获取日历以在REST API(Web API 2)中使用它们。我已经尝试了很多东西来生成JWT,但是对于每次尝试,我都会收到另一个错误。

我的应用程序已正确注册在Azure AAD中,公共密钥已上传。

我尝试的最后一件事是本文:https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-service-apps-apps-with-opps-with-opps-with-ftice-365-mail-calendar and-contacts-apis-oauth2-client-credential-flow/

在他的示例中,我可以从两种不同的方法中生成JWT,但是我得到了错误:X-MS-DINCNOSTICS:2000003; qualion ="受众索赔价值无效'https://outlook.office365.com'。"; error_category =" invalid_resource"

这是我的代码:

`

string tenantId = ConfigurationManager.AppSettings.Get("ida:TenantId");
            /**
             * use the tenant specific endpoint for requesting the app-only access token
             */
            string tokenIssueEndpoint = "https://login.windows.net/" + tenantId + "/oauth2/authorize";
            string clientId = ConfigurationManager.AppSettings.Get("ida:ClientId");


            /**
             * sign the assertion with the private key
             */
            String certPath = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/cert.pfx");
            X509Certificate2 cert = new X509Certificate2(
                certPath,
                "lol",
                X509KeyStorageFlags.MachineKeySet);
            /**
             * Example building assertion using Json Tokenhandler. 
             * Sort of cheating, but just if someone wonders ... there are always more ways to do something :-)
             */
            Dictionary<string, string> claims = new Dictionary<string, string>()
            {
                { "sub", clientId },
                { "jti", Guid.NewGuid().ToString() },
            };
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
            X509SigningCredentials signingCredentials = new X509SigningCredentials(cert, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);
            JwtSecurityToken selfSignedToken = new JwtSecurityToken(
                clientId,
                tokenIssueEndpoint,
                claims.Select(c => new Claim(c.Key, c.Value)),
                DateTime.UtcNow,
                DateTime.UtcNow.Add(TimeSpan.FromMinutes(15)),
                signingCredentials);
            string signedAssertion = tokenHandler.WriteToken(selfSignedToken);
            //---- End example with Json Tokenhandler... now to the fun part doing it all ourselves ...
            /**
              * Example building assertion from scratch with Crypto APIs
            */
            JObject clientAssertion = new JObject();
            clientAssertion.Add("aud", "https://outlook.office365.com");
            clientAssertion.Add("iss", clientId);
            clientAssertion.Add("sub", clientId);
            clientAssertion.Add("jti", Guid.NewGuid().ToString());
            clientAssertion.Add("scp", "Calendars.Read");
            clientAssertion.Add("nbf", WebConvert.EpocTime(DateTime.UtcNow + TimeSpan.FromMinutes(-5)));
            clientAssertion.Add("exp", WebConvert.EpocTime(DateTime.UtcNow + TimeSpan.FromMinutes(15)));
            string assertionPayload = clientAssertion.ToString(Newtonsoft.Json.Formatting.None);
            X509AsymmetricSecurityKey x509Key = new X509AsymmetricSecurityKey(cert);
            RSACryptoServiceProvider rsa = x509Key.GetAsymmetricAlgorithm(SecurityAlgorithms.RsaSha256Signature, true) as RSACryptoServiceProvider;
            RSACryptoServiceProvider newRsa = GetCryptoProviderForSha256(rsa);
            SHA256Cng sha = new SHA256Cng();
            JObject header = new JObject(new JProperty("alg", "RS256"));
            string thumbprint = WebConvert.Base64UrlEncoded(WebConvert.HexStringToBytes(cert.Thumbprint));
            header.Add(new JProperty("x5t", thumbprint));
            string encodedHeader = WebConvert.Base64UrlEncoded(header.ToString());
            string encodedPayload = WebConvert.Base64UrlEncoded(assertionPayload);
            string signingInput = String.Concat(encodedHeader, ".", encodedPayload);
            byte[] signature = newRsa.SignData(Encoding.UTF8.GetBytes(signingInput), sha);
            signedAssertion = string.Format("{0}.{1}.{2}",
                encodedHeader,
                encodedPayload,
                WebConvert.Base64UrlEncoded(signature));

`

我的JWT看起来像这样:

`

{
 alg: "RS256",
 x5t: "8WkmVEiCU9mHkshRp65lyowGOAk"
}.
{
 aud: "https://outlook.office365.com",
 iss: "clientId",
 sub: "clientId",
 jti: "38a34d8a-0764-434f-8e1d-c5774cf37007",
 scp: "Calendars.Read",
 nbf: 1512977093,
 exp: 1512978293
}

`

我将这个令牌放在"携带者"字符串之后的授权标题中。

有什么想法可以解决此类问题?我想我需要一个外部观点:)

谢谢

您不生成JWT,Azure AD做到了。

您将使用证书获取访问令牌。从您链接的文章中借来的示例:

string authority = appConfig.AuthorizationUri.Replace("common", tenantId);
AuthenticationContext authenticationContext = new AuthenticationContext(
               authority,
               false);
string certfile = Server.MapPath(appConfig.ClientCertificatePfx);
X509Certificate2 cert = new X509Certificate2(
    certfile,
    appConfig.ClientCertificatePfxPassword, // password for the cert file containing private key
    X509KeyStorageFlags.MachineKeySet);
ClientAssertionCertificate cac = new ClientAssertionCertificate(
    appConfig.ClientId, cert);
var authenticationResult = await authenticationContext.AcquireTokenAsync(
     resource,   // always https://outlook.office365.com for Mail, Calendar, Contacts API
     cac);
return authenticationResult.AccessToken;

然后可以将结果访问令牌附加到API请求。

它不起作用的原因是Outlook API不认为您是有效的令牌发行人。它只会接受与Azure AD的私钥签名的令牌。您显然没有。

您生成的密钥对的私钥只能用于将您的应用程序验证到Azure AD。

谢谢Juunas!

这是工作代码:

var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.microsoftonline.com/tenantId");
            string tenantId = ConfigurationManager.AppSettings.Get("ida:TenantId");
            string clientId = ConfigurationManager.AppSettings.Get("ida:ClientId");
            String certPath = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/cert.pfx");
            X509Certificate2 cert = new X509Certificate2(
                certPath,
                "keyPwd",
                X509KeyStorageFlags.MachineKeySet);
            ClientAssertionCertificate cac = new ClientAssertionCertificate(clientId, cert);
            var result = (AuthenticationResult)authContext
                .AcquireTokenAsync("https://outlook.office.com", cac)
                .Result;
            var token = result.AccessToken;
            return token;

仅使用应用程序的其他必需步骤,您必须在AAD应用程序设置中使用授予权限按钮。

最新更新